diff --git a/core/storage/btree.rs b/core/storage/btree.rs index 178beb564..8e41de29b 100644 --- a/core/storage/btree.rs +++ b/core/storage/btree.rs @@ -363,7 +363,6 @@ impl BTreeCursor { let cell = contents.cell_get( cell_idx, - self.pager.clone(), payload_overflow_threshold_max(contents.page_type(), self.usable_space() as u16), payload_overflow_threshold_min(contents.page_type(), self.usable_space() as u16), self.usable_space(), @@ -465,7 +464,6 @@ impl BTreeCursor { let cell = contents.cell_get( cell_idx, - self.pager.clone(), payload_overflow_threshold_max(contents.page_type(), self.usable_space() as u16), payload_overflow_threshold_min(contents.page_type(), self.usable_space() as u16), self.usable_space(), @@ -590,7 +588,6 @@ impl BTreeCursor { for cell_idx in 0..contents.cell_count() { let cell = contents.cell_get( cell_idx, - self.pager.clone(), payload_overflow_threshold_max( contents.page_type(), self.usable_space() as u16, @@ -753,7 +750,6 @@ impl BTreeCursor { for cell_idx in 0..contents.cell_count() { match &contents.cell_get( cell_idx, - self.pager.clone(), payload_overflow_threshold_max( contents.page_type(), self.usable_space() as u16, @@ -886,7 +882,6 @@ impl BTreeCursor { if cell_idx < page.get_contents().cell_count() { if let BTreeCell::TableLeafCell(tbl_leaf) = page.get_contents().cell_get( cell_idx, - self.pager.clone(), payload_overflow_threshold_max(page_type, self.usable_space() as u16), payload_overflow_threshold_min(page_type, self.usable_space() as u16), self.usable_space(), @@ -1120,7 +1115,6 @@ impl BTreeCursor { let next_cell_divider = i + first_cell_divider - 1; pgno = match parent_contents.cell_get( next_cell_divider, - self.pager.clone(), payload_overflow_threshold_max( parent_contents.page_type(), self.usable_space() as u16, @@ -1691,7 +1685,6 @@ impl BTreeCursor { match page .cell_get( cell_idx, - self.pager.clone(), payload_overflow_threshold_max(page.page_type(), self.usable_space() as u16), payload_overflow_threshold_min(page.page_type(), self.usable_space() as u16), self.usable_space(), @@ -1905,7 +1898,6 @@ impl BTreeCursor { let cell = contents.cell_get( cell_idx, - self.pager.clone(), payload_overflow_threshold_max( contents.page_type(), self.usable_space() as u16, @@ -1988,7 +1980,6 @@ impl BTreeCursor { let leaf_cell_idx = self.stack.current_cell_index() as usize - 1; let predecessor_cell = leaf_contents.cell_get( leaf_cell_idx, - self.pager.clone(), payload_overflow_threshold_max( leaf_contents.page_type(), self.usable_space() as u16, @@ -2177,7 +2168,6 @@ impl BTreeCursor { } else { let equals = match &contents.cell_get( cell_idx, - self.pager.clone(), payload_overflow_threshold_max(contents.page_type(), self.usable_space() as u16), payload_overflow_threshold_min(contents.page_type(), self.usable_space() as u16), self.usable_space(), @@ -2351,7 +2341,6 @@ impl BTreeCursor { // Get the current cell let cell = contents.cell_get( cell_idx as usize, - Rc::clone(&self.pager), payload_overflow_threshold_max( contents.page_type(), self.usable_space() as u16, @@ -3404,6 +3393,7 @@ mod tests { use crate::Connection; use crate::{BufferPool, DatabaseStorage, WalFile, WalFileShared, WriteCompletion}; use std::cell::RefCell; + use std::mem::transmute; use std::ops::Deref; use std::panic; use std::rc::Rc; @@ -3563,7 +3553,6 @@ mod tests { let cell = contents .cell_get( cell_idx, - pager.clone(), payload_overflow_threshold_max(page_type, 4096), payload_overflow_threshold_min(page_type, 4096), cursor.usable_space(), @@ -3626,7 +3615,6 @@ mod tests { let cell = contents .cell_get( cell_idx, - pager.clone(), payload_overflow_threshold_max(page_type, 4096), payload_overflow_threshold_min(page_type, 4096), cursor.usable_space(), @@ -4032,7 +4020,7 @@ mod tests { // Create leaf cell pointing to start of overflow chain let leaf_cell = BTreeCell::TableLeafCell(TableLeafCell { _rowid: 1, - _payload: large_payload, + _payload: unsafe { transmute::<&[u8], &'static [u8]>(large_payload.as_slice()) }, first_overflow_page: Some(2), // Point to first overflow page }); @@ -4087,7 +4075,7 @@ mod tests { // Create leaf cell with no overflow pages let leaf_cell = BTreeCell::TableLeafCell(TableLeafCell { _rowid: 1, - _payload: small_payload, + _payload: unsafe { transmute::<&[u8], &'static [u8]>(small_payload.as_slice()) }, first_overflow_page: None, }); diff --git a/core/storage/sqlite3_ondisk.rs b/core/storage/sqlite3_ondisk.rs index d2f4c1ec8..7f0090aa4 100644 --- a/core/storage/sqlite3_ondisk.rs +++ b/core/storage/sqlite3_ondisk.rs @@ -558,7 +558,6 @@ impl PageContent { pub fn cell_get( &self, idx: usize, - pager: Rc, payload_overflow_threshold_max: usize, payload_overflow_threshold_min: usize, usable_size: usize, @@ -574,11 +573,11 @@ impl PageContent { let cell_pointer = cell_pointer_array_start + (idx * 2); let cell_pointer = self.read_u16(cell_pointer) as usize; + let static_buf: &'static [u8] = unsafe { std::mem::transmute::<&[u8], &'static [u8]>(buf) }; read_btree_cell( - buf, + static_buf, &self.page_type(), cell_pointer, - pager, payload_overflow_threshold_max, payload_overflow_threshold_min, usable_size, @@ -816,28 +815,29 @@ pub struct TableInteriorCell { #[derive(Debug, Clone)] pub struct TableLeafCell { pub _rowid: u64, - pub _payload: Vec, + pub _payload: &'static [u8], pub first_overflow_page: Option, } #[derive(Debug, Clone)] pub struct IndexInteriorCell { pub left_child_page: u32, - pub payload: Vec, + pub payload: &'static [u8], pub first_overflow_page: Option, } #[derive(Debug, Clone)] pub struct IndexLeafCell { - pub payload: Vec, + pub payload: &'static [u8], pub first_overflow_page: Option, } +/// read_btree_cell contructs a BTreeCell which is basically a wrapper around pointer to the payload of a cell. +/// buffer input "page" is static because we want the cell to point to the data in the page in case it has any payload. pub fn read_btree_cell( - page: &[u8], + page: &'static [u8], page_type: &PageType, pos: usize, - pager: Rc, max_local: usize, min_local: usize, usable_size: usize, @@ -856,7 +856,7 @@ pub fn read_btree_cell( let to_read = if overflows { to_read } else { page.len() - pos }; let (payload, first_overflow_page) = - read_payload(&page[pos..pos + to_read], payload_size as usize, pager); + read_payload(&page[pos..pos + to_read], payload_size as usize); Ok(BTreeCell::IndexInteriorCell(IndexInteriorCell { left_child_page, payload, @@ -884,7 +884,7 @@ pub fn read_btree_cell( let to_read = if overflows { to_read } else { page.len() - pos }; let (payload, first_overflow_page) = - read_payload(&page[pos..pos + to_read], payload_size as usize, pager); + read_payload(&page[pos..pos + to_read], payload_size as usize); Ok(BTreeCell::IndexLeafCell(IndexLeafCell { payload, first_overflow_page, @@ -902,7 +902,7 @@ pub fn read_btree_cell( let to_read = if overflows { to_read } else { page.len() - pos }; let (payload, first_overflow_page) = - read_payload(&page[pos..pos + to_read], payload_size as usize, pager); + read_payload(&page[pos..pos + to_read], payload_size as usize); Ok(BTreeCell::TableLeafCell(TableLeafCell { _rowid: rowid, _payload: payload, @@ -915,11 +915,12 @@ pub fn read_btree_cell( /// read_payload takes in the unread bytearray with the payload size /// and returns the payload on the page, and optionally the first overflow page number. #[allow(clippy::readonly_write_lock)] -fn read_payload(unread: &[u8], payload_size: usize, pager: Rc) -> (Vec, Option) { +fn read_payload(unread: &'static [u8], payload_size: usize) -> (&'static [u8], Option) { let cell_len = unread.len(); + // We will let overflow be constructed back if needed or requested. if payload_size <= cell_len { // fit within 1 page - (unread[..payload_size].to_vec(), None) + (&unread[..payload_size], None) } else { // overflow let first_overflow_page = u32::from_be_bytes([ @@ -928,34 +929,7 @@ fn read_payload(unread: &[u8], payload_size: usize, pager: Rc) -> (Vec 0); - let page; - loop { - // FIXME(pere): this looks terrible, what did i do lmao - let page_ref = pager.read_page(next_overflow as usize); - if let Ok(p) = page_ref { - page = p; - break; - } - } - let page = page.get(); - let contents = page.contents.as_mut().unwrap(); - - let to_read = left_to_read.min(usable_size - 4); - let buf = contents.as_ptr(); - payload.extend_from_slice(&buf[4..4 + to_read]); - - next_overflow = contents.read_u32(0); - left_to_read -= to_read; - } - assert_eq!(left_to_read, 0); - - (payload, Some(first_overflow_page)) + (&unread[..cell_len - 4], Some(first_overflow_page)) } } diff --git a/core/vdbe/mod.rs b/core/vdbe/mod.rs index 40b60f6e2..742f072b0 100644 --- a/core/vdbe/mod.rs +++ b/core/vdbe/mod.rs @@ -392,7 +392,6 @@ impl Program { buff } - #[instrument(skip_all)] pub fn step( &self, state: &mut ProgramState, diff --git a/tests/integration/common.rs b/tests/integration/common.rs index 0f0d550b9..a034b36ae 100644 --- a/tests/integration/common.rs +++ b/tests/integration/common.rs @@ -4,6 +4,9 @@ use std::path::PathBuf; use std::rc::Rc; use std::sync::Arc; use tempfile::TempDir; +use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::util::SubscriberInitExt; +use tracing_subscriber::EnvFilter; #[allow(dead_code)] pub struct TempDatabase { @@ -90,6 +93,17 @@ pub(crate) fn compare_string(a: impl AsRef, b: impl AsRef) { } } +pub fn maybe_setup_tracing() { + let _ = tracing_subscriber::registry() + .with( + tracing_subscriber::fmt::layer() + .with_ansi(false) + .with_line_number(true) + .with_thread_ids(true), + ) + .with(EnvFilter::from_default_env()) + .try_init(); +} #[cfg(test)] mod tests { use super::TempDatabase; diff --git a/tests/integration/query_processing/test_write_path.rs b/tests/integration/query_processing/test_write_path.rs index dd313cfea..724bb5d0c 100644 --- a/tests/integration/query_processing/test_write_path.rs +++ b/tests/integration/query_processing/test_write_path.rs @@ -1,4 +1,4 @@ -use crate::common; +use crate::common::{self, maybe_setup_tracing}; use crate::common::{compare_string, do_flush, TempDatabase}; use limbo_core::{Connection, StepResult}; use log::debug; @@ -157,6 +157,7 @@ fn test_sequential_overflow_page() -> anyhow::Result<()> { #[test_log::test] fn test_sequential_write() -> anyhow::Result<()> { let _ = env_logger::try_init(); + maybe_setup_tracing(); let tmp_db = TempDatabase::new_with_rusqlite("CREATE TABLE test (x INTEGER PRIMARY KEY);"); let conn = tmp_db.connect_limbo(); diff --git a/tests/integration/wal/test_wal.rs b/tests/integration/wal/test_wal.rs index 5a92e01c3..b76ac1773 100644 --- a/tests/integration/wal/test_wal.rs +++ b/tests/integration/wal/test_wal.rs @@ -1,12 +1,9 @@ -use crate::common::{do_flush, TempDatabase}; +use crate::common::{do_flush, maybe_setup_tracing, TempDatabase}; use limbo_core::{Connection, LimboError, Result, StepResult}; use std::cell::RefCell; use std::ops::Deref; use std::rc::Rc; use std::sync::{Arc, Mutex}; -use tracing_subscriber::layer::SubscriberExt; -use tracing_subscriber::util::SubscriberInitExt; -use tracing_subscriber::EnvFilter; #[allow(clippy::arc_with_non_send_sync)] #[test] @@ -116,17 +113,6 @@ fn test_wal_1_writer_1_reader() -> Result<()> { Ok(()) } -fn maybe_setup_tracing() { - let _ = tracing_subscriber::registry() - .with( - tracing_subscriber::fmt::layer() - .with_line_number(true) - .with_thread_ids(true), - ) - .with(EnvFilter::from_default_env()) - .try_init(); -} - /// Execute a statement and get strings result pub(crate) fn execute_and_get_strings( tmp_db: &TempDatabase,