mirror of
https://github.com/deuxfleurs-org/garage.git
synced 2026-08-22 10:46:38 +00:00
Implement block list-errors and block info
This commit is contained in:
@@ -90,6 +90,15 @@ pub struct BlockManager {
|
||||
tx_scrub_command: mpsc::Sender<ScrubWorkerCommand>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct BlockResyncErrorInfo {
|
||||
pub hash: Hash,
|
||||
pub refcount: u64,
|
||||
pub error_count: u64,
|
||||
pub last_try: u64,
|
||||
pub next_try: u64,
|
||||
}
|
||||
|
||||
// This custom struct contains functions that must only be ran
|
||||
// when the lock is held. We ensure that it is the case by storing
|
||||
// it INSIDE a Mutex.
|
||||
@@ -314,6 +323,31 @@ impl BlockManager {
|
||||
let _ = self.tx_scrub_command.send(cmd).await;
|
||||
}
|
||||
|
||||
/// Get the reference count of a block
|
||||
pub fn get_block_rc(&self, hash: &Hash) -> Result<u64, Error> {
|
||||
Ok(self.rc.get_block_rc(hash)?.as_u64())
|
||||
}
|
||||
|
||||
/// List all resync errors
|
||||
pub fn list_resync_errors(&self) -> Result<Vec<BlockResyncErrorInfo>, Error> {
|
||||
let mut blocks = Vec::with_capacity(self.resync.errors.len());
|
||||
for ent in self.resync.errors.iter()? {
|
||||
let (hash, cnt) = ent?;
|
||||
let cnt = ErrorCounter::decode(&cnt);
|
||||
blocks.push(BlockResyncErrorInfo {
|
||||
hash: Hash::try_from(&hash).unwrap(),
|
||||
refcount: 0,
|
||||
error_count: cnt.errors,
|
||||
last_try: cnt.last_try,
|
||||
next_try: cnt.next_try(),
|
||||
});
|
||||
}
|
||||
for block in blocks.iter_mut() {
|
||||
block.refcount = self.get_block_rc(&block.hash)?;
|
||||
}
|
||||
Ok(blocks)
|
||||
}
|
||||
|
||||
//// ----- Managing the reference counter ----
|
||||
|
||||
/// Increment the number of time a block is used, putting it to resynchronization if it is
|
||||
|
||||
@@ -169,4 +169,11 @@ impl RcEntry {
|
||||
pub(crate) fn is_needed(&self) -> bool {
|
||||
!self.is_deletable()
|
||||
}
|
||||
|
||||
pub(crate) fn as_u64(&self) -> u64 {
|
||||
match self {
|
||||
RcEntry::Present { count } => *count,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-5
@@ -540,9 +540,9 @@ impl Worker for ResyncWorker {
|
||||
/// and the time of the last try.
|
||||
/// Used to implement exponential backoff.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
struct ErrorCounter {
|
||||
errors: u64,
|
||||
last_try: u64,
|
||||
pub(crate) struct ErrorCounter {
|
||||
pub(crate) errors: u64,
|
||||
pub(crate) last_try: u64,
|
||||
}
|
||||
|
||||
impl ErrorCounter {
|
||||
@@ -553,12 +553,13 @@ impl ErrorCounter {
|
||||
}
|
||||
}
|
||||
|
||||
fn decode(data: &[u8]) -> Self {
|
||||
pub(crate) fn decode(data: &[u8]) -> Self {
|
||||
Self {
|
||||
errors: u64::from_be_bytes(data[0..8].try_into().unwrap()),
|
||||
last_try: u64::from_be_bytes(data[8..16].try_into().unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
[
|
||||
u64::to_be_bytes(self.errors),
|
||||
@@ -578,7 +579,8 @@ impl ErrorCounter {
|
||||
(RESYNC_RETRY_DELAY.as_millis() as u64)
|
||||
<< std::cmp::min(self.errors - 1, RESYNC_RETRY_DELAY_MAX_BACKOFF_POWER)
|
||||
}
|
||||
fn next_try(&self) -> u64 {
|
||||
|
||||
pub(crate) fn next_try(&self) -> u64 {
|
||||
self.last_try + self.delay_msec()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user