2023-07-25 10:51:56 -07:00
|
|
|
#![allow(dead_code)]
|
|
|
|
|
2023-05-30 14:14:29 -07:00
|
|
|
pub mod byte_block;
|
2023-05-23 15:06:55 -07:00
|
|
|
pub mod error;
|
2023-05-07 13:18:10 -07:00
|
|
|
pub mod file;
|
|
|
|
pub mod footer;
|
2023-06-23 10:25:54 -07:00
|
|
|
pub mod hot;
|
2023-07-15 16:23:08 -07:00
|
|
|
pub mod index;
|
2023-06-01 14:48:27 -07:00
|
|
|
pub mod meta;
|
2023-05-07 13:18:10 -07:00
|
|
|
pub mod mmap_utils;
|
2023-07-06 09:08:09 -07:00
|
|
|
pub mod readable;
|
2023-07-26 23:55:48 -07:00
|
|
|
pub mod writer;
|
2023-05-23 15:06:55 -07:00
|
|
|
|
2023-07-25 10:51:56 -07:00
|
|
|
use {
|
2023-07-26 23:55:48 -07:00
|
|
|
crate::{
|
|
|
|
account_storage::meta::{StorableAccountsWithHashesAndWriteVersions, StoredAccountInfo},
|
|
|
|
storable_accounts::StorableAccounts,
|
|
|
|
},
|
2023-07-25 10:51:56 -07:00
|
|
|
error::TieredStorageError,
|
|
|
|
footer::{AccountBlockFormat, AccountMetaFormat, OwnersBlockFormat},
|
|
|
|
index::AccountIndexFormat,
|
2023-07-26 23:55:48 -07:00
|
|
|
solana_sdk::{account::ReadableAccount, hash::Hash},
|
|
|
|
std::{
|
|
|
|
borrow::Borrow,
|
|
|
|
fs::OpenOptions,
|
|
|
|
path::{Path, PathBuf},
|
|
|
|
},
|
|
|
|
writer::TieredStorageWriter,
|
2023-07-25 10:51:56 -07:00
|
|
|
};
|
2023-05-23 15:06:55 -07:00
|
|
|
|
|
|
|
pub type TieredStorageResult<T> = Result<T, TieredStorageError>;
|
2023-07-25 10:51:56 -07:00
|
|
|
|
|
|
|
/// The struct that defines the formats of all building blocks of a
|
|
|
|
/// TieredStorage.
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct TieredStorageFormat {
|
|
|
|
pub meta_entry_size: usize,
|
|
|
|
pub account_meta_format: AccountMetaFormat,
|
|
|
|
pub owners_block_format: OwnersBlockFormat,
|
|
|
|
pub account_index_format: AccountIndexFormat,
|
|
|
|
pub account_block_format: AccountBlockFormat,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct TieredStorage {
|
|
|
|
format: Option<TieredStorageFormat>,
|
|
|
|
path: PathBuf,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TieredStorage {
|
|
|
|
/// Creates a new writable instance of TieredStorage based on the
|
|
|
|
/// specified path and TieredStorageFormat.
|
|
|
|
///
|
2023-07-26 23:55:48 -07:00
|
|
|
/// Note that the actual file will not be created until write_accounts
|
2023-07-25 10:51:56 -07:00
|
|
|
/// is called.
|
|
|
|
pub fn new_writable(path: impl Into<PathBuf>, format: TieredStorageFormat) -> Self {
|
|
|
|
Self {
|
|
|
|
format: Some(format),
|
|
|
|
path: path.into(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the path to this TieredStorage.
|
|
|
|
pub fn path(&self) -> &Path {
|
|
|
|
self.path.as_path()
|
|
|
|
}
|
2023-07-26 23:55:48 -07:00
|
|
|
|
|
|
|
/// Writes the specified accounts into this TieredStorage.
|
|
|
|
pub fn write_accounts<
|
|
|
|
'a,
|
|
|
|
'b,
|
|
|
|
T: ReadableAccount + Sync,
|
|
|
|
U: StorableAccounts<'a, T>,
|
|
|
|
V: Borrow<Hash>,
|
|
|
|
>(
|
|
|
|
&self,
|
|
|
|
accounts: &StorableAccountsWithHashesAndWriteVersions<'a, 'b, T, U, V>,
|
|
|
|
skip: usize,
|
|
|
|
) -> TieredStorageResult<Vec<StoredAccountInfo>> {
|
|
|
|
// self.format must be Some as write_accounts can only be called on a
|
|
|
|
// TieredStorage instance created via new_writable() where it format
|
|
|
|
// field is required.
|
|
|
|
assert!(self.format.is_some());
|
|
|
|
let writer = TieredStorageWriter::new(&self.path, self.format.as_ref().unwrap())?;
|
|
|
|
writer.write_accounts(accounts, skip)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the size of the underlying accounts file.
|
|
|
|
pub fn file_size(&self) -> TieredStorageResult<u64> {
|
|
|
|
let file = OpenOptions::new().read(true).open(&self.path);
|
|
|
|
|
|
|
|
Ok(file
|
|
|
|
.and_then(|file| file.metadata())
|
|
|
|
.map(|metadata| metadata.len())
|
|
|
|
.unwrap_or(0))
|
|
|
|
}
|
2023-07-25 10:51:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2023-07-26 23:55:48 -07:00
|
|
|
use {
|
|
|
|
super::*,
|
|
|
|
crate::account_storage::meta::StoredMetaWriteVersion,
|
|
|
|
footer::{TieredStorageFooter, TieredStorageMagicNumber},
|
|
|
|
hot::HOT_FORMAT,
|
|
|
|
solana_sdk::{account::AccountSharedData, clock::Slot, pubkey::Pubkey},
|
|
|
|
tempfile::NamedTempFile,
|
|
|
|
};
|
2023-07-25 10:51:56 -07:00
|
|
|
|
|
|
|
#[test]
|
2023-07-26 23:55:48 -07:00
|
|
|
fn test_new_footer_only() {
|
|
|
|
let path = NamedTempFile::new().unwrap().path().to_path_buf();
|
|
|
|
|
|
|
|
let tiered_storage = TieredStorage::new_writable(path.clone(), HOT_FORMAT.clone());
|
|
|
|
assert_eq!(tiered_storage.path(), path);
|
|
|
|
assert_eq!(tiered_storage.file_size().unwrap(), 0);
|
|
|
|
|
|
|
|
let slot_ignored = Slot::MAX;
|
|
|
|
let account_refs = Vec::<(&Pubkey, &AccountSharedData)>::new();
|
|
|
|
let account_data = (slot_ignored, account_refs.as_slice());
|
|
|
|
let storable_accounts =
|
|
|
|
StorableAccountsWithHashesAndWriteVersions::new_with_hashes_and_write_versions(
|
|
|
|
&account_data,
|
|
|
|
Vec::<&Hash>::new(),
|
|
|
|
Vec::<StoredMetaWriteVersion>::new(),
|
|
|
|
);
|
2023-07-25 10:51:56 -07:00
|
|
|
|
2023-07-26 23:55:48 -07:00
|
|
|
let result = tiered_storage.write_accounts(&storable_accounts, 0);
|
|
|
|
// Expect the result to be TieredStorageError::Unsupported as the feature
|
|
|
|
// is not yet fully supported, but we can still check its partial results
|
|
|
|
// in the test.
|
|
|
|
assert!(result.is_err());
|
|
|
|
assert_eq!(
|
|
|
|
tiered_storage.file_size().unwrap() as usize,
|
|
|
|
std::mem::size_of::<TieredStorageFooter>()
|
|
|
|
+ std::mem::size_of::<TieredStorageMagicNumber>()
|
|
|
|
);
|
2023-07-25 10:51:56 -07:00
|
|
|
}
|
|
|
|
}
|