2020-12-09 16:10:06 +05:30
|
|
|
use std::sync::Arc;
|
|
|
|
|
2021-04-13 11:09:14 +05:30
|
|
|
use crate::checksum;
|
2020-12-09 16:10:06 +05:30
|
|
|
use crate::io_engine::*;
|
2021-04-13 11:09:14 +05:30
|
|
|
use crate::pdata::array::{self, *};
|
|
|
|
use crate::pdata::btree::{self, *};
|
2020-12-09 16:10:06 +05:30
|
|
|
use crate::pdata::btree_walker::*;
|
|
|
|
use crate::pdata::unpack::*;
|
|
|
|
|
|
|
|
//------------------------------------------
|
|
|
|
|
|
|
|
pub struct ArrayWalker {
|
|
|
|
engine: Arc<dyn IoEngine + Send + Sync>,
|
2021-03-03 15:57:57 +05:30
|
|
|
ignore_non_fatal: bool,
|
2020-12-09 16:10:06 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: define another Result type for array visiting?
|
2021-03-04 16:43:08 +05:30
|
|
|
pub trait ArrayVisitor<V: Unpack> {
|
2021-04-13 11:09:14 +05:30
|
|
|
fn visit(&self, index: u64, v: V) -> array::Result<()>;
|
2020-12-09 16:10:06 +05:30
|
|
|
}
|
|
|
|
|
2021-03-04 16:43:08 +05:30
|
|
|
struct BlockValueVisitor<'a, V> {
|
2020-12-09 16:10:06 +05:30
|
|
|
engine: Arc<dyn IoEngine + Send + Sync>,
|
2021-04-13 11:09:14 +05:30
|
|
|
array_visitor: &'a mut dyn ArrayVisitor<V>,
|
2020-12-09 16:10:06 +05:30
|
|
|
}
|
|
|
|
|
2021-03-04 16:43:08 +05:30
|
|
|
impl<'a, V: Unpack + Copy> BlockValueVisitor<'a, V> {
|
2021-03-03 15:57:57 +05:30
|
|
|
pub fn new(
|
2020-12-09 16:10:06 +05:30
|
|
|
e: Arc<dyn IoEngine + Send + Sync>,
|
2021-03-04 16:43:08 +05:30
|
|
|
v: &'a mut dyn ArrayVisitor<V>,
|
|
|
|
) -> BlockValueVisitor<'a, V> {
|
2020-12-09 16:10:06 +05:30
|
|
|
BlockValueVisitor {
|
|
|
|
engine: e,
|
2021-04-13 11:09:14 +05:30
|
|
|
array_visitor: v,
|
2020-12-09 16:10:06 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-13 11:09:14 +05:30
|
|
|
pub fn visit_array_block(&self, index: u64, array_block: ArrayBlock<V>) -> array::Result<()>{
|
|
|
|
let mut errs: Vec<ArrayError> = Vec::new();
|
|
|
|
|
2021-03-03 15:57:57 +05:30
|
|
|
let begin = index * array_block.header.max_entries as u64;
|
2020-12-09 16:10:06 +05:30
|
|
|
for i in 0..array_block.header.nr_entries {
|
2021-04-13 11:09:14 +05:30
|
|
|
if let Err(e) = self.array_visitor.visit(begin + i as u64, array_block.values[i as usize]) {
|
|
|
|
errs.push(e); // TODO: add path or keys context?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: duplicate to BTreeWalker::build_aggregrate()
|
|
|
|
match errs.len() {
|
|
|
|
0 => Ok(()),
|
|
|
|
1 => {
|
|
|
|
let e = errs[0].clone();
|
|
|
|
Err(e)
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
let e = array::aggregate_error(errs);
|
|
|
|
Err(e)
|
|
|
|
}
|
2020-12-09 16:10:06 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-04 16:43:08 +05:30
|
|
|
impl<'a, V: Unpack + Copy> NodeVisitor<u64> for BlockValueVisitor<'a, V> {
|
2021-04-13 11:09:14 +05:30
|
|
|
// FIXME: wrap ArrayError into BTreeError, rather than mapping to value_err?
|
2020-12-09 16:10:06 +05:30
|
|
|
fn visit(
|
|
|
|
&self,
|
2021-02-24 17:51:10 +05:30
|
|
|
path: &[u64],
|
2020-12-09 16:10:06 +05:30
|
|
|
_kr: &KeyRange,
|
|
|
|
_h: &NodeHeader,
|
|
|
|
keys: &[u64],
|
2021-03-03 15:57:57 +05:30
|
|
|
values: &[u64],
|
2021-04-13 11:09:14 +05:30
|
|
|
) -> btree::Result<()> {
|
|
|
|
let mut path = path.to_vec();
|
|
|
|
let mut errs: Vec<BTreeError> = Vec::new();
|
|
|
|
|
2021-03-03 15:57:57 +05:30
|
|
|
for (n, index) in keys.iter().enumerate() {
|
2021-04-13 11:09:14 +05:30
|
|
|
let b = self.engine.read(values[n]).map_err(|_| io_err(&path))?;
|
|
|
|
|
|
|
|
// FIXME: move to unpack_array_block?
|
|
|
|
let bt = checksum::metadata_block_type(b.get_data());
|
|
|
|
if bt != checksum::BT::ARRAY {
|
|
|
|
errs.push(btree::value_err(
|
|
|
|
format!("checksum failed for array block {}, {:?}", b.loc, bt)
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
path.push(values[n]);
|
|
|
|
match unpack_array_block::<V>(&path, b.get_data()) {
|
|
|
|
Ok(array_block) => {
|
|
|
|
if let Err(e) = self.visit_array_block(*index, array_block) {
|
|
|
|
errs.push(btree::value_err(format!("{}", e)));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Err(e) => {
|
|
|
|
errs.push(btree::value_err(format!("{}", e)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
path.pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: duplicate to BTreeWalker::build_aggregrate()
|
|
|
|
match errs.len() {
|
|
|
|
0 => Ok(()),
|
|
|
|
1 => {
|
|
|
|
let e = errs[0].clone();
|
|
|
|
Err(e)
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
let e = btree::aggregate_error(errs);
|
|
|
|
Err(e)
|
|
|
|
}
|
2020-12-09 16:10:06 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-13 11:09:14 +05:30
|
|
|
fn visit_again(&self, _path: &[u64], _b: u64) -> btree::Result<()> {
|
2020-12-09 16:10:06 +05:30
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-04-13 11:09:14 +05:30
|
|
|
fn end_walk(&self) -> btree::Result<()> {
|
2020-12-09 16:10:06 +05:30
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ArrayWalker {
|
|
|
|
pub fn new(engine: Arc<dyn IoEngine + Send + Sync>, ignore_non_fatal: bool) -> ArrayWalker {
|
|
|
|
let r: ArrayWalker = ArrayWalker {
|
|
|
|
engine,
|
|
|
|
ignore_non_fatal,
|
|
|
|
};
|
|
|
|
r
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: redefine the Result type for array visiting?
|
2021-04-13 11:09:14 +05:30
|
|
|
pub fn walk<V>(&self, visitor: &mut dyn ArrayVisitor<V>, root: u64) -> array::Result<()>
|
2020-12-09 16:10:06 +05:30
|
|
|
where
|
2021-03-03 15:57:57 +05:30
|
|
|
V: Unpack + Copy,
|
2020-12-09 16:10:06 +05:30
|
|
|
{
|
|
|
|
let w = BTreeWalker::new(self.engine.clone(), self.ignore_non_fatal);
|
2021-03-03 15:57:57 +05:30
|
|
|
let mut path = Vec::new();
|
2020-12-09 16:10:06 +05:30
|
|
|
path.push(0);
|
|
|
|
let v = BlockValueVisitor::<V>::new(self.engine.clone(), visitor);
|
2021-04-13 11:09:14 +05:30
|
|
|
w.walk(&mut path, &v, root).map_err(|e| ArrayError::BTreeError(e))
|
2020-12-09 16:10:06 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------
|