Skip to content

Commit 6441209

Browse files
authored
[TieredStorage] TieredStorageFile -> TieredReadonlyFile and TieredWritableFIle (pyth-network#260)
#### Problem TieredStorageFile struct currently offers new_readonly() and new_writable() to allow both read and write work-load to share the same struct. However, as we need the writer to use BufWriter to improve performance as well as enable Hasher on writes. There is a need to refactor TieredStorageFile to split its usage for read-only and writable. #### Summary of Changes Refactor TieredStorageFile to TieredReadonlyFIle and TieredWritableFile. #### Test Plan Existing tiered-storage tests.
1 parent 36e9765 commit 6441209

File tree

5 files changed

+83
-61
lines changed

5 files changed

+83
-61
lines changed

accounts-db/src/tiered_storage/file.rs

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ use {
99
};
1010

1111
#[derive(Debug)]
12-
pub struct TieredStorageFile(pub File);
12+
pub struct TieredReadableFile(pub File);
1313

14-
impl TieredStorageFile {
15-
pub fn new_readonly(file_path: impl AsRef<Path>) -> Self {
14+
impl TieredReadableFile {
15+
pub fn new(file_path: impl AsRef<Path>) -> Self {
1616
Self(
1717
OpenOptions::new()
1818
.read(true)
@@ -36,30 +36,6 @@ impl TieredStorageFile {
3636
))
3737
}
3838

39-
/// Writes `value` to the file.
40-
///
41-
/// `value` must be plain ol' data.
42-
pub fn write_pod<T: NoUninit>(&self, value: &T) -> IoResult<usize> {
43-
// SAFETY: Since T is NoUninit, it does not contain any uninitialized bytes.
44-
unsafe { self.write_type(value) }
45-
}
46-
47-
/// Writes `value` to the file.
48-
///
49-
/// Prefer `write_pod` when possible, because `write_value` may cause
50-
/// undefined behavior if `value` contains uninitialized bytes.
51-
///
52-
/// # Safety
53-
///
54-
/// Caller must ensure casting T to bytes is safe.
55-
/// Refer to the Safety sections in std::slice::from_raw_parts()
56-
/// and bytemuck's Pod and NoUninit for more information.
57-
pub unsafe fn write_type<T>(&self, value: &T) -> IoResult<usize> {
58-
let ptr = value as *const _ as *const u8;
59-
let bytes = unsafe { std::slice::from_raw_parts(ptr, mem::size_of::<T>()) };
60-
self.write_bytes(bytes)
61-
}
62-
6339
/// Reads a value of type `T` from the file.
6440
///
6541
/// Type T must be plain ol' data.
@@ -95,13 +71,59 @@ impl TieredStorageFile {
9571
(&self.0).seek(SeekFrom::End(offset))
9672
}
9773

74+
pub fn read_bytes(&self, buffer: &mut [u8]) -> IoResult<()> {
75+
(&self.0).read_exact(buffer)
76+
}
77+
}
78+
79+
#[derive(Debug)]
80+
pub struct TieredWritableFile(pub File);
81+
82+
impl TieredWritableFile {
83+
pub fn new(file_path: impl AsRef<Path>) -> IoResult<Self> {
84+
Ok(Self(
85+
OpenOptions::new()
86+
.create_new(true)
87+
.write(true)
88+
.open(file_path)?,
89+
))
90+
}
91+
92+
/// Writes `value` to the file.
93+
///
94+
/// `value` must be plain ol' data.
95+
pub fn write_pod<T: NoUninit>(&self, value: &T) -> IoResult<usize> {
96+
// SAFETY: Since T is NoUninit, it does not contain any uninitialized bytes.
97+
unsafe { self.write_type(value) }
98+
}
99+
100+
/// Writes `value` to the file.
101+
///
102+
/// Prefer `write_pod` when possible, because `write_value` may cause
103+
/// undefined behavior if `value` contains uninitialized bytes.
104+
///
105+
/// # Safety
106+
///
107+
/// Caller must ensure casting T to bytes is safe.
108+
/// Refer to the Safety sections in std::slice::from_raw_parts()
109+
/// and bytemuck's Pod and NoUninit for more information.
110+
pub unsafe fn write_type<T>(&self, value: &T) -> IoResult<usize> {
111+
let ptr = value as *const _ as *const u8;
112+
let bytes = unsafe { std::slice::from_raw_parts(ptr, mem::size_of::<T>()) };
113+
self.write_bytes(bytes)
114+
}
115+
116+
pub fn seek(&self, offset: u64) -> IoResult<u64> {
117+
(&self.0).seek(SeekFrom::Start(offset))
118+
}
119+
120+
pub fn seek_from_end(&self, offset: i64) -> IoResult<u64> {
121+
(&self.0).seek(SeekFrom::End(offset))
122+
}
123+
98124
pub fn write_bytes(&self, bytes: &[u8]) -> IoResult<usize> {
99125
(&self.0).write_all(bytes)?;
100126

101127
Ok(bytes.len())
102128
}
103-
104-
pub fn read_bytes(&self, buffer: &mut [u8]) -> IoResult<()> {
105-
(&self.0).read_exact(buffer)
106-
}
107129
}

accounts-db/src/tiered_storage/footer.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use {
22
crate::tiered_storage::{
33
error::TieredStorageError,
4-
file::TieredStorageFile,
4+
file::{TieredReadableFile, TieredWritableFile},
55
index::IndexBlockFormat,
66
mmap_utils::{get_pod, get_type},
77
owners::OwnersBlockFormat,
@@ -186,19 +186,19 @@ impl Default for TieredStorageFooter {
186186

187187
impl TieredStorageFooter {
188188
pub fn new_from_path(path: impl AsRef<Path>) -> TieredStorageResult<Self> {
189-
let file = TieredStorageFile::new_readonly(path);
189+
let file = TieredReadableFile::new(path);
190190
Self::new_from_footer_block(&file)
191191
}
192192

193-
pub fn write_footer_block(&self, file: &TieredStorageFile) -> TieredStorageResult<()> {
193+
pub fn write_footer_block(&self, file: &TieredWritableFile) -> TieredStorageResult<()> {
194194
// SAFETY: The footer does not contain any uninitialized bytes.
195195
unsafe { file.write_type(self)? };
196196
file.write_pod(&TieredStorageMagicNumber::default())?;
197197

198198
Ok(())
199199
}
200200

201-
pub fn new_from_footer_block(file: &TieredStorageFile) -> TieredStorageResult<Self> {
201+
pub fn new_from_footer_block(file: &TieredReadableFile) -> TieredStorageResult<Self> {
202202
file.seek_from_end(-(FOOTER_TAIL_SIZE as i64))?;
203203

204204
let mut footer_version: u64 = 0;
@@ -326,7 +326,7 @@ mod tests {
326326
use {
327327
super::*,
328328
crate::{
329-
append_vec::test_utils::get_append_vec_path, tiered_storage::file::TieredStorageFile,
329+
append_vec::test_utils::get_append_vec_path, tiered_storage::file::TieredWritableFile,
330330
},
331331
memoffset::offset_of,
332332
solana_sdk::hash::Hash,
@@ -356,7 +356,7 @@ mod tests {
356356

357357
// Persist the expected footer.
358358
{
359-
let file = TieredStorageFile::new_writable(&path.path).unwrap();
359+
let file = TieredWritableFile::new(&path.path).unwrap();
360360
expected_footer.write_footer_block(&file).unwrap();
361361
}
362362

accounts-db/src/tiered_storage/hot.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use {
77
accounts_hash::AccountHash,
88
tiered_storage::{
99
byte_block,
10-
file::TieredStorageFile,
10+
file::TieredWritableFile,
1111
footer::{AccountBlockFormat, AccountMetaFormat, TieredStorageFooter},
1212
index::{AccountIndexWriterEntry, AccountOffset, IndexBlockFormat, IndexOffset},
1313
meta::{AccountMetaFlags, AccountMetaOptionalFields, TieredAccountMeta},
@@ -542,7 +542,7 @@ impl HotStorageReader {
542542
}
543543

544544
fn write_optional_fields(
545-
file: &TieredStorageFile,
545+
file: &TieredWritableFile,
546546
opt_fields: &AccountMetaOptionalFields,
547547
) -> TieredStorageResult<usize> {
548548
let mut size = 0;
@@ -558,14 +558,14 @@ fn write_optional_fields(
558558
/// The writer that creates a hot accounts file.
559559
#[derive(Debug)]
560560
pub struct HotStorageWriter {
561-
storage: TieredStorageFile,
561+
storage: TieredWritableFile,
562562
}
563563

564564
impl HotStorageWriter {
565565
/// Create a new HotStorageWriter with the specified path.
566566
pub fn new(file_path: impl AsRef<Path>) -> TieredStorageResult<Self> {
567567
Ok(Self {
568-
storage: TieredStorageFile::new_writable(file_path)?,
568+
storage: TieredWritableFile::new(file_path)?,
569569
})
570570
}
571571

@@ -706,7 +706,7 @@ pub mod tests {
706706
super::*,
707707
crate::tiered_storage::{
708708
byte_block::ByteBlockWriter,
709-
file::TieredStorageFile,
709+
file::TieredWritableFile,
710710
footer::{AccountBlockFormat, AccountMetaFormat, TieredStorageFooter, FOOTER_SIZE},
711711
hot::{HotAccountMeta, HotStorageReader},
712712
index::{AccountIndexWriterEntry, IndexBlockFormat, IndexOffset},
@@ -892,7 +892,7 @@ pub mod tests {
892892
};
893893

894894
{
895-
let file = TieredStorageFile::new_writable(&path).unwrap();
895+
let file = TieredWritableFile::new(&path).unwrap();
896896
expected_footer.write_footer_block(&file).unwrap();
897897
}
898898

@@ -928,7 +928,7 @@ pub mod tests {
928928
..TieredStorageFooter::default()
929929
};
930930
{
931-
let file = TieredStorageFile::new_writable(&path).unwrap();
931+
let file = TieredWritableFile::new(&path).unwrap();
932932
let mut current_offset = 0;
933933

934934
account_offsets = hot_account_metas
@@ -971,7 +971,7 @@ pub mod tests {
971971
};
972972

973973
{
974-
let file = TieredStorageFile::new_writable(&path).unwrap();
974+
let file = TieredWritableFile::new(&path).unwrap();
975975
footer.write_footer_block(&file).unwrap();
976976
}
977977

@@ -1016,7 +1016,7 @@ pub mod tests {
10161016
..TieredStorageFooter::default()
10171017
};
10181018
{
1019-
let file = TieredStorageFile::new_writable(&path).unwrap();
1019+
let file = TieredWritableFile::new(&path).unwrap();
10201020

10211021
let cursor = footer
10221022
.index_block_format
@@ -1059,7 +1059,7 @@ pub mod tests {
10591059
};
10601060

10611061
{
1062-
let file = TieredStorageFile::new_writable(&path).unwrap();
1062+
let file = TieredWritableFile::new(&path).unwrap();
10631063

10641064
let mut owners_table = OwnersTable::default();
10651065
addresses.iter().for_each(|owner_address| {
@@ -1118,7 +1118,7 @@ pub mod tests {
11181118
let account_offsets: Vec<_>;
11191119

11201120
{
1121-
let file = TieredStorageFile::new_writable(&path).unwrap();
1121+
let file = TieredWritableFile::new(&path).unwrap();
11221122
let mut current_offset = 0;
11231123

11241124
account_offsets = hot_account_metas
@@ -1237,7 +1237,7 @@ pub mod tests {
12371237
};
12381238

12391239
{
1240-
let file = TieredStorageFile::new_writable(&path).unwrap();
1240+
let file = TieredWritableFile::new(&path).unwrap();
12411241
let mut current_offset = 0;
12421242

12431243
// write accounts blocks

accounts-db/src/tiered_storage/index.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use {
22
crate::tiered_storage::{
3-
file::TieredStorageFile, footer::TieredStorageFooter, mmap_utils::get_pod,
3+
file::TieredWritableFile, footer::TieredStorageFooter, mmap_utils::get_pod,
44
TieredStorageResult,
55
},
66
bytemuck::{Pod, Zeroable},
@@ -59,7 +59,7 @@ impl IndexBlockFormat {
5959
/// the total number of bytes written.
6060
pub fn write_index_block(
6161
&self,
62-
file: &TieredStorageFile,
62+
file: &TieredWritableFile,
6363
index_entries: &[AccountIndexWriterEntry<impl AccountOffset>],
6464
) -> TieredStorageResult<usize> {
6565
match self {
@@ -147,7 +147,7 @@ mod tests {
147147
use {
148148
super::*,
149149
crate::tiered_storage::{
150-
file::TieredStorageFile,
150+
file::TieredWritableFile,
151151
hot::{HotAccountOffset, HOT_ACCOUNT_ALIGNMENT},
152152
},
153153
memmap2::MmapOptions,
@@ -181,7 +181,7 @@ mod tests {
181181
.collect();
182182

183183
{
184-
let file = TieredStorageFile::new_writable(&path).unwrap();
184+
let file = TieredWritableFile::new(&path).unwrap();
185185
let indexer = IndexBlockFormat::AddressesThenOffsets;
186186
let cursor = indexer.write_index_block(&file, &index_entries).unwrap();
187187
footer.owners_block_offset = cursor as u64;
@@ -223,7 +223,7 @@ mod tests {
223223
{
224224
// we only write a footer here as the test should hit an assert
225225
// failure before it actually reads the file.
226-
let file = TieredStorageFile::new_writable(&path).unwrap();
226+
let file = TieredWritableFile::new(&path).unwrap();
227227
footer.write_footer_block(&file).unwrap();
228228
}
229229

@@ -259,7 +259,7 @@ mod tests {
259259
{
260260
// we only write a footer here as the test should hit an assert
261261
// failure before it actually reads the file.
262-
let file = TieredStorageFile::new_writable(&path).unwrap();
262+
let file = TieredWritableFile::new(&path).unwrap();
263263
footer.write_footer_block(&file).unwrap();
264264
}
265265

@@ -294,7 +294,7 @@ mod tests {
294294
{
295295
// we only write a footer here as the test should hit an assert
296296
// failure before we actually read the file.
297-
let file = TieredStorageFile::new_writable(&path).unwrap();
297+
let file = TieredWritableFile::new(&path).unwrap();
298298
footer.write_footer_block(&file).unwrap();
299299
}
300300

@@ -334,7 +334,7 @@ mod tests {
334334
{
335335
// we only write a footer here as the test should hit an assert
336336
// failure before we actually read the file.
337-
let file = TieredStorageFile::new_writable(&path).unwrap();
337+
let file = TieredWritableFile::new(&path).unwrap();
338338
footer.write_footer_block(&file).unwrap();
339339
}
340340

accounts-db/src/tiered_storage/owners.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use {
22
crate::tiered_storage::{
3-
file::TieredStorageFile, footer::TieredStorageFooter, mmap_utils::get_pod,
3+
file::TieredWritableFile, footer::TieredStorageFooter, mmap_utils::get_pod,
44
TieredStorageResult,
55
},
66
indexmap::set::IndexSet,
@@ -47,7 +47,7 @@ impl OwnersBlockFormat {
4747
/// Persists the provided owners' addresses into the specified file.
4848
pub fn write_owners_block(
4949
&self,
50-
file: &TieredStorageFile,
50+
file: &TieredWritableFile,
5151
owners_table: &OwnersTable,
5252
) -> TieredStorageResult<usize> {
5353
match self {
@@ -116,7 +116,7 @@ impl<'a> OwnersTable<'a> {
116116
#[cfg(test)]
117117
mod tests {
118118
use {
119-
super::*, crate::tiered_storage::file::TieredStorageFile, memmap2::MmapOptions,
119+
super::*, crate::tiered_storage::file::TieredWritableFile, memmap2::MmapOptions,
120120
std::fs::OpenOptions, tempfile::TempDir,
121121
};
122122

@@ -139,7 +139,7 @@ mod tests {
139139
};
140140

141141
{
142-
let file = TieredStorageFile::new_writable(&path).unwrap();
142+
let file = TieredWritableFile::new(&path).unwrap();
143143

144144
let mut owners_table = OwnersTable::default();
145145
addresses.iter().for_each(|owner_address| {

0 commit comments

Comments
 (0)