Add API to iterate over slot's blobs (#4276)
This commit is contained in:
@ -188,6 +188,14 @@ impl Blocktree {
|
|||||||
Ok(db_iterator)
|
Ok(db_iterator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn slot_data_iterator(
|
||||||
|
&self,
|
||||||
|
slot: u64,
|
||||||
|
) -> Result<impl Iterator<Item = ((u64, u64), Vec<u8>)>> {
|
||||||
|
let slot_iterator = self.db.iter::<cf::Data>(Some((slot, 0)))?;
|
||||||
|
Ok(slot_iterator.take_while(move |((blob_slot, _), _)| *blob_slot == slot))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_shared_blobs<I>(&self, shared_blobs: I) -> Result<()>
|
pub fn write_shared_blobs<I>(&self, shared_blobs: I) -> Result<()>
|
||||||
where
|
where
|
||||||
I: IntoIterator,
|
I: IntoIterator,
|
||||||
@ -673,7 +681,7 @@ impl Blocktree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_ledger_blobs(&self) -> impl Iterator<Item = Blob> + '_ {
|
pub fn read_ledger_blobs(&self) -> impl Iterator<Item = Blob> + '_ {
|
||||||
let iter = self.db.iter::<cf::Data>().unwrap();
|
let iter = self.db.iter::<cf::Data>(None).unwrap();
|
||||||
iter.map(|(_, blob_data)| Blob::new(&blob_data))
|
iter.map(|(_, blob_data)| Blob::new(&blob_data))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3042,6 +3050,34 @@ pub mod tests {
|
|||||||
Blocktree::destroy(&blocktree_path).expect("Expected successful database destruction");
|
Blocktree::destroy(&blocktree_path).expect("Expected successful database destruction");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_slot_data_iterator() {
|
||||||
|
// Construct the blobs
|
||||||
|
let blocktree_path = get_tmp_ledger_path!();
|
||||||
|
let blocktree = Blocktree::open(&blocktree_path).unwrap();
|
||||||
|
let blobs_per_slot = 10;
|
||||||
|
let slots = vec![2, 4, 8, 12];
|
||||||
|
let all_blobs = make_chaining_slot_entries(&slots, blobs_per_slot);
|
||||||
|
let slot_8_blobs = all_blobs[2].0.clone();
|
||||||
|
for (slot_blobs, _) in all_blobs {
|
||||||
|
blocktree.insert_data_blobs(&slot_blobs[..]).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slot doesnt exist, iterator should be empty
|
||||||
|
let blob_iter = blocktree.slot_data_iterator(5).unwrap();
|
||||||
|
let result: Vec<_> = blob_iter.collect();
|
||||||
|
assert_eq!(result, vec![]);
|
||||||
|
|
||||||
|
// Test that the iterator for slot 8 contains what was inserted earlier
|
||||||
|
let blob_iter = blocktree.slot_data_iterator(8).unwrap();
|
||||||
|
let result: Vec<_> = blob_iter.map(|(_, bytes)| Blob::new(&bytes)).collect();
|
||||||
|
assert_eq!(result.len() as u64, blobs_per_slot);
|
||||||
|
assert_eq!(result, slot_8_blobs);
|
||||||
|
|
||||||
|
drop(blocktree);
|
||||||
|
Blocktree::destroy(&blocktree_path).expect("Expected successful database destruction");
|
||||||
|
}
|
||||||
|
|
||||||
mod erasure {
|
mod erasure {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::blocktree::meta::ErasureMetaStatus;
|
use crate::blocktree::meta::ErasureMetaStatus;
|
||||||
|
@ -60,7 +60,7 @@ pub trait Backend: Sized + Send + Sync {
|
|||||||
|
|
||||||
fn delete_cf(&self, cf: Self::ColumnFamily, key: &Self::Key) -> Result<()>;
|
fn delete_cf(&self, cf: Self::ColumnFamily, key: &Self::Key) -> Result<()>;
|
||||||
|
|
||||||
fn iterator_cf(&self, cf: Self::ColumnFamily) -> Result<Self::Iter>;
|
fn iterator_cf(&self, cf: Self::ColumnFamily, from: Option<&Self::Key>) -> Result<Self::Iter>;
|
||||||
|
|
||||||
fn raw_iterator_cf(&self, cf: Self::ColumnFamily) -> Result<Self::Cursor>;
|
fn raw_iterator_cf(&self, cf: Self::ColumnFamily) -> Result<Self::Cursor>;
|
||||||
|
|
||||||
@ -241,16 +241,24 @@ where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter<C>(&self) -> Result<impl Iterator<Item = (C::Index, Vec<u8>)>>
|
pub fn iter<C>(
|
||||||
|
&self,
|
||||||
|
start_from: Option<C::Index>,
|
||||||
|
) -> Result<impl Iterator<Item = (C::Index, Vec<u8>)>>
|
||||||
where
|
where
|
||||||
C: Column<B>,
|
C: Column<B>,
|
||||||
{
|
{
|
||||||
let iter = self
|
let iter = {
|
||||||
.backend
|
if let Some(index) = start_from {
|
||||||
.iterator_cf(self.cf_handle::<C>())?
|
let key = C::key(index);
|
||||||
.map(|(key, value)| (C::index(&key), value.into()));
|
self.backend
|
||||||
|
.iterator_cf(self.cf_handle::<C>(), Some(key.borrow()))?
|
||||||
|
} else {
|
||||||
|
self.backend.iterator_cf(self.cf_handle::<C>(), None)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(iter)
|
Ok(iter.map(|(key, value)| (C::index(&key), value.into())))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -371,13 +379,21 @@ where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter(&self) -> Result<impl Iterator<Item = (C::Index, Vec<u8>)>> {
|
pub fn iter(
|
||||||
let iter = self
|
&self,
|
||||||
.backend
|
start_from: Option<C::Index>,
|
||||||
.iterator_cf(self.handle())?
|
) -> Result<impl Iterator<Item = (C::Index, Vec<u8>)>> {
|
||||||
.map(|(key, value)| (C::index(&key), value.into()));
|
let iter = {
|
||||||
|
if let Some(index) = start_from {
|
||||||
|
let key = C::key(index);
|
||||||
|
self.backend
|
||||||
|
.iterator_cf(self.handle(), Some(key.borrow()))?
|
||||||
|
} else {
|
||||||
|
self.backend.iterator_cf(self.handle(), None)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(iter)
|
Ok(iter.map(|(key, value)| (C::index(&key), value.into())))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -6,8 +6,8 @@ use crate::result::{Error, Result};
|
|||||||
use byteorder::{BigEndian, ByteOrder};
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
|
|
||||||
use rocksdb::{
|
use rocksdb::{
|
||||||
self, ColumnFamily, ColumnFamilyDescriptor, DBIterator, DBRawIterator, IteratorMode, Options,
|
self, ColumnFamily, ColumnFamilyDescriptor, DBIterator, DBRawIterator, Direction, IteratorMode,
|
||||||
WriteBatch as RWriteBatch, DB,
|
Options, WriteBatch as RWriteBatch, DB,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@ -101,10 +101,17 @@ impl Backend for Rocks {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterator_cf(&self, cf: ColumnFamily) -> Result<DBIterator> {
|
fn iterator_cf(&self, cf: ColumnFamily, start_from: Option<&[u8]>) -> Result<DBIterator> {
|
||||||
let raw_iter = self.0.iterator_cf(cf, IteratorMode::Start)?;
|
let iter = {
|
||||||
|
if let Some(start_from) = start_from {
|
||||||
|
self.0
|
||||||
|
.iterator_cf(cf, IteratorMode::From(start_from, Direction::Forward))?
|
||||||
|
} else {
|
||||||
|
self.0.iterator_cf(cf, IteratorMode::Start)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(raw_iter)
|
Ok(iter)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn raw_iterator_cf(&self, cf: ColumnFamily) -> Result<DBRawIterator> {
|
fn raw_iterator_cf(&self, cf: ColumnFamily) -> Result<DBRawIterator> {
|
||||||
|
Reference in New Issue
Block a user