From 35bd70f2e2caebfe00cff60e8d9254d6c15ac2ba Mon Sep 17 00:00:00 2001 From: Ian L Date: Tue, 15 Apr 2025 22:29:23 +0100 Subject: [PATCH 1/8] Experiment w/ removing lifetimes from `Transaction` It is a nice primitive, but we might not benefit much from it. Realistically, we will not be cloning the `Database` often, and even when we do, the costs of doing it is low relative to the performance gains from TrieDB overall. --- src/database.rs | 30 ++++++++++++++++-------------- src/storage/engine.rs | 2 +- src/transaction.rs | 27 +++++++++++++-------------- tests/ethereum_execution_spec.rs | 3 ++- 4 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/database.rs b/src/database.rs index 471c1fe6..33b6690f 100644 --- a/src/database.rs +++ b/src/database.rs @@ -9,7 +9,7 @@ use crate::{ use alloy_primitives::B256; use alloy_trie::EMPTY_ROOT_HASH; use parking_lot::RwLock; -use std::fs::File; +use std::{fs::File, sync::Arc}; #[derive(Debug)] pub struct Database { @@ -73,11 +73,12 @@ impl Database { }; let db = Self::new(metadata, StorageEngine::new(page_manager, orphan_manager)); + let db_arc = Arc::new(db); - let tx = db.begin_rw().unwrap(); + let tx = db_arc.begin_rw().unwrap(); tx.commit().unwrap(); - Ok(db) + Ok(Arc::try_unwrap(db_arc).unwrap()) } pub fn open(file_path: &str) -> Result { @@ -135,7 +136,7 @@ impl Database { } } - pub fn begin_rw(&self) -> Result, TransactionError> { + pub fn begin_rw(self: &Arc) -> Result, TransactionError> { let mut transaction_manager = self.inner.transaction_manager.write(); let storage_engine = self.inner.storage_engine.read(); let metadata = self.inner.metadata.read().next(); @@ -144,16 +145,16 @@ impl Database { storage_engine.unlock(min_snapshot_id - 1); } let context = TransactionContext::new(metadata); - Ok(Transaction::new(context, self, None)) + Ok(Transaction::new(context, Arc::clone(self), None)) } - pub fn begin_ro(&self) -> Result, TransactionError> { + pub fn begin_ro(self: &Arc) -> Result, TransactionError> { let mut transaction_manager = self.inner.transaction_manager.write(); - let storage_engine = self.inner.storage_engine.read(); + let storage_engine = self.inner.storage_engine.read().clone(); let metadata = self.inner.metadata.read().clone(); transaction_manager.begin_ro(metadata.snapshot_id)?; let context = TransactionContext::new(metadata); - Ok(Transaction::new(context, self, Some(storage_engine))) + Ok(Transaction::new(context, Arc::clone(self), Some(storage_engine))) } pub fn state_root(&self) -> B256 { @@ -238,7 +239,7 @@ mod tests { fn test_set_get_account() { let tmp_dir = TempDir::new("test_db").unwrap(); let file_path = tmp_dir.path().join("test.db").to_str().unwrap().to_owned(); - let db = Database::create(file_path.as_str()).unwrap(); + let db = Arc::new(Database::create(file_path.as_str()).unwrap()); let address = address!("0xd8da6bf26964af9d7eed9e03e53415d37aa96045"); @@ -354,7 +355,7 @@ mod tests { fn test_data_persistence() { let tmp_dir = TempDir::new("test_db").unwrap(); let file_path = tmp_dir.path().join("test.db").to_str().unwrap().to_owned(); - let db = Database::create(&file_path).unwrap(); + let db = Arc::new(Database::create(&file_path).unwrap()); let address1 = address!("0xd8da6bf26964af9d7eed9e03e53415d37aa96045"); let account1 = Account::new(1, U256::from(100), EMPTY_ROOT_HASH, KECCAK_EMPTY); @@ -363,9 +364,9 @@ mod tests { tx.set_account(AddressPath::for_address(address1), Some(account1.clone())).unwrap(); tx.commit().unwrap(); - db.close().unwrap(); + Arc::try_unwrap(db).unwrap().close().unwrap(); - let db = Database::open(file_path.as_str()).unwrap(); + let db = Arc::new(Database::open(file_path.as_str()).unwrap()); let tx = db.begin_ro().unwrap(); let account = tx.get_account(AddressPath::for_address(address1)).unwrap().unwrap(); assert_eq!(account, account1); @@ -378,9 +379,9 @@ mod tests { tx.set_account(AddressPath::for_address(address2), Some(account2.clone())).unwrap(); tx.commit().unwrap(); - db.close().unwrap(); + Arc::try_unwrap(db).unwrap().close().unwrap(); - let db = Database::open(&file_path).unwrap(); + let db = Arc::new(Database::open(&file_path).unwrap()); let tx = db.begin_ro().unwrap(); let account = tx.get_account(AddressPath::for_address(address1)).unwrap().unwrap(); @@ -390,3 +391,4 @@ mod tests { assert_eq!(account, account2); } } + diff --git a/src/storage/engine.rs b/src/storage/engine.rs index 20a6ae27..747e8ed0 100644 --- a/src/storage/engine.rs +++ b/src/storage/engine.rs @@ -36,7 +36,7 @@ use super::value::Value; /// which could be memory-mapped files, in-memory storage, or other implementations. /// /// All operations are thread-safe through the use of a read-write lock around the inner state. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct StorageEngine { inner: Arc>, } diff --git a/src/transaction.rs b/src/transaction.rs index 820963cb..6054f0f5 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -13,10 +13,9 @@ use alloy_primitives::{StorageValue, B256}; use alloy_trie::Nibbles; pub use error::TransactionError; pub use manager::TransactionManager; -use parking_lot::RwLockReadGuard; use reth_trie_common::MultiProof; use sealed::sealed; -use std::{collections::HashMap, fmt::Debug}; +use std::{collections::HashMap, fmt::Debug, sync::Arc}; #[sealed] pub trait TransactionKind: Debug {} @@ -36,25 +35,25 @@ impl TransactionKind for RO {} // Compile-time assertion to ensure that `Transaction` is `Send` const _: fn() = || { fn consumer() {} - consumer::>(); - consumer::>(); + consumer::>(); + consumer::>(); }; #[derive(Debug)] -pub struct Transaction<'tx, K: TransactionKind> { +pub struct Transaction { committed: bool, context: TransactionContext, - database: &'tx Database, + database: Arc, pending_changes: HashMap>, - _lock: Option>, + _lock: Option, _marker: std::marker::PhantomData, } -impl<'tx, K: TransactionKind> Transaction<'tx, K> { +impl Transaction { pub(crate) fn new( context: TransactionContext, - database: &'tx Database, - lock: Option>, + database: Arc, + lock: Option, ) -> Self { Self { committed: false, @@ -67,7 +66,7 @@ impl<'tx, K: TransactionKind> Transaction<'tx, K> { } pub fn get_account( - &'tx self, + &self, address_path: AddressPath, ) -> Result, TransactionError> { let storage_engine = self.database.inner.storage_engine.read(); @@ -112,7 +111,7 @@ impl<'tx, K: TransactionKind> Transaction<'tx, K> { } } -impl Transaction<'_, RW> { +impl Transaction { pub fn set_account( &mut self, address_path: AddressPath, @@ -182,7 +181,7 @@ impl Transaction<'_, RW> { } } -impl Transaction<'_, RO> { +impl Transaction { pub fn commit(mut self) -> Result<(), TransactionError> { let mut transaction_manager = self.database.inner.transaction_manager.write(); transaction_manager.remove_transaction(self.context.metadata.snapshot_id, false)?; @@ -192,7 +191,7 @@ impl Transaction<'_, RO> { } } -impl Drop for Transaction<'_, K> { +impl Drop for Transaction { fn drop(&mut self) { // TODO: panic if the transaction is not committed } diff --git a/tests/ethereum_execution_spec.rs b/tests/ethereum_execution_spec.rs index 4b481782..a2d7a71e 100644 --- a/tests/ethereum_execution_spec.rs +++ b/tests/ethereum_execution_spec.rs @@ -15,6 +15,7 @@ use triedb::{ path::{AddressPath, StoragePath}, Database, }; +use std::sync::Arc; use walkdir::WalkDir; #[test] @@ -34,7 +35,7 @@ fn run_ethereum_execution_spec_state_tests() { .as_str() .replace("/", "_")[0..min(test_case_name.len(), 100)]; let file_path = tmp_dir.path().join(database_file_name).to_str().unwrap().to_owned(); - let test_database = Database::create(file_path.as_str()).unwrap(); + let test_database = Arc::new(Database::create(file_path.as_str()).unwrap()); // will track accounts and storage that need to be deleted. this is essentially the // "diff" between the pre state and post state. From 64af9a8087e5edc5e17d1f8db9bb771821725f11 Mon Sep 17 00:00:00 2001 From: Ian L Date: Tue, 15 Apr 2025 22:33:55 +0100 Subject: [PATCH 2/8] Fix formatting --- src/database.rs | 1 - tests/ethereum_execution_spec.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/database.rs b/src/database.rs index 33b6690f..e9e0a7b4 100644 --- a/src/database.rs +++ b/src/database.rs @@ -391,4 +391,3 @@ mod tests { assert_eq!(account, account2); } } - diff --git a/tests/ethereum_execution_spec.rs b/tests/ethereum_execution_spec.rs index a2d7a71e..709cd8e5 100644 --- a/tests/ethereum_execution_spec.rs +++ b/tests/ethereum_execution_spec.rs @@ -8,6 +8,7 @@ use std::{ cmp::min, collections::{HashMap, HashSet}, str::FromStr, + sync::Arc, }; use tempdir::TempDir; use triedb::{ @@ -15,7 +16,6 @@ use triedb::{ path::{AddressPath, StoragePath}, Database, }; -use std::sync::Arc; use walkdir::WalkDir; #[test] From 37e35423b6fd588684a2f04929512446edc24cb1 Mon Sep 17 00:00:00 2001 From: Ian L Date: Tue, 15 Apr 2025 22:37:57 +0100 Subject: [PATCH 3/8] Fix benches --- benches/benchmark_common.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/benches/benchmark_common.rs b/benches/benchmark_common.rs index 3c6cca0e..69738ff0 100644 --- a/benches/benchmark_common.rs +++ b/benches/benchmark_common.rs @@ -1,6 +1,7 @@ use alloy_primitives::{Address, StorageKey, StorageValue, U256}; use alloy_trie::{EMPTY_ROOT_HASH, KECCAK_EMPTY}; use rand::prelude::*; +use std::sync::Arc; use tempdir::TempDir; use triedb::{ account::Account, @@ -15,10 +16,10 @@ pub fn generate_random_address(rng: &mut StdRng) -> AddressPath { AddressPath::for_address(addr) } -pub fn setup_database(size: usize) -> (TempDir, Database) { +pub fn setup_database(size: usize) -> (TempDir, Arc) { let dir = TempDir::new("triedb_bench").unwrap(); let db_path = dir.path().join("db"); - let db = Database::create(db_path.to_str().unwrap()).unwrap(); + let db = Arc::new(Database::create(db_path.to_str().unwrap()).unwrap()); // Populate database with initial accounts let mut rng = StdRng::seed_from_u64(42); @@ -38,10 +39,10 @@ pub fn setup_database(size: usize) -> (TempDir, Database) { (dir, db) } -pub fn setup_database_with_storage(size: usize) -> (TempDir, Database) { +pub fn setup_database_with_storage(size: usize) -> (TempDir, Arc) { let dir = TempDir::new("triedb_bench_storage").unwrap(); let db_path = dir.path().join("db"); - let db = Database::create(db_path.to_str().unwrap()).unwrap(); + let db = Arc::new(Database::create(db_path.to_str().unwrap()).unwrap()); // Populate database with initial accounts let mut rng = StdRng::seed_from_u64(42); From 9a09dc1b5dc5fe7952bad35c458acf1a76f80bda Mon Sep 17 00:00:00 2001 From: Joby Thundil Date: Mon, 12 May 2025 12:45:28 -0400 Subject: [PATCH 4/8] add fixes for reth side around error handling --- src/database.rs | 2 +- src/node.rs | 32 ++++++++++++++++---------------- src/page/manager.rs | 13 +++++++++++-- src/page/manager/mmap.rs | 22 +++++++++++++--------- src/storage/engine.rs | 7 ++++--- 5 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/database.rs b/src/database.rs index c41bfbef..8ad43704 100644 --- a/src/database.rs +++ b/src/database.rs @@ -45,7 +45,7 @@ impl Metadata { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub enum Error { PageError(PageError), CloseError(engine::Error), diff --git a/src/node.rs b/src/node.rs index ff4496cf..6517dfc6 100644 --- a/src/node.rs +++ b/src/node.rs @@ -53,7 +53,7 @@ pub enum Node { }, } -#[derive(Debug)] +#[derive(Clone, Debug)] pub enum NodeError { ChildrenUnsupported, MaxPrefixLengthExceeded, @@ -336,12 +336,12 @@ impl Value for Node { } Self::AccountLeaf { prefix, balance_rlp, nonce_rlp, storage_root, code_hash } => { let packed_prefix_length = prefix.len().div_ceil(2); - 2 + packed_prefix_length + - balance_rlp.len() + - nonce_rlp.len() + - storage_root.is_some() as usize * 37 + - (*code_hash != KECCAK_EMPTY) as usize * 32 // 2 bytes for flags and prefix - // length + 2 + packed_prefix_length + + balance_rlp.len() + + nonce_rlp.len() + + storage_root.is_some() as usize * 37 + + (*code_hash != KECCAK_EMPTY) as usize * 32 // 2 bytes for flags and prefix + // length } Self::Branch { prefix, children } => { let (_, children_slot_size) = Self::children_slot_size(children); @@ -375,19 +375,19 @@ impl Value for Node { Self::AccountLeaf { prefix, balance_rlp, nonce_rlp, code_hash, storage_root } => { let prefix_length = prefix.len(); let packed_prefix_length = prefix.len().div_ceil(2); - let total_size = 2 + - packed_prefix_length + - balance_rlp.len() + - nonce_rlp.len() + - storage_root.is_some() as usize * 37 + - (*code_hash != KECCAK_EMPTY) as usize * 32; + let total_size = 2 + + packed_prefix_length + + balance_rlp.len() + + nonce_rlp.len() + + storage_root.is_some() as usize * 37 + + (*code_hash != KECCAK_EMPTY) as usize * 32; if buf.len() < total_size { return Err(value::Error::InvalidEncoding); } - let flags = 1 | - ((storage_root.is_some() as u8) << 7) | - (((*code_hash != KECCAK_EMPTY) as u8) << 6); + let flags = 1 + | ((storage_root.is_some() as u8) << 7) + | (((*code_hash != KECCAK_EMPTY) as u8) << 6); buf[0] = flags; buf[1] = prefix_length as u8; diff --git a/src/page/manager.rs b/src/page/manager.rs index 073bb322..2e3afcba 100644 --- a/src/page/manager.rs +++ b/src/page/manager.rs @@ -1,3 +1,6 @@ +use std::io; +use std::sync::Arc; + pub(super) mod mmap; pub(super) mod options; @@ -5,8 +8,14 @@ pub(super) mod options; /// Currently we use 4 bytes for page ids, which implies a maximum of 16TB of data. pub type PageId = u32; +impl From for PageError { + fn from(error: io::Error) -> Self { + Self::IO(error.into()) + } +} + /// Represents various errors that might arise from page operations. -#[derive(Debug)] +#[derive(Clone, Debug)] pub enum PageError { PageNotFound(PageId), OutOfBounds(PageId), @@ -16,7 +25,7 @@ pub enum PageError { NoFreeCells, PageIsFull, PageSplitLimitReached, - IO(std::io::Error), + IO(Arc), InvalidValue, InvalidPageContents(PageId), // TODO: add more errors here for other cases. diff --git a/src/page/manager/mmap.rs b/src/page/manager/mmap.rs index f39cc56c..4fe6d3d7 100644 --- a/src/page/manager/mmap.rs +++ b/src/page/manager/mmap.rs @@ -3,7 +3,7 @@ use crate::{ snapshot::SnapshotId, }; use memmap2::{Advice, MmapMut, MmapOptions}; -use std::{fs::File, path::Path}; +use std::{fs::File, path::Path, sync::Arc}; // Manages pages in a memory mapped file. #[derive(Debug)] @@ -36,7 +36,7 @@ impl PageManager { opts: &PageManagerOptions, path: impl AsRef, ) -> Result { - let file = opts.open_options.open(path).map_err(PageError::IO)?; + let file = opts.open_options.open(path)?; Self::from_file_with_options(opts, file) } @@ -73,11 +73,15 @@ impl PageManager { // SAFETY: we assume that we have full ownership of the file, even though in practice // there's no way to guarantee it - let mmap = - unsafe { MmapOptions::new().len(mmap_len).map_mut(&file).map_err(PageError::IO)? }; - mmap.advise(Advice::Random).map_err(PageError::IO)?; - - let file_len = file.metadata().map_err(PageError::IO)?.len(); + let mmap = unsafe { + MmapOptions::new() + .len(mmap_len) + .map_mut(&file) + .map_err(|err| PageError::IO(Arc::new(err)))? + }; + mmap.advise(Advice::Random)?; + + let file_len = file.metadata()?.len(); let min_file_len = (opts.page_count as u64) * (Page::SIZE as u64); assert!( file_len >= min_file_len, @@ -154,7 +158,7 @@ impl PageManager { assert!(new_len > cur_len, "reached max capacity"); - self.file.set_len(new_len).map_err(PageError::IO)?; + self.file.set_len(new_len)?; self.file_len = new_len; Ok(()) } @@ -189,7 +193,7 @@ impl PageManager { /// Syncs pages to the backing file. pub fn commit(&mut self) -> Result<(), PageError> { - self.mmap.flush().map_err(PageError::IO) + Ok(self.mmap.flush()?) } } diff --git a/src/storage/engine.rs b/src/storage/engine.rs index dbec8680..42d1d350 100644 --- a/src/storage/engine.rs +++ b/src/storage/engine.rs @@ -22,6 +22,7 @@ use std::{ cmp::{max, Ordering}, fmt::Debug, io, + sync::Arc, }; /// The [StorageEngine] is responsible for managing the storage of data in the database. @@ -1784,9 +1785,9 @@ impl StorageEngine { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub enum Error { - IO(io::Error), + IO(Arc), NodeError(NodeError), PageError(PageError), InvalidCommonPrefixIndex, @@ -1809,7 +1810,7 @@ impl From for Error { impl From for Error { fn from(error: io::Error) -> Self { - Self::IO(error) + Self::IO(error.into()) } } From e8abd4eea24f67bdbb6ee670e42e1d52261bc8f5 Mon Sep 17 00:00:00 2001 From: Joby Thundil Date: Tue, 27 May 2025 21:50:16 -0400 Subject: [PATCH 5/8] try making commit take reference --- src/database.rs | 2 +- src/transaction.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/database.rs b/src/database.rs index 8ad43704..9f0ac372 100644 --- a/src/database.rs +++ b/src/database.rs @@ -74,7 +74,7 @@ impl Database { let db = Self::new(metadata, StorageEngine::new(page_manager, orphan_manager)); let db_arc = Arc::new(db); - let tx = db_arc.begin_rw().unwrap(); + let mut tx = db_arc.begin_rw().unwrap(); tx.commit().unwrap(); Ok(Arc::try_unwrap(db_arc).unwrap()) diff --git a/src/transaction.rs b/src/transaction.rs index 0cbd7cfb..7d30a7e9 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -153,7 +153,7 @@ impl Transaction { Ok(()) } - pub fn commit(mut self) -> Result<(), TransactionError> { + pub fn commit(&mut self) -> Result<(), TransactionError> { let mut storage_engine = self.database.inner.storage_engine.write(); let mut changes = self.pending_changes.drain().collect::)>>(); From a642a26132ec05b99870dce289ad02d6f71a78ac Mon Sep 17 00:00:00 2001 From: Joby Thundil Date: Wed, 4 Jun 2025 16:21:20 -0400 Subject: [PATCH 6/8] format --- Cargo.toml | 2 +- src/node.rs | 30 +++++++++++++++--------------- src/storage/engine.rs | 8 ++++---- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b5866666..4f9b0d00 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ metrics-derive = "0.1.0" metrics = "0.24.1" zerocopy = { version = "0.8.24", features = ["derive"] } reth-trie-common = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } -reth-primitives-traits = { path = "/Users/jobythundil/Documents/coinbase/github.com/base/reth-triedb/crates/primitives-traits" } +reth-primitives-traits = { git = "https://github.com/paradigmxyz/reth", tag = "v1.3.8" } parking_lot = { version = "0.12.3", features = ["send_guard"] } fxhash = "0.2.1" static_assertions = "1.1.0" diff --git a/src/node.rs b/src/node.rs index 6517dfc6..1e8f14f0 100644 --- a/src/node.rs +++ b/src/node.rs @@ -336,12 +336,12 @@ impl Value for Node { } Self::AccountLeaf { prefix, balance_rlp, nonce_rlp, storage_root, code_hash } => { let packed_prefix_length = prefix.len().div_ceil(2); - 2 + packed_prefix_length - + balance_rlp.len() - + nonce_rlp.len() - + storage_root.is_some() as usize * 37 - + (*code_hash != KECCAK_EMPTY) as usize * 32 // 2 bytes for flags and prefix - // length + 2 + packed_prefix_length + + balance_rlp.len() + + nonce_rlp.len() + + storage_root.is_some() as usize * 37 + + (*code_hash != KECCAK_EMPTY) as usize * 32 // 2 bytes for flags and prefix + // length } Self::Branch { prefix, children } => { let (_, children_slot_size) = Self::children_slot_size(children); @@ -375,19 +375,19 @@ impl Value for Node { Self::AccountLeaf { prefix, balance_rlp, nonce_rlp, code_hash, storage_root } => { let prefix_length = prefix.len(); let packed_prefix_length = prefix.len().div_ceil(2); - let total_size = 2 - + packed_prefix_length - + balance_rlp.len() - + nonce_rlp.len() - + storage_root.is_some() as usize * 37 - + (*code_hash != KECCAK_EMPTY) as usize * 32; + let total_size = 2 + + packed_prefix_length + + balance_rlp.len() + + nonce_rlp.len() + + storage_root.is_some() as usize * 37 + + (*code_hash != KECCAK_EMPTY) as usize * 32; if buf.len() < total_size { return Err(value::Error::InvalidEncoding); } - let flags = 1 - | ((storage_root.is_some() as u8) << 7) - | (((*code_hash != KECCAK_EMPTY) as u8) << 6); + let flags = 1 | + ((storage_root.is_some() as u8) << 7) | + (((*code_hash != KECCAK_EMPTY) as u8) << 6); buf[0] = flags; buf[1] = prefix_length as u8; diff --git a/src/storage/engine.rs b/src/storage/engine.rs index da583f4d..b7b64f68 100644 --- a/src/storage/engine.rs +++ b/src/storage/engine.rs @@ -211,8 +211,8 @@ impl StorageEngine { if remaining_path.is_empty() { // cache the account location if it is a contract account if let TrieValue::Account(account) = node.value()? { - if account.storage_root != EMPTY_ROOT_HASH - && original_path_slice.len() == ADDRESS_PATH_LENGTH + if account.storage_root != EMPTY_ROOT_HASH && + original_path_slice.len() == ADDRESS_PATH_LENGTH { let original_path = Nibbles::from_nibbles_unchecked(original_path_slice); context @@ -958,8 +958,8 @@ impl StorageEngine { // 3. and add new cell pointer for the new leaf node (3 bytes) // when adding the new child, split the page. // FIXME: is it safe to split the page here if we've already modified the page? - if slotted_page.num_free_bytes() - < node_size_incr + new_node.size() + CELL_POINTER_SIZE + if slotted_page.num_free_bytes() < + node_size_incr + new_node.size() + CELL_POINTER_SIZE { self.split_page(context, slotted_page)?; return Err(Error::PageSplit(0)); From 3be583c41af620fc590d919f8660cb00fe844efc Mon Sep 17 00:00:00 2001 From: Joby Thundil Date: Wed, 4 Jun 2025 16:26:41 -0400 Subject: [PATCH 7/8] finish merge --- src/page/manager/mmap.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/page/manager/mmap.rs b/src/page/manager/mmap.rs index a364f193..c32b1364 100644 --- a/src/page/manager/mmap.rs +++ b/src/page/manager/mmap.rs @@ -3,11 +3,7 @@ use crate::{ snapshot::SnapshotId, }; use memmap2::{Advice, MmapMut, MmapOptions}; -<<<<<<< HEAD use std::{fs::File, path::Path, sync::Arc}; -======= -use std::{fs::File, io, path::Path}; ->>>>>>> main // Manages pages in a memory mapped file. #[derive(Debug)] From 11c08fc171cded9b4ecc050492a388146b42d77e Mon Sep 17 00:00:00 2001 From: Joby Thundil Date: Wed, 4 Jun 2025 16:27:23 -0400 Subject: [PATCH 8/8] fix merge --- src/page/manager/mmap.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/page/manager/mmap.rs b/src/page/manager/mmap.rs index c32b1364..249ae840 100644 --- a/src/page/manager/mmap.rs +++ b/src/page/manager/mmap.rs @@ -3,7 +3,7 @@ use crate::{ snapshot::SnapshotId, }; use memmap2::{Advice, MmapMut, MmapOptions}; -use std::{fs::File, path::Path, sync::Arc}; +use std::{fs::File, io, path::Path, sync::Arc}; // Manages pages in a memory mapped file. #[derive(Debug)]