use std::io;
use std::ops::ControlFlow;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use super::{MemoryStore, ObjectStore, WritableObjectStore};
use crate::error::{Error, Result};
use crate::objects::{HashAlgo, Object, ObjectId, ObjectInfo, ObjectKind};
use crate::odb::WriteOptions;
#[derive(Debug)]
pub(crate) struct FlakyStore {
inner: MemoryStore,
fail_contains: AtomicBool,
fail_reads: AtomicBool,
}
impl FlakyStore {
pub(crate) fn new() -> Arc<Self> {
Arc::new(Self {
inner: MemoryStore::new(HashAlgo::Sha1),
fail_contains: AtomicBool::new(false),
fail_reads: AtomicBool::new(false),
})
}
pub(crate) fn fail_contains(&self, fail: bool) {
self.fail_contains.store(fail, Ordering::Relaxed);
}
pub(crate) fn fail_all(&self, fail: bool) {
self.fail_contains(fail);
self.fail_reads.store(fail, Ordering::Relaxed);
}
fn check(flag: &AtomicBool) -> Result<()> {
if flag.load(Ordering::Relaxed) {
return Err(Error::Io(io::Error::new(
io::ErrorKind::ConnectionReset,
"backend down",
)));
}
Ok(())
}
}
pub(crate) fn is_injected(err: &Error) -> bool {
matches!(err, Error::Io(e) if e.kind() == io::ErrorKind::ConnectionReset)
}
impl ObjectStore for FlakyStore {
fn hash_algo(&self) -> HashAlgo {
HashAlgo::Sha1
}
fn read(&self, oid: &ObjectId) -> Result<Option<Object>> {
Self::check(&self.fail_reads)?;
self.inner.read(oid)
}
fn read_info(&self, oid: &ObjectId) -> Result<Option<ObjectInfo>> {
Self::check(&self.fail_reads)?;
self.inner.read_info(oid)
}
fn contains(&self, oid: &ObjectId) -> Result<bool> {
Self::check(&self.fail_contains)?;
self.inner.contains(oid)
}
fn for_each_object(&self, f: &mut dyn FnMut(&ObjectId) -> ControlFlow<()>) -> Result<()> {
Self::check(&self.fail_reads)?;
self.inner.for_each_object(f)
}
}
impl WritableObjectStore for FlakyStore {
fn write(&self, kind: ObjectKind, data: &[u8], options: WriteOptions) -> Result<ObjectId> {
Self::check(&self.fail_reads)?;
self.inner.write(kind, data, options)
}
fn freshen(&self, oid: &ObjectId) -> Result<bool> {
Self::check(&self.fail_reads)?;
self.inner.freshen(oid)
}
}