Skip to content

Commit a3482ea

Browse files
trim chain
1 parent 19e4685 commit a3482ea

1 file changed

Lines changed: 37 additions & 1 deletion

File tree

storage/src/qmdb/current/batch.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,42 @@ pub(crate) struct BitmapBatchLayer<const N: usize> {
767767

768768
impl<const N: usize> BitmapBatch<N> {
769769
const CHUNK_SIZE_BITS: u64 = BitMap::<N>::CHUNK_SIZE_BITS;
770+
771+
/// Walk to the terminal [`SharedBitmap`] at the bottom of the chain.
772+
fn shared(&self) -> &Arc<SharedBitmap<N>> {
773+
let mut current = self;
774+
loop {
775+
match current {
776+
Self::Base(s) => return s,
777+
Self::Layer(layer) => current = &layer.parent,
778+
}
779+
}
780+
}
781+
782+
/// Return a chain equivalent to `self` with any `Layer` whose overlay is now fully committed
783+
/// replaced by a direct reference to the committed bitmap. Since `apply_batch` commits
784+
/// contiguous prefixes, committed `Layer`s are always at the bottom of the chain.
785+
fn trim_committed(&self) -> Self {
786+
let shared = self.shared();
787+
let committed = shared.read().len();
788+
let mut kept: Vec<Arc<ChunkOverlay<N>>> = Vec::new();
789+
let mut current = self;
790+
while let Self::Layer(layer) = current {
791+
if layer.overlay.len <= committed {
792+
let mut result = Self::Base(Arc::clone(shared));
793+
for overlay in kept.into_iter().rev() {
794+
result = Self::Layer(Arc::new(BitmapBatchLayer {
795+
parent: result,
796+
overlay,
797+
}));
798+
}
799+
return result;
800+
}
801+
kept.push(Arc::clone(&layer.overlay));
802+
current = &layer.parent;
803+
}
804+
self.clone()
805+
}
770806
}
771807

772808
impl<const N: usize> BitmapReadable<N> for BitmapBatch<N> {
@@ -861,7 +897,7 @@ where
861897
UnmerkleizedBatch::new(
862898
self.inner.new_batch::<H>(),
863899
Arc::clone(&self.grafted),
864-
self.bitmap.clone(),
900+
self.bitmap.trim_committed(),
865901
)
866902
}
867903

0 commit comments

Comments
 (0)