From f1a82cb666340ee606a2d5e384d944585b0d2611 Mon Sep 17 00:00:00 2001 From: Yueh-Hsuan Chiang <93241502+yhchiang-sol@users.noreply.github.com> Date: Fri, 22 Mar 2024 11:56:30 -0700 Subject: [PATCH] [TieredStorage] Use mmap.len() in TieredStorage::file_size() for HotStorage (#381) #### Problem The current implementation of TieredStorage::file_size() requires a sys-call to provide the file size. #### Summary of Changes Add len() API to TieredStorageReader, and have HotStorageReader() implement the API using Mmap::len(). #### Test Plan Update existing unit-test to also verify HotStorageReader::len(). --- accounts-db/src/tiered_storage.rs | 9 ++------- accounts-db/src/tiered_storage/hot.rs | 21 ++++++++++++++++++++- accounts-db/src/tiered_storage/readable.rs | 14 ++++++++++++++ 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/accounts-db/src/tiered_storage.rs b/accounts-db/src/tiered_storage.rs index 3f655896a28ed6..20626143d7036d 100644 --- a/accounts-db/src/tiered_storage.rs +++ b/accounts-db/src/tiered_storage.rs @@ -27,7 +27,7 @@ use { solana_sdk::account::ReadableAccount, std::{ borrow::Borrow, - fs::{self, OpenOptions}, + fs, path::{Path, PathBuf}, sync::{ atomic::{AtomicBool, Ordering}, @@ -156,12 +156,7 @@ impl TieredStorage { /// Returns the size of the underlying accounts file. pub fn file_size(&self) -> TieredStorageResult { - let file = OpenOptions::new().read(true).open(&self.path); - - Ok(file - .and_then(|file| file.metadata()) - .map(|metadata| metadata.len()) - .unwrap_or(0)) + Ok(self.reader().map_or(0, |reader| reader.len())) } } diff --git a/accounts-db/src/tiered_storage/hot.rs b/accounts-db/src/tiered_storage/hot.rs index c1e92e4469b269..4d3fabfec40a63 100644 --- a/accounts-db/src/tiered_storage/hot.rs +++ b/accounts-db/src/tiered_storage/hot.rs @@ -359,6 +359,16 @@ impl HotStorageReader { Ok(Self { mmap, footer }) } + /// Returns the size of the underlying storage. + pub fn len(&self) -> u64 { + self.mmap.len() as u64 + } + + /// Returns whether the nderlying storage is empty. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + /// Returns the footer of the underlying tiered-storage accounts file. pub fn footer(&self) -> &TieredStorageFooter { &self.footer @@ -709,7 +719,7 @@ pub mod tests { super::*, crate::tiered_storage::{ byte_block::ByteBlockWriter, - file::TieredWritableFile, + file::{TieredStorageMagicNumber, TieredWritableFile}, footer::{AccountBlockFormat, AccountMetaFormat, TieredStorageFooter, FOOTER_SIZE}, hot::{HotAccountMeta, HotStorageReader}, index::{AccountIndexWriterEntry, IndexBlockFormat, IndexOffset}, @@ -1420,5 +1430,14 @@ pub mod tests { let partial_accounts = hot_storage.accounts(IndexOffset(i as u32)).unwrap(); assert_eq!(&partial_accounts, &accounts[i..]); } + let footer = hot_storage.footer(); + + let expected_size: u64 = footer.owners_block_offset + + std::mem::size_of::() as u64 * footer.owner_count as u64 + + std::mem::size_of::() as u64 + + std::mem::size_of::() as u64; + + assert!(!hot_storage.is_empty()); + assert_eq!(expected_size, hot_storage.len()); } } diff --git a/accounts-db/src/tiered_storage/readable.rs b/accounts-db/src/tiered_storage/readable.rs index 15d678ffc856fc..cc2b6fdee0356f 100644 --- a/accounts-db/src/tiered_storage/readable.rs +++ b/accounts-db/src/tiered_storage/readable.rs @@ -30,6 +30,20 @@ impl TieredStorageReader { } } + /// Returns the size of the underlying storage. + pub fn len(&self) -> u64 { + match self { + Self::Hot(hot) => hot.len(), + } + } + + /// Returns whether the nderlying storage is empty. + pub fn is_empty(&self) -> bool { + match self { + Self::Hot(hot) => hot.is_empty(), + } + } + /// Returns the footer of the associated HotAccountsFile. pub fn footer(&self) -> &TieredStorageFooter { match self {