[TieredStorage] OwnersBlock (#34052)
#### Problem A TieredStorage file has three types of block: accounts block, index block, and owner block, but implementation of the TieredStorage OwnersBlock is missing in the current master. #### Summary of Changes This PR implements OwnersBlock which stores a set of owners' addresses in a compact but efficient way. #### Test Plan A new unit-test is included in this PR.
This commit is contained in:
parent
fb76b4cb6c
commit
7fd13c0cd2
|
@ -8,6 +8,7 @@ pub mod hot;
|
|||
pub mod index;
|
||||
pub mod meta;
|
||||
pub mod mmap_utils;
|
||||
pub mod owners;
|
||||
pub mod readable;
|
||||
pub mod writer;
|
||||
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
use {
|
||||
crate::tiered_storage::{
|
||||
file::TieredStorageFile, footer::TieredStorageFooter, mmap_utils::get_type,
|
||||
TieredStorageResult,
|
||||
},
|
||||
memmap2::Mmap,
|
||||
solana_sdk::pubkey::Pubkey,
|
||||
};
|
||||
|
||||
/// Owner block holds a set of unique addresses of account owners,
|
||||
/// and an account meta has a owner_offset field for accessing
|
||||
/// it's owner address.
|
||||
#[derive(Debug)]
|
||||
pub struct OwnersBlock;
|
||||
|
||||
/// The offset to an owner entry in the owners block.
|
||||
/// This is used to obtain the address of the account owner.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct OwnerOffset(pub usize);
|
||||
|
||||
/// OwnersBlock is persisted as a consecutive bytes of pubkeys without any
|
||||
/// meta-data. For each account meta, it has a owner_offset field to
|
||||
/// access its owner's address in the OwnersBlock.
|
||||
impl OwnersBlock {
|
||||
/// Persists the provided owners' addresses into the specified file.
|
||||
pub fn write_owners_block(
|
||||
file: &TieredStorageFile,
|
||||
addresses: &[Pubkey],
|
||||
) -> TieredStorageResult<usize> {
|
||||
let mut bytes_written = 0;
|
||||
for address in addresses {
|
||||
bytes_written += file.write_type(address)?;
|
||||
}
|
||||
|
||||
Ok(bytes_written)
|
||||
}
|
||||
|
||||
/// Returns the owner address associated with the specified owner_offset
|
||||
/// and footer inside the input mmap.
|
||||
pub fn get_owner_address<'a>(
|
||||
mmap: &'a Mmap,
|
||||
footer: &TieredStorageFooter,
|
||||
owner_offset: OwnerOffset,
|
||||
) -> TieredStorageResult<&'a Pubkey> {
|
||||
let offset =
|
||||
footer.owners_block_offset as usize + (std::mem::size_of::<Pubkey>() * owner_offset.0);
|
||||
let (pubkey, _) = get_type::<Pubkey>(mmap, offset)?;
|
||||
|
||||
Ok(pubkey)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use {
|
||||
super::*, crate::tiered_storage::file::TieredStorageFile, memmap2::MmapOptions,
|
||||
std::fs::OpenOptions, tempfile::TempDir,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_owners_block() {
|
||||
// Generate a new temp path that is guaranteed to NOT already have a file.
|
||||
let temp_dir = TempDir::new().unwrap();
|
||||
let path = temp_dir.path().join("test_owners_block");
|
||||
const NUM_OWNERS: u32 = 10;
|
||||
|
||||
let addresses: Vec<_> = std::iter::repeat_with(Pubkey::new_unique)
|
||||
.take(NUM_OWNERS as usize)
|
||||
.collect();
|
||||
|
||||
let footer = TieredStorageFooter {
|
||||
// Set owners_block_offset to 0 as we didn't write any account
|
||||
// meta/data nor index block.
|
||||
owners_block_offset: 0,
|
||||
..TieredStorageFooter::default()
|
||||
};
|
||||
|
||||
{
|
||||
let file = TieredStorageFile::new_writable(&path).unwrap();
|
||||
|
||||
OwnersBlock::write_owners_block(&file, &addresses).unwrap();
|
||||
|
||||
// while the test only focuses on account metas, writing a footer
|
||||
// here is necessary to make it a valid tiered-storage file.
|
||||
footer.write_footer_block(&file).unwrap();
|
||||
}
|
||||
|
||||
let file = OpenOptions::new().read(true).open(path).unwrap();
|
||||
let mmap = unsafe { MmapOptions::new().map(&file).unwrap() };
|
||||
|
||||
for (i, address) in addresses.iter().enumerate() {
|
||||
assert_eq!(
|
||||
OwnersBlock::get_owner_address(&mmap, &footer, OwnerOffset(i)).unwrap(),
|
||||
address
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue