diff options
author | Alex Auvolat <alex@adnab.me> | 2024-03-19 11:04:20 +0100 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2024-03-19 16:20:22 +0100 |
commit | dc0b78cdb88e9cbfd7dc1a2ee0b15333939be549 (patch) | |
tree | 20d18c4d8676b455513dd84d560e1748df6fd12b /src/util | |
parent | 0038ca8a78f147b9c0ec07ef0121773aaf110dc9 (diff) | |
download | garage-dc0b78cdb88e9cbfd7dc1a2ee0b15333939be549.tar.gz garage-dc0b78cdb88e9cbfd7dc1a2ee0b15333939be549.zip |
[block-ref-repair] Block refcount recalculation and repair
- We always recalculate the reference count of a block before deleting
it locally, to make sure that it is indeed zero.
- If we had to fetch a remote block but we were not able to get it,
check that refcount is indeed > 0.
- Repair procedure that checks everything
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/data.rs | 35 | ||||
-rw-r--r-- | src/util/error.rs | 3 |
2 files changed, 38 insertions, 0 deletions
diff --git a/src/util/data.rs b/src/util/data.rs index 2579fd1b..1fe7dfe0 100644 --- a/src/util/data.rs +++ b/src/util/data.rs @@ -83,6 +83,19 @@ impl FixedBytes32 { ret.copy_from_slice(by); Some(Self(ret)) } + /// Return the next hash + pub fn increment(&self) -> Option<Self> { + let mut ret = *self; + for byte in ret.0.iter_mut().rev() { + if *byte == u8::MAX { + *byte = 0; + } else { + *byte = *byte + 1; + return Some(ret); + } + } + return None; + } } impl From<garage_net::NodeID> for FixedBytes32 { @@ -140,3 +153,25 @@ pub fn fasthash(data: &[u8]) -> FastHash { pub fn gen_uuid() -> Uuid { rand::thread_rng().gen::<[u8; 32]>().into() } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_increment() { + let zero: FixedBytes32 = [0u8; 32].into(); + let mut one: FixedBytes32 = [0u8; 32].into(); + one.0[31] = 1; + let max: FixedBytes32 = [0xFFu8; 32].into(); + assert_eq!(zero.increment(), Some(one)); + assert_eq!(max.increment(), None); + + let mut test: FixedBytes32 = [0u8; 32].into(); + let i = 0x198DF97209F8FFFFu64; + test.0[24..32].copy_from_slice(&u64::to_be_bytes(i)); + let mut test2: FixedBytes32 = [0u8; 32].into(); + test2.0[24..32].copy_from_slice(&u64::to_be_bytes(i + 1)); + assert_eq!(test.increment(), Some(test2)); + } +} diff --git a/src/util/error.rs b/src/util/error.rs index da9eda10..75fd3f9c 100644 --- a/src/util/error.rs +++ b/src/util/error.rs @@ -70,6 +70,9 @@ pub enum Error { #[error(display = "Corrupt data: does not match hash {:?}", _0)] CorruptData(Hash), + #[error(display = "Missing block {:?}: no node returned a valid block", _0)] + MissingBlock(Hash), + #[error(display = "{}", _0)] Message(String), } |