[cache_check (rust)] Add more checks
- Report errors - Support reading partially broken bitset - The output is a bitmap of 2-bit entries, indicating availability of bits
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use nom::{multi::count, number::complete::*, IResult};
|
||||
use std::fmt;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::checksum;
|
||||
@@ -52,25 +53,43 @@ pub struct ArrayBlock<V: Unpack> {
|
||||
|
||||
#[derive(Error, Clone, Debug)]
|
||||
pub enum ArrayError {
|
||||
#[error("io_error")]
|
||||
//#[error("io_error")]
|
||||
IoError,
|
||||
|
||||
#[error("block error: {0}")]
|
||||
//#[error("block error: {0}")]
|
||||
BlockError(String),
|
||||
|
||||
#[error("value error: {0}")]
|
||||
//#[error("value error: {0}")]
|
||||
ValueError(String),
|
||||
|
||||
#[error("aggregate: {0:?}")]
|
||||
//#[error("aggregate: {0:?}")]
|
||||
Aggregate(Vec<ArrayError>),
|
||||
|
||||
#[error("{0:?}, {1}")]
|
||||
//#[error("{0:?}, {1}")]
|
||||
Path(Vec<u64>, Box<ArrayError>),
|
||||
|
||||
#[error(transparent)]
|
||||
BTreeError(#[from] btree::BTreeError),
|
||||
}
|
||||
|
||||
impl fmt::Display for ArrayError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
ArrayError::IoError => write!(f, "io error"),
|
||||
ArrayError::BlockError(msg) => write!(f, "block error: {}", msg),
|
||||
ArrayError::ValueError(msg) => write!(f, "value error: {}", msg),
|
||||
ArrayError::Aggregate(errs) => {
|
||||
for e in errs {
|
||||
write!(f, "{}", e)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
ArrayError::Path(path, e) => write!(f, "{} {}", e, btree::encode_node_path(path)),
|
||||
ArrayError::BTreeError(e) => write!(f, "{}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn array_block_err(path: &[u64], msg: &str) -> ArrayError {
|
||||
ArrayError::Path(
|
||||
path.to_vec(),
|
||||
|
||||
@@ -5,21 +5,49 @@ use crate::io_engine::IoEngine;
|
||||
use crate::pdata::array::{self, ArrayBlock};
|
||||
use crate::pdata::array_walker::{ArrayVisitor, ArrayWalker};
|
||||
|
||||
struct BitsetVisitor<'a> {
|
||||
nr_entries: u64,
|
||||
bits: Mutex<&'a mut FixedBitSet>,
|
||||
pub struct CheckedBitSet {
|
||||
bits: FixedBitSet,
|
||||
}
|
||||
|
||||
impl<'a> BitsetVisitor<'a> {
|
||||
pub fn new(bitset: &'a mut FixedBitSet) -> Self {
|
||||
BitsetVisitor {
|
||||
nr_entries: bitset.len() as u64,
|
||||
bits: Mutex::new(bitset),
|
||||
impl CheckedBitSet {
|
||||
pub fn with_capacity(bits: usize) -> CheckedBitSet {
|
||||
CheckedBitSet {
|
||||
bits: FixedBitSet::with_capacity(bits << 1),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set(&mut self, bit: usize, enabled: bool) {
|
||||
self.bits.set(bit << 1, true);
|
||||
self.bits.set((bit << 1) + 1, enabled);
|
||||
}
|
||||
|
||||
pub fn contains(&self, bit: usize) -> Option<bool> {
|
||||
if !self.bits.contains(bit << 1) {
|
||||
return None;
|
||||
}
|
||||
Some(self.bits.contains((bit << 1) + 1))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ArrayVisitor<u64> for BitsetVisitor<'a> {
|
||||
struct BitsetVisitor {
|
||||
nr_entries: usize,
|
||||
bits: Mutex<CheckedBitSet>,
|
||||
}
|
||||
|
||||
impl BitsetVisitor {
|
||||
pub fn new(nr_entries: usize) -> Self {
|
||||
BitsetVisitor {
|
||||
nr_entries,
|
||||
bits: Mutex::new(CheckedBitSet::with_capacity(nr_entries)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_bitset(self) -> CheckedBitSet {
|
||||
self.bits.into_inner().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl ArrayVisitor<u64> for BitsetVisitor {
|
||||
fn visit(&self, index: u64, b: ArrayBlock<u64>) -> array::Result<()> {
|
||||
let mut begin = index as usize * (b.header.max_entries as usize) << 6;
|
||||
|
||||
@@ -46,10 +74,15 @@ impl<'a> ArrayVisitor<u64> for BitsetVisitor<'a> {
|
||||
pub fn read_bitset(
|
||||
engine: Arc<dyn IoEngine + Send + Sync>,
|
||||
root: u64,
|
||||
nr_entries: usize,
|
||||
ignore_none_fatal: bool,
|
||||
bitset: &mut FixedBitSet,
|
||||
)-> array::Result<()> {
|
||||
)-> (CheckedBitSet, Option<array::ArrayError>) {
|
||||
let w = ArrayWalker::new(engine.clone(), ignore_none_fatal);
|
||||
let mut v = BitsetVisitor::new(bitset);
|
||||
w.walk(&mut v, root)
|
||||
let mut v = BitsetVisitor::new(nr_entries);
|
||||
let err = w.walk(&mut v, root);
|
||||
let e = match err {
|
||||
Ok(()) => None,
|
||||
Err(e) => Some(e),
|
||||
};
|
||||
return (v.get_bitset(), e);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user