Skip to content

Commit

Permalink
[TieredStorage] byte_block::read_type (#32295)
Browse files Browse the repository at this point in the history
#### 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.
  • Loading branch information
yhchiang-sol authored Jun 28, 2023
1 parent 5624aaa commit 4cfdb37
Showing 1 changed file with 36 additions and 17 deletions.
53 changes: 36 additions & 17 deletions runtime/src/tiered_storage/byte_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,21 @@ impl ByteBlockWriter {
/// The util struct for reading byte blocks.
pub struct ByteBlockReader;

/// Reads the raw part of the input byte_block at the specified offset
/// as type T.
///
/// If `offset` + size_of::<T>() exceeds the size of the input byte_block,
/// then None will be returned.
pub fn read_type<T>(byte_block: &[u8], offset: usize) -> Option<&T> {
let (next, overflow) = offset.overflowing_add(std::mem::size_of::<T>());
if overflow || next > byte_block.len() {
return None;
}
let ptr = byte_block[offset..].as_ptr() as *const T;
debug_assert!(ptr as usize % std::mem::align_of::<T>() == 0);
Some(unsafe { &*ptr })
}

impl ByteBlockReader {
/// Decode the input byte array using the specified format.
///
Expand Down Expand Up @@ -143,7 +158,7 @@ mod tests {
solana_sdk::{hash::Hash, stake_history::Epoch},
};

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

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

let (value_from_buffer, next) = read_type::<u32>(&decoded_buffer, 0);
let (value_from_buffer, next) = read_type_unaligned::<u32>(&decoded_buffer, 0);
assert_eq!(value, value_from_buffer);

if format != AccountBlockFormat::AlignedRaw {
Expand Down Expand Up @@ -250,25 +265,29 @@ mod tests {
);

// verify meta1 and its data
let (meta1_from_buffer, next1) = read_type::<TestMetaStruct>(&decoded_buffer, 0);
let (meta1_from_buffer, next1) = read_type_unaligned::<TestMetaStruct>(&decoded_buffer, 0);
assert_eq!(test_metas[0], meta1_from_buffer);
assert_eq!(
test_data1,
decoded_buffer[next1..][..meta1_from_buffer.data_len]
);

// verify meta2 and its data
let (meta2_from_buffer, next2) =
read_type::<TestMetaStruct>(&decoded_buffer, next1 + meta1_from_buffer.data_len);
let (meta2_from_buffer, next2) = read_type_unaligned::<TestMetaStruct>(
&decoded_buffer,
next1 + meta1_from_buffer.data_len,
);
assert_eq!(test_metas[1], meta2_from_buffer);
assert_eq!(
test_data2,
decoded_buffer[next2..][..meta2_from_buffer.data_len]
);

// verify meta3 and its data
let (meta3_from_buffer, next3) =
read_type::<TestMetaStruct>(&decoded_buffer, next2 + meta2_from_buffer.data_len);
let (meta3_from_buffer, next3) = read_type_unaligned::<TestMetaStruct>(
&decoded_buffer,
next2 + meta2_from_buffer.data_len,
);
assert_eq!(test_metas[2], meta3_from_buffer);
assert_eq!(
test_data3,
Expand Down Expand Up @@ -337,23 +356,23 @@ mod tests {
let mut offset = 0;
for opt_fields in &opt_fields_vec {
if let Some(expected_rent_epoch) = opt_fields.rent_epoch {
let (rent_epoch, next) = read_type::<Epoch>(&decoded_buffer, offset);
assert_eq!(rent_epoch, expected_rent_epoch);
let rent_epoch = read_type::<Epoch>(&decoded_buffer, offset).unwrap();
assert_eq!(*rent_epoch, expected_rent_epoch);
verified_count += 1;
offset = next;
offset += std::mem::size_of::<Epoch>();
}
if let Some(expected_hash) = opt_fields.account_hash {
let (hash, next) = read_type::<Hash>(&decoded_buffer, offset);
assert_eq!(hash, expected_hash);
let hash = read_type::<Hash>(&decoded_buffer, offset).unwrap();
assert_eq!(hash, &expected_hash);
verified_count += 1;
offset = next;
offset += std::mem::size_of::<Hash>();
}
if let Some(expected_write_version) = opt_fields.write_version {
let (write_version, next) =
read_type::<StoredMetaWriteVersion>(&decoded_buffer, offset);
assert_eq!(write_version, expected_write_version);
let write_version =
read_type::<StoredMetaWriteVersion>(&decoded_buffer, offset).unwrap();
assert_eq!(*write_version, expected_write_version);
verified_count += 1;
offset = next;
offset += std::mem::size_of::<StoredMetaWriteVersion>();
}
}

Expand Down

0 comments on commit 4cfdb37

Please sign in to comment.