Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit 4cfdb37

Browse files
authored
[TieredStorage] byte_block::read_type (#32295)
#### Summary of Changes This PR adds byte_block::read_type(), an util function that reads the raw part of the input byte block at the specified offset as type T. This function will be later used by the hot storage. #### Test Plan Modified existing unit tests to use byte_block::read_type() when the input byte block is properly aligned.
1 parent 5624aaa commit 4cfdb37

File tree

1 file changed

+36
-17
lines changed

1 file changed

+36
-17
lines changed

runtime/src/tiered_storage/byte_block.rs

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,21 @@ impl ByteBlockWriter {
115115
/// The util struct for reading byte blocks.
116116
pub struct ByteBlockReader;
117117

118+
/// Reads the raw part of the input byte_block at the specified offset
119+
/// as type T.
120+
///
121+
/// If `offset` + size_of::<T>() exceeds the size of the input byte_block,
122+
/// then None will be returned.
123+
pub fn read_type<T>(byte_block: &[u8], offset: usize) -> Option<&T> {
124+
let (next, overflow) = offset.overflowing_add(std::mem::size_of::<T>());
125+
if overflow || next > byte_block.len() {
126+
return None;
127+
}
128+
let ptr = byte_block[offset..].as_ptr() as *const T;
129+
debug_assert!(ptr as usize % std::mem::align_of::<T>() == 0);
130+
Some(unsafe { &*ptr })
131+
}
132+
118133
impl ByteBlockReader {
119134
/// Decode the input byte array using the specified format.
120135
///
@@ -143,7 +158,7 @@ mod tests {
143158
solana_sdk::{hash::Hash, stake_history::Epoch},
144159
};
145160

146-
fn read_type<T>(buffer: &[u8], offset: usize) -> (T, usize) {
161+
fn read_type_unaligned<T>(buffer: &[u8], offset: usize) -> (T, usize) {
147162
let size = std::mem::size_of::<T>();
148163
let (next, overflow) = offset.overflowing_add(size);
149164
assert!(!overflow && next <= buffer.len());
@@ -170,7 +185,7 @@ mod tests {
170185

171186
assert_eq!(decoded_buffer.len(), mem::size_of::<u32>());
172187

173-
let (value_from_buffer, next) = read_type::<u32>(&decoded_buffer, 0);
188+
let (value_from_buffer, next) = read_type_unaligned::<u32>(&decoded_buffer, 0);
174189
assert_eq!(value, value_from_buffer);
175190

176191
if format != AccountBlockFormat::AlignedRaw {
@@ -250,25 +265,29 @@ mod tests {
250265
);
251266

252267
// verify meta1 and its data
253-
let (meta1_from_buffer, next1) = read_type::<TestMetaStruct>(&decoded_buffer, 0);
268+
let (meta1_from_buffer, next1) = read_type_unaligned::<TestMetaStruct>(&decoded_buffer, 0);
254269
assert_eq!(test_metas[0], meta1_from_buffer);
255270
assert_eq!(
256271
test_data1,
257272
decoded_buffer[next1..][..meta1_from_buffer.data_len]
258273
);
259274

260275
// verify meta2 and its data
261-
let (meta2_from_buffer, next2) =
262-
read_type::<TestMetaStruct>(&decoded_buffer, next1 + meta1_from_buffer.data_len);
276+
let (meta2_from_buffer, next2) = read_type_unaligned::<TestMetaStruct>(
277+
&decoded_buffer,
278+
next1 + meta1_from_buffer.data_len,
279+
);
263280
assert_eq!(test_metas[1], meta2_from_buffer);
264281
assert_eq!(
265282
test_data2,
266283
decoded_buffer[next2..][..meta2_from_buffer.data_len]
267284
);
268285

269286
// verify meta3 and its data
270-
let (meta3_from_buffer, next3) =
271-
read_type::<TestMetaStruct>(&decoded_buffer, next2 + meta2_from_buffer.data_len);
287+
let (meta3_from_buffer, next3) = read_type_unaligned::<TestMetaStruct>(
288+
&decoded_buffer,
289+
next2 + meta2_from_buffer.data_len,
290+
);
272291
assert_eq!(test_metas[2], meta3_from_buffer);
273292
assert_eq!(
274293
test_data3,
@@ -337,23 +356,23 @@ mod tests {
337356
let mut offset = 0;
338357
for opt_fields in &opt_fields_vec {
339358
if let Some(expected_rent_epoch) = opt_fields.rent_epoch {
340-
let (rent_epoch, next) = read_type::<Epoch>(&decoded_buffer, offset);
341-
assert_eq!(rent_epoch, expected_rent_epoch);
359+
let rent_epoch = read_type::<Epoch>(&decoded_buffer, offset).unwrap();
360+
assert_eq!(*rent_epoch, expected_rent_epoch);
342361
verified_count += 1;
343-
offset = next;
362+
offset += std::mem::size_of::<Epoch>();
344363
}
345364
if let Some(expected_hash) = opt_fields.account_hash {
346-
let (hash, next) = read_type::<Hash>(&decoded_buffer, offset);
347-
assert_eq!(hash, expected_hash);
365+
let hash = read_type::<Hash>(&decoded_buffer, offset).unwrap();
366+
assert_eq!(hash, &expected_hash);
348367
verified_count += 1;
349-
offset = next;
368+
offset += std::mem::size_of::<Hash>();
350369
}
351370
if let Some(expected_write_version) = opt_fields.write_version {
352-
let (write_version, next) =
353-
read_type::<StoredMetaWriteVersion>(&decoded_buffer, offset);
354-
assert_eq!(write_version, expected_write_version);
371+
let write_version =
372+
read_type::<StoredMetaWriteVersion>(&decoded_buffer, offset).unwrap();
373+
assert_eq!(*write_version, expected_write_version);
355374
verified_count += 1;
356-
offset = next;
375+
offset += std::mem::size_of::<StoredMetaWriteVersion>();
357376
}
358377
}
359378

0 commit comments

Comments
 (0)