more ancient append vec fns (#25127)
This commit is contained in:
parent
3ce877d1ab
commit
11fa0db850
|
@ -5,9 +5,12 @@
|
||||||
//! Otherwise, an ancient append vec is the same as any other append vec
|
//! Otherwise, an ancient append vec is the same as any other append vec
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use {
|
use {
|
||||||
crate::{accounts_db::FoundStoredAccount, append_vec::StoredAccountMeta},
|
crate::{
|
||||||
|
accounts_db::{AccountStorageEntry, FoundStoredAccount, SnapshotStorage},
|
||||||
|
append_vec::{AppendVec, StoredAccountMeta},
|
||||||
|
},
|
||||||
solana_sdk::{clock::Slot, hash::Hash, pubkey::Pubkey},
|
solana_sdk::{clock::Slot, hash::Hash, pubkey::Pubkey},
|
||||||
std::collections::HashMap,
|
std::{collections::HashMap, sync::Arc},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// a set of accounts need to be stored.
|
/// a set of accounts need to be stored.
|
||||||
|
@ -81,12 +84,55 @@ impl<'a> AccountsToStore<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// capacity of an ancient append vec
|
||||||
|
pub fn get_ancient_append_vec_capacity() -> u64 {
|
||||||
|
use crate::append_vec::MAXIMUM_APPEND_VEC_FILE_SIZE;
|
||||||
|
// smaller than max by a bit just in case
|
||||||
|
// some functions add slop on allocation
|
||||||
|
MAXIMUM_APPEND_VEC_FILE_SIZE - 2048
|
||||||
|
}
|
||||||
|
|
||||||
|
/// true iff storage is ancient size and is almost completely full
|
||||||
|
pub fn is_full_ancient(storage: &AppendVec) -> bool {
|
||||||
|
// not sure of slop amount here. Maybe max account size with 10MB data?
|
||||||
|
// append vecs can't usually be made entirely full
|
||||||
|
let threshold_bytes = 10_000;
|
||||||
|
is_ancient(storage) && storage.remaining_bytes() < threshold_bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
/// is this a max-size append vec designed to be used as an ancient append vec?
|
||||||
|
pub fn is_ancient(storage: &AppendVec) -> bool {
|
||||||
|
storage.capacity() >= get_ancient_append_vec_capacity()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// return true if the accounts in this slot should be moved to an ancient append vec
|
||||||
|
/// otherwise, return false and the caller can skip this slot
|
||||||
|
/// side effect could be updating 'current_ancient'
|
||||||
|
pub fn should_move_to_ancient_append_vec(
|
||||||
|
all_storages: &SnapshotStorage,
|
||||||
|
current_ancient: &mut Option<(Slot, Arc<AccountStorageEntry>)>,
|
||||||
|
slot: Slot,
|
||||||
|
) -> bool {
|
||||||
|
if current_ancient.is_none() && all_storages.len() == 1 {
|
||||||
|
let first_storage = all_storages.first().unwrap();
|
||||||
|
if is_ancient(&first_storage.accounts) {
|
||||||
|
if is_full_ancient(&first_storage.accounts) {
|
||||||
|
return false; // skip this full ancient append vec completely
|
||||||
|
}
|
||||||
|
// this slot is ancient and can become the 'current' ancient for other slots to be squashed into
|
||||||
|
*current_ancient = Some((slot, Arc::clone(first_storage)));
|
||||||
|
return false; // we're done with this slot - this slot IS the ancient append vec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
use {
|
use {
|
||||||
super::*,
|
super::*,
|
||||||
crate::{
|
crate::{
|
||||||
accounts_db::AppendVecId,
|
accounts_db::{get_temp_accounts_paths, AppendVecId},
|
||||||
append_vec::{AccountMeta, StoredMeta},
|
append_vec::{AccountMeta, StoredMeta},
|
||||||
},
|
},
|
||||||
solana_sdk::account::{AccountSharedData, ReadableAccount},
|
solana_sdk::account::{AccountSharedData, ReadableAccount},
|
||||||
|
@ -170,4 +216,51 @@ pub mod tests {
|
||||||
StorageSelector::Primary => StorageSelector::Overflow,
|
StorageSelector::Primary => StorageSelector::Overflow,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_ancient_append_vec_capacity() {
|
||||||
|
assert_eq!(
|
||||||
|
get_ancient_append_vec_capacity(),
|
||||||
|
crate::append_vec::MAXIMUM_APPEND_VEC_FILE_SIZE - 2048
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_ancient() {
|
||||||
|
for (size, expected_ancient) in [
|
||||||
|
(get_ancient_append_vec_capacity() + 1, true),
|
||||||
|
(get_ancient_append_vec_capacity(), true),
|
||||||
|
(get_ancient_append_vec_capacity() - 1, false),
|
||||||
|
] {
|
||||||
|
let tf = crate::append_vec::test_utils::get_append_vec_path("test_is_ancient");
|
||||||
|
let (_temp_dirs, _paths) = get_temp_accounts_paths(1).unwrap();
|
||||||
|
let av = AppendVec::new(&tf.path, true, size as usize);
|
||||||
|
|
||||||
|
assert_eq!(expected_ancient, is_ancient(&av));
|
||||||
|
assert!(!is_full_ancient(&av));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_full_ancient() {
|
||||||
|
let size = get_ancient_append_vec_capacity();
|
||||||
|
let tf = crate::append_vec::test_utils::get_append_vec_path("test_is_ancient");
|
||||||
|
let (_temp_dirs, _paths) = get_temp_accounts_paths(1).unwrap();
|
||||||
|
let av = AppendVec::new(&tf.path, true, size as usize);
|
||||||
|
assert!(is_ancient(&av));
|
||||||
|
assert!(!is_full_ancient(&av));
|
||||||
|
let overhead = 400;
|
||||||
|
let data_len = size - overhead;
|
||||||
|
let mut account = AccountSharedData::default();
|
||||||
|
account.set_data(vec![0; data_len as usize]);
|
||||||
|
|
||||||
|
let sm = StoredMeta {
|
||||||
|
write_version: 0,
|
||||||
|
pubkey: Pubkey::new(&[0; 32]),
|
||||||
|
data_len: data_len as u64,
|
||||||
|
};
|
||||||
|
av.append_accounts(&[(sm, Some(&account))], &[Hash::default()]);
|
||||||
|
assert!(is_ancient(&av));
|
||||||
|
assert!(is_full_ancient(&av), "Remaining: {}", av.remaining_bytes());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue