Skip to content

Commit

Permalink
[TieredStorage] Have HotStorageWriter::write_account return Vec<Store…
Browse files Browse the repository at this point in the history
…dAccountInfo>
  • Loading branch information
yhchiang-sol committed Jan 26, 2024
1 parent 20110b7 commit c01ff81
Showing 1 changed file with 68 additions and 32 deletions.
100 changes: 68 additions & 32 deletions accounts-db/src/tiered_storage/hot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use {
crate::{
account_storage::meta::StoredAccountMeta,
account_storage::meta::{StoredAccountInfo, StoredAccountMeta},
accounts_file::MatchAccountOwnerError,
accounts_hash::AccountHash,
tiered_storage::{
Expand Down Expand Up @@ -542,14 +542,15 @@ impl HotStorageWriter {
&self,
accounts: &StorableAccountsWithHashesAndWriteVersions<'a, 'b, T, U, V>,
skip: usize,
) -> TieredStorageResult<()> {
) -> TieredStorageResult<Vec<StoredAccountInfo>> {
let mut footer = new_hot_footer();
let mut index = vec![];
let mut owners_table = OwnersTable::default();
let mut cursor = 0;

// writing accounts blocks
let len = accounts.accounts.len();
let mut stored_infos = Vec::with_capacity(len - skip);
for i in skip..len {
let (account, address, account_hash, _write_version) = accounts.get(i);
let index_entry = AccountIndexWriterEntry {
Expand All @@ -573,14 +574,30 @@ impl HotStorageWriter {
})
.unwrap_or((0, &OWNER_NO_OWNER, &[], false, None, None));
let owner_offset = owners_table.insert(owner);
cursor += self.write_account(
let stored_size = self.write_account(
lamports,
owner_offset,
data,
executable,
rent_epoch,
account_hash,
)?;
cursor += stored_size;

stored_infos.push(StoredAccountInfo {
// Here we pass the IndexOffset as the get_account() API
// takes IndexOffset. Given the account address is also
// maintained outside the TieredStorage, a potential optimization
// is to store AccountOffset instead, which can further save
// one jump from the index block to the accounts block.
offset: index.len(),
// The size here might be slightly bigger than the actual
// storage size of one account as one owner address could be
// shared by multiple accounts.
size: stored_size
+ footer.index_block_format.entry_size::<HotAccountOffset>()
+ std::mem::size_of::<Pubkey>(),
});
index.push(index_entry);
}
footer.account_entry_count = (len - skip) as u32;
Expand Down Expand Up @@ -610,7 +627,7 @@ impl HotStorageWriter {

footer.write_footer_block(&self.storage)?;

Ok(())
Ok(stored_infos)
}
}

Expand Down Expand Up @@ -1279,6 +1296,37 @@ pub mod tests {
(stored_meta, AccountSharedData::from(account))
}

fn verify_account(
stored_meta: &StoredAccountMeta<'_>,
account: Option<&impl ReadableAccount>,
address: &Pubkey,
account_hash: &AccountHash,
) {
let (lamports, owner, data, executable, account_hash) = account
.map(|acc| {
(
acc.lamports(),
acc.owner(),
acc.data(),
acc.executable(),
// only persist rent_epoch for those non-rent-exempt accounts
Some(*account_hash),
)
})
.unwrap_or((0, &OWNER_NO_OWNER, &[], false, None));

assert_eq!(stored_meta.lamports(), lamports);
assert_eq!(stored_meta.data().len(), data.len());
assert_eq!(stored_meta.data(), data);
assert_eq!(stored_meta.executable(), executable);
assert_eq!(stored_meta.owner(), owner);
assert_eq!(stored_meta.pubkey(), address);
assert_eq!(
*stored_meta.hash(),
account_hash.unwrap_or(AccountHash(Hash::default()))
);
}

#[test]
fn test_write_account_and_index_blocks() {
let account_data_sizes = &[
Expand Down Expand Up @@ -1315,11 +1363,10 @@ pub mod tests {

let temp_dir = TempDir::new().unwrap();
let path = temp_dir.path().join("test_write_account_and_index_blocks");

{
let stored_infos = {
let writer = HotStorageWriter::new(&path).unwrap();
writer.write_accounts(&storable_accounts, 0).unwrap();
}
writer.write_accounts(&storable_accounts, 0).unwrap()
};

let hot_storage = HotStorageReader::new_from_path(&path).unwrap();

Expand All @@ -1331,30 +1378,8 @@ pub mod tests {
.unwrap()
.unwrap();

let (account, address, account_hash, _write_version) = storable_accounts.get(i);
let (lamports, owner, data, executable, account_hash) = account
.map(|acc| {
(
acc.lamports(),
acc.owner(),
acc.data(),
acc.executable(),
// only persist rent_epoch for those non-rent-exempt accounts
Some(*account_hash),
)
})
.unwrap_or((0, &OWNER_NO_OWNER, &[], false, None));

assert_eq!(stored_meta.lamports(), lamports);
assert_eq!(stored_meta.data().len(), data.len());
assert_eq!(stored_meta.data(), data);
assert_eq!(stored_meta.executable(), executable);
assert_eq!(stored_meta.owner(), owner);
assert_eq!(stored_meta.pubkey(), address);
assert_eq!(
*stored_meta.hash(),
account_hash.unwrap_or(AccountHash(Hash::default()))
);
let (account, address, hash, _write_version) = storable_accounts.get(i);
verify_account(&stored_meta, account, address, hash);

assert_eq!(i + 1, next);
}
Expand All @@ -1364,5 +1389,16 @@ pub mod tests {
hot_storage.get_account(IndexOffset(num_accounts as u32)),
Ok(None)
);

for stored_info in stored_infos {
let (stored_meta, _) = hot_storage
.get_account(IndexOffset(stored_info.offset as u32))
.unwrap()
.unwrap();

let (account, address, hash, _write_version) =
storable_accounts.get(stored_info.offset);
verify_account(&stored_meta, account, address, hash);
}
}
}

0 comments on commit c01ff81

Please sign in to comment.