Skip to content

Commit

Permalink
parsing more pages.
Browse files Browse the repository at this point in the history
  • Loading branch information
Codetector1374 committed Aug 4, 2024
1 parent 27aa448 commit d51f8f7
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 7 deletions.
69 changes: 69 additions & 0 deletions src/innodb/page/lob/data_page.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use anyhow::{anyhow, Result};

use crate::innodb::{page::{Page, PageType}, InnoDBError};

#[derive(Debug, Clone)]
pub struct LobDataHeader {
pub version: u8,
pub data_len: u32,
pub trx_id: u64, // 6 bytes
}

impl LobDataHeader {
pub fn size() -> usize {
1 + 4 + 6
}

pub fn try_from_bytes(buf: &[u8]) -> Result<Self> {
if buf.len() < 11 {
return Err(anyhow!("Buffer too short for LobDataHeader"));
}

let version = buf[0];
let data_len = u32::from_be_bytes(buf[1..5].try_into()?);

// trx_id is 6 bytes, so we need to pad it with two zero bytes for u64
let trx_id = u64::from_be_bytes([0, 0, buf[5], buf[6], buf[7], buf[8], buf[9], buf[10]]);

Ok(LobDataHeader {
version,
data_len,
trx_id,
})
}
}

#[derive(Debug)]
pub struct LobData<'a> {
pub page: &'a Page<'a>,
pub header: LobDataHeader,
}

impl <'a> LobData<'a> {
pub fn try_from_page(p: &'a Page<'a>) -> Result<Self> {
match p.header.page_type {
PageType::LobData => Ok(LobData{
header: LobDataHeader::try_from_bytes(p.body())?,
page: p,
}),
_ => Err(anyhow!(InnoDBError::InvalidPageType {
expected: PageType::LobData,
has: p.header.page_type
})),
}
}

pub fn read(&self, offset: usize, buf: &mut [u8]) -> usize {
let data_len = self.header.data_len as usize;
let data = &self.body()[..data_len];
assert!(offset < data.len(), "offset too large");
let data = &data[offset..];
let bytes_to_copy = std::cmp::min(buf.len(), data.len());
buf[..bytes_to_copy].copy_from_slice(&data[..bytes_to_copy]);
bytes_to_copy
}

pub fn body(&self) -> &[u8] {
&self.page.body()[LobDataHeader::size()..]
}
}
2 changes: 2 additions & 0 deletions src/innodb/page/lob/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use anyhow::{anyhow, Ok, Result};

use super::{Page, PageType};

pub mod data_page;

/*
* General Flow for reading extern records
*
Expand Down
20 changes: 13 additions & 7 deletions src/innodb/table/row.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ use std::{
};

use crate::innodb::{
buffer_manager::BufferManager,
buffer_manager::{self, BufferManager},
file_list::FileListInnerNode,
page::{
index::record::{Record, RECORD_HEADER_FIXED_LENGTH},
lob::{LobFirst, LobIndexEntry},
lob::{data_page::LobData, LobFirst, LobIndexEntry},
},
table::blob_header::ExternReference,
InnoDBError,
Expand Down Expand Up @@ -139,8 +139,9 @@ impl<'a> Row<'a> {
extern_header: &ExternReference,
buffer_mgr: &mut dyn BufferManager,
) -> Result<Box<[u8]>> {
let space_id = extern_header.space_id;
let first_page_number = extern_header.page_number;
let lob_first_page = buffer_mgr.open_page(extern_header.space_id, first_page_number)?;
let lob_first_page = buffer_mgr.open_page(space_id, first_page_number)?;
if lob_first_page.header.offset != extern_header.page_number {
return Err(anyhow!(InnoDBError::InvalidPage));
}
Expand All @@ -165,18 +166,23 @@ impl<'a> Row<'a> {
let node = LobIndexEntry::try_from_bytes(buf)?;
trace!("Index Node: {:#?}", node);

let mut bytes_read = 0usize;
if node.page_number == first_page_number {
let bytes_read = lob_first.read(page_offset, &mut output_buffer[filled..]);
filled += bytes_read;
page_offset = page_offset.saturating_sub(bytes_read);
bytes_read = lob_first.read(page_offset, &mut output_buffer[filled..]);
trace!(
"Read {} bytes from first page, in total expecting {} bytes",
bytes_read,
output_buffer.len()
);
} else {
// TODO: implemtn LobData
let page_guard = buffer_mgr.open_page(space_id, node.page_number)?;
let data_page = LobData::try_from_page(&page_guard)?;
trace!("Data page: {:#?}", data_page);
bytes_read = data_page.read(page_offset, &mut output_buffer[filled..]);
trace!("Read {} bytes from data page", bytes_read);
}
filled += bytes_read;
page_offset = page_offset.saturating_sub(bytes_read);

node_location = node.file_list_node.next;
}
Expand Down

0 comments on commit d51f8f7

Please sign in to comment.