2021-04-10 22:13:12 +05:30
|
|
|
use fixedbitset::FixedBitSet;
|
|
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
|
|
|
|
use crate::io_engine::IoEngine;
|
2021-04-16 15:22:54 +05:30
|
|
|
use crate::pdata::array::{self, ArrayBlock};
|
2021-04-10 22:13:12 +05:30
|
|
|
use crate::pdata::array_walker::{ArrayVisitor, ArrayWalker};
|
2021-04-21 21:06:10 +05:30
|
|
|
use crate::pdata::space_map::*;
|
2021-04-10 22:13:12 +05:30
|
|
|
|
2021-04-20 13:37:25 +05:30
|
|
|
pub struct CheckedBitSet {
|
|
|
|
bits: FixedBitSet,
|
2021-04-10 22:13:12 +05:30
|
|
|
}
|
|
|
|
|
2021-04-20 13:37:25 +05:30
|
|
|
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))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct BitsetVisitor {
|
|
|
|
nr_entries: usize,
|
|
|
|
bits: Mutex<CheckedBitSet>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl BitsetVisitor {
|
|
|
|
pub fn new(nr_entries: usize) -> Self {
|
2021-04-10 22:13:12 +05:30
|
|
|
BitsetVisitor {
|
2021-04-20 13:37:25 +05:30
|
|
|
nr_entries,
|
|
|
|
bits: Mutex::new(CheckedBitSet::with_capacity(nr_entries)),
|
2021-04-10 22:13:12 +05:30
|
|
|
}
|
|
|
|
}
|
2021-04-20 13:37:25 +05:30
|
|
|
|
|
|
|
pub fn get_bitset(self) -> CheckedBitSet {
|
|
|
|
self.bits.into_inner().unwrap()
|
|
|
|
}
|
2021-04-10 22:13:12 +05:30
|
|
|
}
|
|
|
|
|
2021-04-20 13:37:25 +05:30
|
|
|
impl ArrayVisitor<u64> for BitsetVisitor {
|
2021-04-16 15:22:54 +05:30
|
|
|
fn visit(&self, index: u64, b: ArrayBlock<u64>) -> array::Result<()> {
|
|
|
|
let mut begin = index as usize * (b.header.max_entries as usize) << 6;
|
|
|
|
|
|
|
|
for i in 0..b.header.nr_entries as usize {
|
|
|
|
if begin > self.nr_entries as usize {
|
|
|
|
return Err(array::value_err("bitset size exceeds expectation".to_string()));
|
|
|
|
}
|
|
|
|
|
|
|
|
let end: usize = std::cmp::min(begin + 64, self.nr_entries as usize);
|
|
|
|
let mut mask = 1;
|
|
|
|
let bits = b.values[i];
|
2021-04-10 22:13:12 +05:30
|
|
|
|
2021-04-16 15:22:54 +05:30
|
|
|
for bi in begin..end {
|
|
|
|
self.bits.lock().unwrap().set(bi, bits & mask != 0);
|
|
|
|
mask <<= 1;
|
|
|
|
}
|
|
|
|
begin += 64;
|
2021-04-10 22:13:12 +05:30
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: multi-threaded is possible
|
|
|
|
pub fn read_bitset(
|
|
|
|
engine: Arc<dyn IoEngine + Send + Sync>,
|
|
|
|
root: u64,
|
2021-04-20 13:37:25 +05:30
|
|
|
nr_entries: usize,
|
2021-04-10 22:13:12 +05:30
|
|
|
ignore_none_fatal: bool,
|
2021-04-20 13:37:25 +05:30
|
|
|
)-> (CheckedBitSet, Option<array::ArrayError>) {
|
2021-04-21 21:06:10 +05:30
|
|
|
let w = ArrayWalker::new(engine, ignore_none_fatal);
|
2021-04-20 13:37:25 +05:30
|
|
|
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);
|
2021-04-10 22:13:12 +05:30
|
|
|
}
|
2021-04-21 21:06:10 +05:30
|
|
|
|
|
|
|
// TODO: multi-threaded is possible
|
|
|
|
pub fn read_bitset_with_sm(
|
|
|
|
engine: Arc<dyn IoEngine + Send + Sync>,
|
|
|
|
root: u64,
|
|
|
|
nr_entries: usize,
|
|
|
|
sm: Arc<Mutex<dyn SpaceMap + Send + Sync>>,
|
|
|
|
ignore_none_fatal: bool,
|
|
|
|
)-> array::Result<(CheckedBitSet, Option<array::ArrayError>)> {
|
|
|
|
let w = ArrayWalker::new_with_sm(engine, sm, ignore_none_fatal)?;
|
|
|
|
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 Ok((v.get_bitset(), e));
|
|
|
|
}
|