extend coverage map

This commit is contained in:
soruh 2023-08-03 04:23:30 +02:00
parent 42a2aef527
commit 94880f311e

View File

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