-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2877b81
commit cb5faf4
Showing
2 changed files
with
99 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
); | ||
} | ||
} | ||
} |