Skip to content

Commit

Permalink
Split BPlusTreePageCodec
Browse files Browse the repository at this point in the history
  • Loading branch information
lewiszlw committed Feb 7, 2024
1 parent a57d620 commit 0828a60
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 69 deletions.
198 changes: 130 additions & 68 deletions bustubx/src/storage/codec/index_page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,8 @@ pub struct BPlusTreePageCodec;
impl BPlusTreePageCodec {
pub fn encode(page: &BPlusTreePage) -> Vec<u8> {
match page {
BPlusTreePage::Leaf(page) => {
let mut bytes = vec![];
bytes.extend(BPlusTreeLeafPageHeaderCodec::encode(&page.header));
for (tuple, rid) in page.array.iter() {
bytes.extend(TupleCodec::encode(tuple));
bytes.extend(RidCodec::encode(rid));
}
// make sure length of bytes is BUSTUBX_PAGE_SIZE
assert!(bytes.len() <= BUSTUBX_PAGE_SIZE);
bytes.extend(vec![0; BUSTUBX_PAGE_SIZE - bytes.len()]);
bytes
}

BPlusTreePage::Internal(page) => {
let mut bytes = vec![];
bytes.extend(BPlusTreeInternalPageHeaderCodec::encode(&page.header));
for (tuple, page_id) in page.array.iter() {
bytes.extend(TupleCodec::encode(tuple));
bytes.extend(CommonCodec::encode_u32(*page_id));
}
// make sure length of bytes is BUSTUBX_PAGE_SIZE
assert!(bytes.len() <= BUSTUBX_PAGE_SIZE);
bytes.extend(vec![0; BUSTUBX_PAGE_SIZE - bytes.len()]);
bytes
}
BPlusTreePage::Leaf(page) => BPlusTreeLeafPageCodec::encode(page),
BPlusTreePage::Internal(page) => BPlusTreeInternalPageCodec::encode(page),
}
}

Expand All @@ -48,60 +25,145 @@ impl BPlusTreePageCodec {
bytes.len()
)));
}
let mut left_bytes = bytes;

// not consume left_bytes
let (page_type, offset) = BPlusTreePageTypeCodec::decode(left_bytes)?;
let (page_type, _) = BPlusTreePageTypeCodec::decode(bytes)?;

match page_type {
BPlusTreePageType::LeafPage => {
let (header, offset) = BPlusTreeLeafPageHeaderCodec::decode(left_bytes)?;
let (page, offset) = BPlusTreeLeafPageCodec::decode(bytes, schema.clone())?;
Ok((BPlusTreePage::Leaf(page), offset))
}
BPlusTreePageType::InternalPage => {
let (page, offset) = BPlusTreeInternalPageCodec::decode(bytes, schema.clone())?;
Ok((BPlusTreePage::Internal(page), offset))
}
}
}
}

pub struct BPlusTreeLeafPageCodec;

impl BPlusTreeLeafPageCodec {
pub fn encode(page: &BPlusTreeLeafPage) -> Vec<u8> {
let mut bytes = vec![];
bytes.extend(BPlusTreeLeafPageHeaderCodec::encode(&page.header));
for (tuple, rid) in page.array.iter() {
bytes.extend(TupleCodec::encode(tuple));
bytes.extend(RidCodec::encode(rid));
}
// make sure length of bytes is BUSTUBX_PAGE_SIZE
assert!(bytes.len() <= BUSTUBX_PAGE_SIZE);
bytes.extend(vec![0; BUSTUBX_PAGE_SIZE - bytes.len()]);
bytes
}

pub fn decode(
bytes: &[u8],
schema: SchemaRef,
) -> BustubxResult<DecodedData<BPlusTreeLeafPage>> {
if bytes.len() != BUSTUBX_PAGE_SIZE {
return Err(BustubxError::Storage(format!(
"Index page size is not {} instead of {}",
BUSTUBX_PAGE_SIZE,
bytes.len()
)));
}
let mut left_bytes = bytes;

// not consume left_bytes
let (page_type, _) = BPlusTreePageTypeCodec::decode(left_bytes)?;

if matches!(page_type, BPlusTreePageType::LeafPage) {
let (header, offset) = BPlusTreeLeafPageHeaderCodec::decode(left_bytes)?;
left_bytes = &left_bytes[offset..];

let mut array = vec![];
for _ in 0..header.current_size {
let (tuple, offset) = TupleCodec::decode(left_bytes, schema.clone())?;
left_bytes = &left_bytes[offset..];

let mut array = vec![];
for _ in 0..header.current_size {
let (tuple, offset) = TupleCodec::decode(left_bytes, schema.clone())?;
left_bytes = &left_bytes[offset..];

let (rid, offset) = RidCodec::decode(left_bytes)?;
left_bytes = &left_bytes[offset..];

array.push((tuple, rid));
}

Ok((
BPlusTreePage::Leaf(BPlusTreeLeafPage {
schema,
header,
array,
}),
BUSTUBX_PAGE_SIZE,
))
let (rid, offset) = RidCodec::decode(left_bytes)?;
left_bytes = &left_bytes[offset..];

array.push((tuple, rid));
}
BPlusTreePageType::InternalPage => {
let (header, offset) = BPlusTreeInternalPageHeaderCodec::decode(left_bytes)?;

Ok((
BPlusTreeLeafPage {
schema,
header,
array,
},
BUSTUBX_PAGE_SIZE,
))
} else {
Err(BustubxError::Storage(
"Index page type must be leaf page".to_string(),
))
}
}
}

pub struct BPlusTreeInternalPageCodec;

impl BPlusTreeInternalPageCodec {
pub fn encode(page: &BPlusTreeInternalPage) -> Vec<u8> {
let mut bytes = vec![];
bytes.extend(BPlusTreeInternalPageHeaderCodec::encode(&page.header));
for (tuple, page_id) in page.array.iter() {
bytes.extend(TupleCodec::encode(tuple));
bytes.extend(CommonCodec::encode_u32(*page_id));
}
// make sure length of bytes is BUSTUBX_PAGE_SIZE
assert!(bytes.len() <= BUSTUBX_PAGE_SIZE);
bytes.extend(vec![0; BUSTUBX_PAGE_SIZE - bytes.len()]);
bytes
}

pub fn decode(
bytes: &[u8],
schema: SchemaRef,
) -> BustubxResult<DecodedData<BPlusTreeInternalPage>> {
if bytes.len() != BUSTUBX_PAGE_SIZE {
return Err(BustubxError::Storage(format!(
"Index page size is not {} instead of {}",
BUSTUBX_PAGE_SIZE,
bytes.len()
)));
}
let mut left_bytes = bytes;

// not consume left_bytes
let (page_type, _) = BPlusTreePageTypeCodec::decode(left_bytes)?;

if matches!(page_type, BPlusTreePageType::InternalPage) {
let (header, offset) = BPlusTreeInternalPageHeaderCodec::decode(left_bytes)?;
left_bytes = &left_bytes[offset..];

let mut array = vec![];
for _ in 0..header.current_size {
let (tuple, offset) = TupleCodec::decode(left_bytes, schema.clone())?;
left_bytes = &left_bytes[offset..];

let mut array = vec![];
for _ in 0..header.current_size {
let (tuple, offset) = TupleCodec::decode(left_bytes, schema.clone())?;
left_bytes = &left_bytes[offset..];

let (page_id, offset) = CommonCodec::decode_u32(left_bytes)?;
left_bytes = &left_bytes[offset..];

array.push((tuple, page_id));
}

Ok((
BPlusTreePage::Internal(BPlusTreeInternalPage {
schema,
header,
array,
}),
BUSTUBX_PAGE_SIZE,
))
let (page_id, offset) = CommonCodec::decode_u32(left_bytes)?;
left_bytes = &left_bytes[offset..];

array.push((tuple, page_id));
}

Ok((
BPlusTreeInternalPage {
schema,
header,
array,
},
BUSTUBX_PAGE_SIZE,
))
} else {
Err(BustubxError::Storage(
"Index page type must be internal page".to_string(),
))
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion bustubx/src/storage/codec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ mod table_page;
mod tuple;

pub use common::CommonCodec;
pub use index_page::BPlusTreePageTypeCodec;
pub use index_page::{
BPlusTreeInternalPageCodec, BPlusTreeLeafPageCodec, BPlusTreePageCodec, BPlusTreePageTypeCodec,

Check warning on line 9 in bustubx/src/storage/codec/mod.rs

View workflow job for this annotation

GitHub Actions / Test Suite

unused imports: `BPlusTreeInternalPageCodec`, `BPlusTreeLeafPageCodec`, `BPlusTreePageCodec`
};
pub use scalar::ScalarValueCodec;
pub use table_page::{
RidCodec, TablePageCodec, TablePageHeaderCodec, TablePageHeaderTupleInfoCodec,
Expand Down

0 comments on commit 0828a60

Please sign in to comment.