[thin/cache_restore (rust)] Build the metadata space map in-place
That avoids cloning the source space map
This commit is contained in:
parent
9ab8dfa283
commit
4b7b3658ff
4
src/cache/restore.rs
vendored
4
src/cache/restore.rs
vendored
@ -3,7 +3,6 @@ use anyhow::{anyhow, Result};
|
||||
use std::convert::TryInto;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Cursor;
|
||||
use std::ops::Deref;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
@ -230,8 +229,7 @@ impl<'a> MetadataVisitor for Restorer<'a> {
|
||||
fn build_metadata_sm(w: &mut WriteBatcher) -> Result<Vec<u8>> {
|
||||
let mut sm_root = vec![0u8; SPACE_MAP_ROOT_SIZE];
|
||||
let mut cur = Cursor::new(&mut sm_root);
|
||||
let sm_without_meta = clone_space_map(w.sm.lock().unwrap().deref())?;
|
||||
let r = write_metadata_sm(w, sm_without_meta.deref())?;
|
||||
let r = write_metadata_sm(w)?;
|
||||
r.pack(&mut cur)?;
|
||||
|
||||
Ok(sm_root)
|
||||
|
@ -152,16 +152,6 @@ pub fn core_sm_without_mutex(nr_entries: u64, max_count: u32) -> Box<dyn SpaceMa
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: replace it by using the Clone trait
|
||||
pub fn clone_space_map(src: &dyn SpaceMap) -> Result<Box<dyn SpaceMap>> {
|
||||
let nr_blocks = src.get_nr_blocks()?;
|
||||
let mut dest = Box::new(CoreSpaceMap::<u32>::new(nr_blocks));
|
||||
for i in 0..nr_blocks {
|
||||
dest.set(i, src.get(i)?)?;
|
||||
}
|
||||
Ok(dest)
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
|
||||
// This in core space map can only count to one, useful when walking
|
||||
|
@ -250,6 +250,90 @@ pub fn write_common(w: &mut WriteBatcher, sm: &dyn SpaceMap) -> Result<(Vec<Inde
|
||||
Ok((index_entries, ref_count_root))
|
||||
}
|
||||
|
||||
pub fn write_metadata_common(w: &mut WriteBatcher) -> Result<(Vec<IndexEntry>, u64)> {
|
||||
use BitmapEntry::*;
|
||||
|
||||
let mut index_entries = Vec::new();
|
||||
let mut overflow_builder: BTreeBuilder<u32> = BTreeBuilder::new(Box::new(NoopRC {}));
|
||||
|
||||
// how many bitmaps do we need?
|
||||
let nr_blocks = w.sm.lock().unwrap().get_nr_blocks()?;
|
||||
let nr_bitmaps = div_up(nr_blocks, ENTRIES_PER_BITMAP as u64) as usize;
|
||||
|
||||
// how many blocks are allocated or reserved so far?
|
||||
let reserved = w.get_reserved_range();
|
||||
if reserved.end < reserved.start {
|
||||
return Err(anyhow!("unsupported allocation pattern"));
|
||||
}
|
||||
let nr_used_bitmaps = div_up(reserved.end, ENTRIES_PER_BITMAP as u64) as usize;
|
||||
|
||||
for bm in 0..nr_used_bitmaps {
|
||||
let begin = bm as u64 * ENTRIES_PER_BITMAP as u64;
|
||||
let len = std::cmp::min(nr_blocks - begin, ENTRIES_PER_BITMAP as u64);
|
||||
let mut entries = Vec::with_capacity(ENTRIES_PER_BITMAP);
|
||||
let mut first_free: Option<u32> = None;
|
||||
|
||||
// blocks beyond the limit won't be checked right now, thus are marked as freed
|
||||
let limit = std::cmp::min(reserved.end - begin, ENTRIES_PER_BITMAP as u64);
|
||||
let mut nr_free: u32 = (len - limit) as u32;
|
||||
|
||||
for i in 0..limit {
|
||||
let b = begin + i;
|
||||
let rc = w.sm.lock().unwrap().get(b)?;
|
||||
let e = match rc {
|
||||
0 => {
|
||||
nr_free += 1;
|
||||
if first_free.is_none() {
|
||||
first_free = Some(i as u32);
|
||||
}
|
||||
Small(0)
|
||||
}
|
||||
1 => Small(1),
|
||||
2 => Small(2),
|
||||
_ => {
|
||||
overflow_builder.push_value(w, b as u64, rc)?;
|
||||
Overflow
|
||||
}
|
||||
};
|
||||
entries.push(e);
|
||||
}
|
||||
|
||||
// Fill unused entries with zeros
|
||||
if limit < len {
|
||||
entries.resize_with(len as usize, || BitmapEntry::Small(0));
|
||||
}
|
||||
|
||||
let blocknr = write_bitmap(w, entries)?;
|
||||
|
||||
// Insert into the index list
|
||||
let ie = IndexEntry {
|
||||
blocknr,
|
||||
nr_free,
|
||||
none_free_before: first_free.unwrap_or(limit as u32),
|
||||
};
|
||||
index_entries.push(ie);
|
||||
}
|
||||
|
||||
// Fill the rest of the bitmaps with zeros
|
||||
for bm in nr_used_bitmaps..nr_bitmaps {
|
||||
let begin = bm as u64 * ENTRIES_PER_BITMAP as u64;
|
||||
let len = std::cmp::min(nr_blocks - begin, ENTRIES_PER_BITMAP as u64);
|
||||
let entries = vec![BitmapEntry::Small(0); ENTRIES_PER_BITMAP];
|
||||
let blocknr = write_bitmap(w, entries)?;
|
||||
|
||||
// Insert into the index list
|
||||
let ie = IndexEntry {
|
||||
blocknr,
|
||||
nr_free: len as u32,
|
||||
none_free_before: 0,
|
||||
};
|
||||
index_entries.push(ie);
|
||||
}
|
||||
|
||||
let ref_count_root = overflow_builder.complete(w)?;
|
||||
Ok((index_entries, ref_count_root))
|
||||
}
|
||||
|
||||
fn write_bitmap(w: &mut WriteBatcher, entries: Vec<BitmapEntry>) -> Result<u64> {
|
||||
// allocate a new block
|
||||
let b = w.alloc_zeroed()?;
|
||||
|
@ -6,7 +6,6 @@ use std::io::Cursor;
|
||||
|
||||
use crate::checksum;
|
||||
use crate::io_engine::*;
|
||||
use crate::pdata::space_map::*;
|
||||
use crate::pdata::space_map_common::*;
|
||||
use crate::pdata::unpack::*;
|
||||
use crate::write_batcher::*;
|
||||
@ -103,9 +102,10 @@ fn adjust_counts(w: &mut WriteBatcher, ie: &IndexEntry, allocs: &[u64]) -> Resul
|
||||
})
|
||||
}
|
||||
|
||||
pub fn write_metadata_sm(w: &mut WriteBatcher, sm: &dyn SpaceMap) -> Result<SMRoot> {
|
||||
pub fn write_metadata_sm(w: &mut WriteBatcher) -> Result<SMRoot> {
|
||||
w.clear_allocations();
|
||||
let (mut indexes, ref_count_root) = write_common(w, sm)?;
|
||||
|
||||
let (mut indexes, ref_count_root) = write_metadata_common(w)?;
|
||||
|
||||
let bitmap_root = w.alloc_zeroed()?;
|
||||
|
||||
@ -135,6 +135,7 @@ pub fn write_metadata_sm(w: &mut WriteBatcher, sm: &dyn SpaceMap) -> Result<SMRo
|
||||
w.write(bitmap_root, checksum::BT::INDEX)?;
|
||||
w.flush()?;
|
||||
|
||||
let sm = w.sm.lock().unwrap();
|
||||
Ok(SMRoot {
|
||||
nr_blocks: sm.get_nr_blocks()?,
|
||||
nr_allocated: sm.get_nr_allocated()?,
|
||||
|
@ -251,8 +251,7 @@ fn build_data_sm(w: &mut WriteBatcher, sm: &dyn SpaceMap) -> Result<Vec<u8>> {
|
||||
fn build_metadata_sm(w: &mut WriteBatcher) -> Result<Vec<u8>> {
|
||||
let mut sm_root = vec![0u8; SPACE_MAP_ROOT_SIZE];
|
||||
let mut cur = Cursor::new(&mut sm_root);
|
||||
let sm_without_meta = clone_space_map(w.sm.lock().unwrap().deref())?;
|
||||
let r = write_metadata_sm(w, sm_without_meta.deref())?;
|
||||
let r = write_metadata_sm(w)?;
|
||||
r.pack(&mut cur)?;
|
||||
|
||||
Ok(sm_root)
|
||||
|
@ -114,6 +114,13 @@ impl WriteBatcher {
|
||||
tmp
|
||||
}
|
||||
|
||||
pub fn get_reserved_range(&self) -> std::ops::Range<u64> {
|
||||
std::ops::Range {
|
||||
start: self.reserved.start,
|
||||
end: self.reserved.end,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&mut self, b: Block, kind: checksum::BT) -> Result<()> {
|
||||
checksum::write_checksum(&mut b.get_data(), kind)?;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user