extend coverage map
This commit is contained in:
parent
42a2aef527
commit
94880f311e
106
src/lib.rs
106
src/lib.rs
@ -901,12 +901,6 @@ mod tests {
|
||||
coverage.set_allocated(next.range());
|
||||
next = snaphot.read(next).next;
|
||||
}
|
||||
|
||||
for SnapshotAndFreeList { to_free, .. } in &db.snapshots {
|
||||
for &range in to_free {
|
||||
coverage.set_range(range, CoverageKind::Free);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
snapshots.push_back(db.create_reader().state.get());
|
||||
@ -953,11 +947,14 @@ mod tests {
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy)]
|
||||
#[rustfmt::skip]
|
||||
enum CoverageKind {
|
||||
Unaccounted = 0b00,
|
||||
Allocated = 0b01,
|
||||
Free = 0b10,
|
||||
Metadata = 0b11,
|
||||
Unaccounted = 0b000,
|
||||
Allocated = 0b001,
|
||||
Free = 0b010,
|
||||
Retired = 0b011,
|
||||
SlabMetadata = 0b100,
|
||||
FileMetadata = 0b101,
|
||||
}
|
||||
|
||||
impl CoverageKind {
|
||||
@ -966,31 +963,42 @@ mod tests {
|
||||
CoverageKind::Unaccounted => "31",
|
||||
CoverageKind::Allocated => "32",
|
||||
CoverageKind::Free => "34",
|
||||
CoverageKind::Metadata => "35",
|
||||
CoverageKind::Retired => "36",
|
||||
CoverageKind::SlabMetadata => "35",
|
||||
CoverageKind::FileMetadata => "93",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CoverageKind {
|
||||
fn from_bits(a: bool, b: bool) -> Self {
|
||||
let res = match (a, b) {
|
||||
(false, false) => Self::Unaccounted,
|
||||
(false, true) => Self::Allocated,
|
||||
(true, false) => Self::Free,
|
||||
(true, true) => Self::Metadata,
|
||||
#[rustfmt::skip]
|
||||
fn from_bits(a: bool, b: bool, c: bool) -> Self {
|
||||
let res = match (a, b, c) {
|
||||
(false, false, false) => Self::Unaccounted,
|
||||
(false, false, true) => Self::Allocated,
|
||||
(false, true, false) => Self::Free,
|
||||
(false, true, true) => Self::Retired,
|
||||
( true, false, false) => Self::SlabMetadata,
|
||||
( true, false, true) => Self::FileMetadata,
|
||||
_ => panic!(),
|
||||
};
|
||||
assert_eq!(res as u8, ((a as u8) << 1) + b as u8);
|
||||
assert_eq!(res as u8, ((a as u8) << 2) + ((b as u8) << 1) + c as u8);
|
||||
res
|
||||
}
|
||||
|
||||
fn to_bits(self) -> (bool, bool) {
|
||||
(self as u8 & 0b10 != 0, self as u8 & 0b01 != 0)
|
||||
fn to_bits(self) -> (bool, bool, bool) {
|
||||
(
|
||||
self as u8 & 0b100 != 0,
|
||||
self as u8 & 0b010 != 0,
|
||||
self as u8 & 0b001 != 0,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct CoverageMap {
|
||||
data_0: Vec<u8>,
|
||||
data_1: Vec<u8>,
|
||||
data_2: Vec<u8>,
|
||||
empty_bits: u8,
|
||||
}
|
||||
|
||||
@ -1000,6 +1008,7 @@ mod tests {
|
||||
Self {
|
||||
data_0: vec![0; bits],
|
||||
data_1: vec![0; bits],
|
||||
data_2: vec![0; bits],
|
||||
empty_bits: (8 - len % 8) as u8,
|
||||
}
|
||||
}
|
||||
@ -1010,20 +1019,21 @@ mod tests {
|
||||
let i_bit = i % 8;
|
||||
let mask = 1 << i_bit;
|
||||
|
||||
let (set_0, set_1) = kind.to_bits();
|
||||
let (set_0, set_1, set_2) = kind.to_bits();
|
||||
|
||||
if i_byte >= self.data_0.len() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let is_set = self.data_0[i_byte] & mask != 0 || self.data_1[i_byte] & mask != 0;
|
||||
let byte = self.data_0[i_byte] | self.data_1[i_byte] | self.data_2[i_byte];
|
||||
|
||||
if is_set {
|
||||
if byte & mask != 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.data_0[i_byte] |= mask * set_0 as u8;
|
||||
self.data_1[i_byte] |= mask * set_1 as u8;
|
||||
self.data_2[i_byte] |= mask * set_2 as u8;
|
||||
|
||||
true
|
||||
}
|
||||
@ -1046,8 +1056,14 @@ mod tests {
|
||||
|
||||
fn all_covered(&self) -> bool {
|
||||
let len = self.data_0.len();
|
||||
for (i, (&byte_0, &byte_1)) in self.data_0.iter().zip(self.data_1.iter()).enumerate() {
|
||||
let byte = byte_0 | byte_1;
|
||||
for (i, ((&byte_0, &byte_1), &byte_2)) in self
|
||||
.data_0
|
||||
.iter()
|
||||
.zip(self.data_1.iter())
|
||||
.zip(self.data_2.iter())
|
||||
.enumerate()
|
||||
{
|
||||
let byte = byte_0 | byte_1 | byte_2;
|
||||
if i == len - 1 {
|
||||
if byte != u8::MAX.overflowing_shl(self.empty_bits as u32).0 {
|
||||
return false;
|
||||
@ -1069,22 +1085,34 @@ mod tests {
|
||||
let mut res = String::new();
|
||||
|
||||
let mut prev = "";
|
||||
for (i, (&byte_0, &byte_1)) in self.data_0.iter().zip(self.data_1.iter()).enumerate() {
|
||||
let byte = byte_0 | byte_1;
|
||||
for (i, ((&byte_0, &byte_1), &byte_2)) in self
|
||||
.data_0
|
||||
.iter()
|
||||
.zip(self.data_1.iter())
|
||||
.zip(self.data_2.iter())
|
||||
.enumerate()
|
||||
{
|
||||
let byte = byte_0 | byte_1 | byte_2;
|
||||
|
||||
fn all_equal(bits: u8) -> bool {
|
||||
bits == 0 || bits == u8::MAX
|
||||
}
|
||||
|
||||
let kind = if all_equal(byte_0) && all_equal(byte_1) {
|
||||
Some(CoverageKind::from_bits(byte_0 & 1 == 1, byte_1 & 1 == 1))
|
||||
let kind = if all_equal(byte_0) && all_equal(byte_1) && all_equal(byte_2) {
|
||||
Some(CoverageKind::from_bits(
|
||||
byte_0 & 1 == 1,
|
||||
byte_1 & 1 == 1,
|
||||
byte_2 & 1 == 1,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if i != 0 {
|
||||
if i as u64 % (PAGE_SIZE / 8 / 8) == 0 {
|
||||
Self::set_color(&mut res, "");
|
||||
res.push('\n');
|
||||
Self::set_color(&mut res, prev);
|
||||
}
|
||||
if i as u64 % (PAGE_SIZE / 8) == 0 {
|
||||
Self::set_color(&mut res, "");
|
||||
@ -1095,7 +1123,6 @@ mod tests {
|
||||
}
|
||||
|
||||
let color = kind.map(CoverageKind::color).unwrap_or("33");
|
||||
|
||||
if color != prev {
|
||||
Self::set_color(&mut res, color);
|
||||
}
|
||||
@ -1122,7 +1149,9 @@ mod tests {
|
||||
fn coverage_map_works() {
|
||||
let mut coverage = CoverageMap::new(40);
|
||||
assert!(!coverage.all_covered());
|
||||
assert!(coverage.try_set_range(RawFilePointer::null().range(20), CoverageKind::Metadata));
|
||||
assert!(
|
||||
coverage.try_set_range(RawFilePointer::null().range(20), CoverageKind::FileMetadata)
|
||||
);
|
||||
assert!(!coverage.all_covered());
|
||||
assert!(coverage.try_set_range((RawFilePointer::null() + 20).range(20), CoverageKind::Free));
|
||||
assert!(coverage.all_covered());
|
||||
@ -1141,7 +1170,7 @@ mod tests {
|
||||
|
||||
let snapshot = &*db.state.get();
|
||||
|
||||
coverage.set_range(Db::<R>::header_ptr().range(), CoverageKind::Metadata);
|
||||
coverage.set_range(Db::<R>::header_ptr().range(), CoverageKind::FileMetadata);
|
||||
|
||||
// general purpose
|
||||
{
|
||||
@ -1165,7 +1194,7 @@ mod tests {
|
||||
.0
|
||||
.into_raw()
|
||||
.range(slabs.read_header(db).size() as u64),
|
||||
CoverageKind::Metadata,
|
||||
CoverageKind::SlabMetadata,
|
||||
);
|
||||
next = slabs.next(db);
|
||||
|
||||
@ -1182,7 +1211,7 @@ mod tests {
|
||||
let header =
|
||||
FilePointer::<RelativeFreeListHeader>::new(page.start());
|
||||
|
||||
coverage.set_range(header.range(), CoverageKind::Metadata);
|
||||
coverage.set_range(header.range(), CoverageKind::SlabMetadata);
|
||||
|
||||
let header = snapshot.read(header);
|
||||
|
||||
@ -1219,6 +1248,15 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
// retired objects
|
||||
{
|
||||
for SnapshotAndFreeList { to_free, .. } in &db.snapshots {
|
||||
for &range in to_free {
|
||||
coverage.set_range(range, CoverageKind::Retired);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
f(snapshot, &mut coverage);
|
||||
|
||||
print!("{}", coverage.print());
|
||||
|
Loading…
Reference in New Issue
Block a user