core: Switch RwLock<Arc<Pager>> to ArcSwap<Pager>

We don't actually need the RwLock locking capabilities, just the ability
to swap the instance.
This commit is contained in:
Pekka Enberg
2025-10-23 13:18:07 +03:00
parent 418fc90f8a
commit c3fb867173
13 changed files with 171 additions and 162 deletions

7
Cargo.lock generated
View File

@@ -227,6 +227,12 @@ version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]]
name = "arc-swap"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
[[package]]
name = "arrayref"
version = "0.3.9"
@@ -4904,6 +4910,7 @@ dependencies = [
"aes",
"aes-gcm",
"antithesis_sdk",
"arc-swap",
"bitflags 2.9.4",
"built",
"bytemuck",

View File

@@ -84,6 +84,7 @@ twox-hash = "2.1.1"
intrusive-collections = "0.9.7"
roaring = "0.11.2"
simsimd = "6.5.3"
arc-swap = "1.7"
[build-dependencies]
chrono = { workspace = true, default-features = false }

View File

@@ -2580,7 +2580,7 @@ mod tests {
let io: Arc<dyn IO> = Arc::new(MemoryIO::new());
let db = Database::open_file(io.clone(), ":memory:", false, false).unwrap();
let conn = db.connect().unwrap();
let pager = conn.pager.read().clone();
let pager = conn.pager.load().clone();
let _ = pager.io.block(|| pager.allocate_page1()).unwrap();

View File

@@ -270,7 +270,7 @@ mod tests {
let db = Database::open_file(io.clone(), ":memory:", false, false).unwrap();
let conn = db.connect().unwrap();
let pager = conn.pager.read().clone();
let pager = conn.pager.load().clone();
// Allocate page 1 first (database header)
let _ = pager.io.block(|| pager.allocate_page1());

View File

@@ -86,7 +86,7 @@ impl ProjectOperator {
for col in &self.columns {
// Use the internal connection's pager for expression evaluation
let internal_pager = self.internal_conn.pager.read().clone();
let internal_pager = self.internal_conn.pager.load().clone();
// Execute the compiled expression (handles both columns and complex expressions)
let result = col

View File

@@ -51,6 +51,7 @@ use crate::vdbe::explain::{EXPLAIN_COLUMNS_TYPE, EXPLAIN_QUERY_PLAN_COLUMNS_TYPE
use crate::vdbe::metrics::ConnectionMetrics;
use crate::vtab::VirtualTable;
use crate::{incremental::view::AllViewsTxState, translate::emitter::TransactionMode};
use arc_swap::ArcSwap;
use core::str;
pub use error::{CompletionError, LimboError};
pub use io::clock::{Clock, Instant};
@@ -487,7 +488,7 @@ impl Database {
let conn = db.connect()?;
let syms = conn.syms.read();
let pager = conn.pager.read().clone();
let pager = conn.pager.load().clone();
if let Some(encryption_opts) = encryption_opts {
conn.pragma_update("cipher", format!("'{}'", encryption_opts.cipher))?;
@@ -559,7 +560,7 @@ impl Database {
.get();
let conn = Arc::new(Connection {
db: self.clone(),
pager: RwLock::new(pager),
pager: ArcSwap::new(pager),
schema: RwLock::new(self.schema.lock().unwrap().clone()),
database_schemas: RwLock::new(std::collections::HashMap::new()),
auto_commit: AtomicBool::new(true),
@@ -1061,7 +1062,7 @@ impl DatabaseCatalog {
pub struct Connection {
db: Arc<Database>,
pager: RwLock<Arc<Pager>>,
pager: ArcSwap<Pager>,
schema: RwLock<Arc<Schema>>,
/// Per-database schema cache (database_index -> schema)
/// Loaded lazily to avoid copying all schemas on connection open
@@ -1161,7 +1162,7 @@ impl Connection {
.unwrap()
.trim();
self.maybe_update_schema();
let pager = self.pager.read().clone();
let pager = self.pager.load().clone();
let mode = QueryMode::new(&cmd);
let (Cmd::Stmt(stmt) | Cmd::Explain(stmt) | Cmd::ExplainQueryPlan(stmt)) = cmd;
let program = translate::translate(
@@ -1192,7 +1193,7 @@ impl Connection {
/// This function must be called outside of any transaction because internally it will start transaction session by itself
#[allow(dead_code)]
fn maybe_reparse_schema(self: &Arc<Connection>) -> Result<()> {
let pager = self.pager.read().clone();
let pager = self.pager.load().clone();
// first, quickly read schema_version from the root page in order to check if schema changed
pager.begin_read_tx()?;
@@ -1258,7 +1259,7 @@ impl Connection {
}
fn reparse_schema(self: &Arc<Connection>) -> Result<()> {
let pager = self.pager.read().clone();
let pager = self.pager.load().clone();
// read cookie before consuming statement program - otherwise we can end up reading cookie with closed transaction state
let cookie = pager
@@ -1315,7 +1316,7 @@ impl Connection {
let mut parser = Parser::new(sql.as_bytes());
while let Some(cmd) = parser.next_cmd()? {
let syms = self.syms.read();
let pager = self.pager.read().clone();
let pager = self.pager.load().clone();
let byte_offset_end = parser.offset();
let input = str::from_utf8(&sql.as_bytes()[..byte_offset_end])
.unwrap()
@@ -1367,7 +1368,7 @@ impl Connection {
return Err(LimboError::InternalError("Connection closed".to_string()));
}
let syms = self.syms.read();
let pager = self.pager.read().clone();
let pager = self.pager.load().clone();
let mode = QueryMode::new(&cmd);
let (Cmd::Stmt(stmt) | Cmd::Explain(stmt) | Cmd::ExplainQueryPlan(stmt)) = cmd;
let program = translate::translate(
@@ -1399,7 +1400,7 @@ impl Connection {
let mut parser = Parser::new(sql.as_bytes());
while let Some(cmd) = parser.next_cmd()? {
let syms = self.syms.read();
let pager = self.pager.read().clone();
let pager = self.pager.load().clone();
let byte_offset_end = parser.offset();
let input = str::from_utf8(&sql.as_bytes()[..byte_offset_end])
.unwrap()
@@ -1428,7 +1429,7 @@ impl Connection {
return Ok(None);
};
let syms = self.syms.read();
let pager = self.pager.read().clone();
let pager = self.pager.load().clone();
let byte_offset_end = parser.offset();
let input = str::from_utf8(&sql.as_bytes()[..byte_offset_end])
.unwrap()
@@ -1518,7 +1519,7 @@ impl Connection {
if let Some(encryption_opts) = encryption_opts {
let _ = conn.pragma_update("cipher", encryption_opts.cipher.to_string());
let _ = conn.pragma_update("hexkey", encryption_opts.hexkey.to_string());
let pager = conn.pager.read();
let pager = conn.pager.load();
if db.db_state.get().is_initialized() {
// Clear page cache so the header page can be reread from disk and decrypted using the encryption context.
pager.clear_page_cache(false);
@@ -1572,7 +1573,7 @@ impl Connection {
/// Read schema version at current transaction
#[cfg(all(feature = "fs", feature = "conn_raw_api"))]
pub fn read_schema_version(&self) -> Result<u32> {
let pager = self.pager.read();
let pager = self.pager.load();
pager
.io
.block(|| pager.with_header(|header| header.schema_cookie))
@@ -1590,7 +1591,7 @@ impl Connection {
"write_schema_version must be called from within Write transaction".to_string(),
));
};
let pager = self.pager.read();
let pager = self.pager.load();
pager.io.block(|| {
pager.with_header_mut(|header| {
turso_assert!(
@@ -1617,7 +1618,7 @@ impl Connection {
page: &mut [u8],
frame_watermark: Option<u64>,
) -> Result<bool> {
let pager = self.pager.read();
let pager = self.pager.load();
let (page_ref, c) = match pager.read_page_no_cache(page_idx as i64, frame_watermark, true) {
Ok(result) => result,
// on windows, zero read will trigger UnexpectedEof
@@ -1643,19 +1644,19 @@ impl Connection {
/// (so, if concurrent connection wrote something to the WAL - this method will not see this change)
#[cfg(all(feature = "fs", feature = "conn_raw_api"))]
pub fn wal_changed_pages_after(&self, frame_watermark: u64) -> Result<Vec<u32>> {
self.pager.read().wal_changed_pages_after(frame_watermark)
self.pager.load().wal_changed_pages_after(frame_watermark)
}
#[cfg(all(feature = "fs", feature = "conn_raw_api"))]
pub fn wal_state(&self) -> Result<WalState> {
self.pager.read().wal_state()
self.pager.load().wal_state()
}
#[cfg(all(feature = "fs", feature = "conn_raw_api"))]
pub fn wal_get_frame(&self, frame_no: u64, frame: &mut [u8]) -> Result<WalFrameInfo> {
use crate::storage::sqlite3_ondisk::parse_wal_frame_header;
let c = self.pager.read().wal_get_frame(frame_no, frame)?;
let c = self.pager.load().wal_get_frame(frame_no, frame)?;
self.db.io.wait_for_completion(c)?;
let (header, _) = parse_wal_frame_header(frame);
Ok(WalFrameInfo {
@@ -1669,13 +1670,13 @@ impl Connection {
/// If attempt to write frame at the position `frame_no` will create gap in the WAL - method will return error
#[cfg(all(feature = "fs", feature = "conn_raw_api"))]
pub fn wal_insert_frame(&self, frame_no: u64, frame: &[u8]) -> Result<WalFrameInfo> {
self.pager.read().wal_insert_frame(frame_no, frame)
self.pager.load().wal_insert_frame(frame_no, frame)
}
/// Start WAL session by initiating read+write transaction for this connection
#[cfg(all(feature = "fs", feature = "conn_raw_api"))]
pub fn wal_insert_begin(&self) -> Result<()> {
let pager = self.pager.read();
let pager = self.pager.load();
pager.begin_read_tx()?;
pager.io.block(|| pager.begin_write_tx()).inspect_err(|_| {
pager.end_read_tx();
@@ -1695,7 +1696,7 @@ impl Connection {
#[cfg(all(feature = "fs", feature = "conn_raw_api"))]
pub fn wal_insert_end(self: &Arc<Connection>, force_commit: bool) -> Result<()> {
{
let pager = self.pager.read();
let pager = self.pager.load();
let Some(wal) = pager.wal.as_ref() else {
return Err(LimboError::InternalError(
@@ -1745,14 +1746,14 @@ impl Connection {
if self.is_closed() {
return Err(LimboError::InternalError("Connection closed".to_string()));
}
self.pager.read().cacheflush()
self.pager.load().cacheflush()
}
pub fn checkpoint(&self, mode: CheckpointMode) -> Result<CheckpointResult> {
if self.is_closed() {
return Err(LimboError::InternalError("Connection closed".to_string()));
}
self.pager.read().wal_checkpoint(mode)
self.pager.load().wal_checkpoint(mode)
}
/// Close a connection and checkpoint.
@@ -1768,7 +1769,7 @@ impl Connection {
}
_ => {
if !self.mvcc_enabled() {
let pager = self.pager.read();
let pager = self.pager.load();
pager.rollback_tx(self);
}
self.set_tx_state(TransactionState::None);
@@ -1782,7 +1783,7 @@ impl Connection {
.eq(&1)
{
self.pager
.read()
.load()
.checkpoint_shutdown(self.is_wal_auto_checkpoint_disabled())?;
};
Ok(())
@@ -1891,11 +1892,11 @@ impl Connection {
shared_wal.enabled.store(false, Ordering::SeqCst);
shared_wal.file = None;
}
self.pager.write().clear_page_cache(false);
self.pager.load().clear_page_cache(false);
let pager = self.db.init_pager(Some(size.get() as usize))?;
pager.enable_encryption(self.db.opts.enable_encryption);
*self.pager.write() = Arc::new(pager);
self.pager.read().set_initial_page_size(size);
self.pager.store(Arc::new(pager));
self.pager.load().set_initial_page_size(size);
Ok(())
}
@@ -2034,7 +2035,7 @@ impl Connection {
fn get_pager_from_database_index(&self, index: &usize) -> Arc<Pager> {
if *index < 2 {
self.pager.read().clone()
self.pager.load().clone()
} else {
self.attached_databases.read().get_pager_by_index(index)
}
@@ -2247,7 +2248,7 @@ impl Connection {
}
pub fn get_pager(&self) -> Arc<Pager> {
self.pager.read().clone()
self.pager.load().clone()
}
pub fn get_query_only(&self) -> bool {
@@ -2294,7 +2295,7 @@ impl Connection {
}
pub fn set_reserved_bytes(&self, reserved_bytes: u8) -> Result<()> {
let pager = self.pager.read();
let pager = self.pager.load();
pager.set_reserved_space_bytes(reserved_bytes);
Ok(())
}
@@ -2317,7 +2318,7 @@ impl Connection {
return Ok(());
};
tracing::trace!("setting encryption ctx for connection");
let pager = self.pager.read();
let pager = self.pager.load();
if pager.is_encryption_ctx_set() {
return Err(LimboError::InvalidArgument(
"cannot reset encryption attributes if already set in the session".to_string(),

View File

@@ -404,7 +404,7 @@ impl<Clock: LogicalClock> CommitStateMachine<Clock> {
commit_coordinator: Arc<CommitCoordinator>,
header: Arc<RwLock<Option<DatabaseHeader>>>,
) -> Self {
let pager = connection.pager.read().clone();
let pager = connection.pager.load().clone();
Self {
state,
is_finalized: false,
@@ -1047,7 +1047,7 @@ impl<Clock: LogicalClock> MvStore<Clock> {
self.insert_table_id_to_rootpage(root_page_as_table_id, Some(*root_page));
}
if !self.maybe_recover_logical_log(bootstrap_conn.pager.read().clone())? {
if !self.maybe_recover_logical_log(bootstrap_conn.pager.load().clone())? {
// There was no logical log to recover, so we're done.
return Ok(());
}

View File

@@ -125,7 +125,7 @@ fn test_insert_read() {
let tx1 = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let tx1_row = generate_simple_string_row((-2).into(), 1, "Hello");
db.mvcc_store.insert(tx1, tx1_row.clone()).unwrap();
@@ -145,7 +145,7 @@ fn test_insert_read() {
let tx2 = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let row = db
.mvcc_store
@@ -166,7 +166,7 @@ fn test_read_nonexistent() {
let db = MvccTestDb::new();
let tx = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let row = db.mvcc_store.read(
tx,
@@ -184,7 +184,7 @@ fn test_delete() {
let tx1 = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let tx1_row = generate_simple_string_row((-2).into(), 1, "Hello");
db.mvcc_store.insert(tx1, tx1_row.clone()).unwrap();
@@ -224,7 +224,7 @@ fn test_delete() {
let tx2 = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let row = db
.mvcc_store
@@ -244,7 +244,7 @@ fn test_delete_nonexistent() {
let db = MvccTestDb::new();
let tx = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
assert!(!db
.mvcc_store
@@ -263,7 +263,7 @@ fn test_commit() {
let db = MvccTestDb::new();
let tx1 = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let tx1_row = generate_simple_string_row((-2).into(), 1, "Hello");
db.mvcc_store.insert(tx1, tx1_row.clone()).unwrap();
@@ -297,7 +297,7 @@ fn test_commit() {
let tx2 = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let row = db
.mvcc_store
@@ -320,7 +320,7 @@ fn test_rollback() {
let db = MvccTestDb::new();
let tx1 = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let row1 = generate_simple_string_row((-2).into(), 1, "Hello");
db.mvcc_store.insert(tx1, row1.clone()).unwrap();
@@ -351,10 +351,10 @@ fn test_rollback() {
.unwrap();
assert_eq!(row3, row4);
db.mvcc_store
.rollback_tx(tx1, db.conn.pager.read().clone(), &db.conn);
.rollback_tx(tx1, db.conn.pager.load().clone(), &db.conn);
let tx2 = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let row5 = db
.mvcc_store
@@ -376,7 +376,7 @@ fn test_dirty_write() {
// T1 inserts a row with ID 1, but does not commit.
let tx1 = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let tx1_row = generate_simple_string_row((-2).into(), 1, "Hello");
db.mvcc_store.insert(tx1, tx1_row.clone()).unwrap();
@@ -395,7 +395,7 @@ fn test_dirty_write() {
let conn2 = db.db.connect().unwrap();
// T2 attempts to delete row with ID 1, but fails because T1 has not committed.
let tx2 = db.mvcc_store.begin_tx(conn2.pager.read().clone()).unwrap();
let tx2 = db.mvcc_store.begin_tx(conn2.pager.load().clone()).unwrap();
let tx2_row = generate_simple_string_row((-2).into(), 1, "World");
assert!(!db.mvcc_store.update(tx2, tx2_row).unwrap());
@@ -420,14 +420,14 @@ fn test_dirty_read() {
// T1 inserts a row with ID 1, but does not commit.
let tx1 = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let row1 = generate_simple_string_row((-2).into(), 1, "Hello");
db.mvcc_store.insert(tx1, row1).unwrap();
// T2 attempts to read row with ID 1, but doesn't see one because T1 has not committed.
let conn2 = db.db.connect().unwrap();
let tx2 = db.mvcc_store.begin_tx(conn2.pager.read().clone()).unwrap();
let tx2 = db.mvcc_store.begin_tx(conn2.pager.load().clone()).unwrap();
let row2 = db
.mvcc_store
.read(
@@ -448,7 +448,7 @@ fn test_dirty_read_deleted() {
// T1 inserts a row with ID 1 and commits.
let tx1 = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let tx1_row = generate_simple_string_row((-2).into(), 1, "Hello");
db.mvcc_store.insert(tx1, tx1_row.clone()).unwrap();
@@ -456,7 +456,7 @@ fn test_dirty_read_deleted() {
// T2 deletes row with ID 1, but does not commit.
let conn2 = db.db.connect().unwrap();
let tx2 = db.mvcc_store.begin_tx(conn2.pager.read().clone()).unwrap();
let tx2 = db.mvcc_store.begin_tx(conn2.pager.load().clone()).unwrap();
assert!(db
.mvcc_store
.delete(
@@ -470,7 +470,7 @@ fn test_dirty_read_deleted() {
// T3 reads row with ID 1, but doesn't see the delete because T2 hasn't committed.
let conn3 = db.db.connect().unwrap();
let tx3 = db.mvcc_store.begin_tx(conn3.pager.read().clone()).unwrap();
let tx3 = db.mvcc_store.begin_tx(conn3.pager.load().clone()).unwrap();
let row = db
.mvcc_store
.read(
@@ -492,7 +492,7 @@ fn test_fuzzy_read() {
// T1 inserts a row with ID 1 and commits.
let tx1 = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let tx1_row = generate_simple_string_row((-2).into(), 1, "First");
db.mvcc_store.insert(tx1, tx1_row.clone()).unwrap();
@@ -512,7 +512,7 @@ fn test_fuzzy_read() {
// T2 reads the row with ID 1 within an active transaction.
let conn2 = db.db.connect().unwrap();
let tx2 = db.mvcc_store.begin_tx(conn2.pager.read().clone()).unwrap();
let tx2 = db.mvcc_store.begin_tx(conn2.pager.load().clone()).unwrap();
let row = db
.mvcc_store
.read(
@@ -528,7 +528,7 @@ fn test_fuzzy_read() {
// T3 updates the row and commits.
let conn3 = db.db.connect().unwrap();
let tx3 = db.mvcc_store.begin_tx(conn3.pager.read().clone()).unwrap();
let tx3 = db.mvcc_store.begin_tx(conn3.pager.load().clone()).unwrap();
let tx3_row = generate_simple_string_row((-2).into(), 1, "Second");
db.mvcc_store.update(tx3, tx3_row).unwrap();
commit_tx(db.mvcc_store.clone(), &conn3, tx3).unwrap();
@@ -561,7 +561,7 @@ fn test_lost_update() {
// T1 inserts a row with ID 1 and commits.
let tx1 = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let tx1_row = generate_simple_string_row((-2).into(), 1, "Hello");
db.mvcc_store.insert(tx1, tx1_row.clone()).unwrap();
@@ -581,13 +581,13 @@ fn test_lost_update() {
// T2 attempts to update row ID 1 within an active transaction.
let conn2 = db.db.connect().unwrap();
let tx2 = db.mvcc_store.begin_tx(conn2.pager.read().clone()).unwrap();
let tx2 = db.mvcc_store.begin_tx(conn2.pager.load().clone()).unwrap();
let tx2_row = generate_simple_string_row((-2).into(), 1, "World");
assert!(db.mvcc_store.update(tx2, tx2_row.clone()).unwrap());
// T3 also attempts to update row ID 1 within an active transaction.
let conn3 = db.db.connect().unwrap();
let tx3 = db.mvcc_store.begin_tx(conn3.pager.read().clone()).unwrap();
let tx3 = db.mvcc_store.begin_tx(conn3.pager.load().clone()).unwrap();
let tx3_row = generate_simple_string_row((-2).into(), 1, "Hello, world!");
assert!(matches!(
db.mvcc_store.update(tx3, tx3_row),
@@ -595,7 +595,7 @@ fn test_lost_update() {
));
// hack: in the actual tursodb database we rollback the mvcc tx ourselves, so manually roll it back here
db.mvcc_store
.rollback_tx(tx3, conn3.pager.read().clone(), &conn3);
.rollback_tx(tx3, conn3.pager.load().clone(), &conn3);
commit_tx(db.mvcc_store.clone(), &conn2, tx2).unwrap();
assert!(matches!(
@@ -604,7 +604,7 @@ fn test_lost_update() {
));
let conn4 = db.db.connect().unwrap();
let tx4 = db.mvcc_store.begin_tx(conn4.pager.read().clone()).unwrap();
let tx4 = db.mvcc_store.begin_tx(conn4.pager.load().clone()).unwrap();
let row = db
.mvcc_store
.read(
@@ -628,7 +628,7 @@ fn test_committed_visibility() {
// let's add $10 to my account since I like money
let tx1 = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let tx1_row = generate_simple_string_row((-2).into(), 1, "10");
db.mvcc_store.insert(tx1, tx1_row.clone()).unwrap();
@@ -636,7 +636,7 @@ fn test_committed_visibility() {
// but I like more money, so let me try adding $10 more
let conn2 = db.db.connect().unwrap();
let tx2 = db.mvcc_store.begin_tx(conn2.pager.read().clone()).unwrap();
let tx2 = db.mvcc_store.begin_tx(conn2.pager.load().clone()).unwrap();
let tx2_row = generate_simple_string_row((-2).into(), 1, "20");
assert!(db.mvcc_store.update(tx2, tx2_row.clone()).unwrap());
let row = db
@@ -654,7 +654,7 @@ fn test_committed_visibility() {
// can I check how much money I have?
let conn3 = db.db.connect().unwrap();
let tx3 = db.mvcc_store.begin_tx(conn3.pager.read().clone()).unwrap();
let tx3 = db.mvcc_store.begin_tx(conn3.pager.load().clone()).unwrap();
let row = db
.mvcc_store
.read(
@@ -676,11 +676,11 @@ fn test_future_row() {
let tx1 = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let conn2 = db.db.connect().unwrap();
let tx2 = db.mvcc_store.begin_tx(conn2.pager.read().clone()).unwrap();
let tx2 = db.mvcc_store.begin_tx(conn2.pager.load().clone()).unwrap();
let tx2_row = generate_simple_string_row((-2).into(), 1, "Hello");
db.mvcc_store.insert(tx2, tx2_row).unwrap();
@@ -726,7 +726,7 @@ fn setup_test_db() -> (MvccTestDb, u64) {
let db = MvccTestDb::new();
let tx_id = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let table_id = MVTableId::new(-1);
@@ -749,7 +749,7 @@ fn setup_test_db() -> (MvccTestDb, u64) {
let tx_id = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
(db, tx_id)
}
@@ -758,7 +758,7 @@ fn setup_lazy_db(initial_keys: &[i64]) -> (MvccTestDb, u64) {
let db = MvccTestDb::new();
let tx_id = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let table_id = -1;
@@ -774,7 +774,7 @@ fn setup_lazy_db(initial_keys: &[i64]) -> (MvccTestDb, u64) {
let tx_id = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
(db, tx_id)
}
@@ -829,8 +829,8 @@ fn test_lazy_scan_cursor_basic() {
db.mvcc_store.clone(),
tx_id,
table_id,
db.conn.pager.read().clone(),
Box::new(BTreeCursor::new(db.conn.pager.read().clone(), table_id, 1)),
db.conn.pager.load().clone(),
Box::new(BTreeCursor::new(db.conn.pager.load().clone(), table_id, 1)),
)
.unwrap();
@@ -872,8 +872,8 @@ fn test_lazy_scan_cursor_with_gaps() {
db.mvcc_store.clone(),
tx_id,
table_id,
db.conn.pager.read().clone(),
Box::new(BTreeCursor::new(db.conn.pager.read().clone(), table_id, 1)),
db.conn.pager.load().clone(),
Box::new(BTreeCursor::new(db.conn.pager.load().clone(), table_id, 1)),
)
.unwrap();
@@ -924,8 +924,8 @@ fn test_cursor_basic() {
db.mvcc_store.clone(),
tx_id,
table_id,
db.conn.pager.read().clone(),
Box::new(BTreeCursor::new(db.conn.pager.read().clone(), table_id, 1)),
db.conn.pager.load().clone(),
Box::new(BTreeCursor::new(db.conn.pager.load().clone(), table_id, 1)),
)
.unwrap();
@@ -964,13 +964,13 @@ fn test_cursor_with_empty_table() {
let db = MvccTestDb::new();
{
// FIXME: force page 1 initialization
let pager = db.conn.pager.read().clone();
let pager = db.conn.pager.load().clone();
let tx_id = db.mvcc_store.begin_tx(pager.clone()).unwrap();
commit_tx(db.mvcc_store.clone(), &db.conn, tx_id).unwrap();
}
let tx_id = db
.mvcc_store
.begin_tx(db.conn.pager.read().clone())
.begin_tx(db.conn.pager.load().clone())
.unwrap();
let table_id = -1; // Empty table
@@ -979,8 +979,8 @@ fn test_cursor_with_empty_table() {
db.mvcc_store.clone(),
tx_id,
table_id,
db.conn.pager.read().clone(),
Box::new(BTreeCursor::new(db.conn.pager.read().clone(), table_id, 1)),
db.conn.pager.load().clone(),
Box::new(BTreeCursor::new(db.conn.pager.load().clone(), table_id, 1)),
)
.unwrap();
assert!(cursor.is_empty());
@@ -997,8 +997,8 @@ fn test_cursor_modification_during_scan() {
db.mvcc_store.clone(),
tx_id,
table_id,
db.conn.pager.read().clone(),
Box::new(BTreeCursor::new(db.conn.pager.read().clone(), table_id, 1)),
db.conn.pager.load().clone(),
Box::new(BTreeCursor::new(db.conn.pager.load().clone(), table_id, 1)),
)
.unwrap();
@@ -1202,7 +1202,7 @@ fn test_restart() {
{
let conn = db.connect();
let mvcc_store = db.get_mvcc_store();
let tx_id = mvcc_store.begin_tx(conn.pager.read().clone()).unwrap();
let tx_id = mvcc_store.begin_tx(conn.pager.load().clone()).unwrap();
// insert table id -2 into sqlite_schema table (table_id -1)
let data = ImmutableRecord::from_values(
&[
@@ -1240,13 +1240,13 @@ fn test_restart() {
{
let conn = db.connect();
let mvcc_store = db.get_mvcc_store();
let tx_id = mvcc_store.begin_tx(conn.pager.read().clone()).unwrap();
let tx_id = mvcc_store.begin_tx(conn.pager.load().clone()).unwrap();
let row = generate_simple_string_row((-2).into(), 2, "bar");
mvcc_store.insert(tx_id, row).unwrap();
commit_tx(mvcc_store.clone(), &conn, tx_id).unwrap();
let tx_id = mvcc_store.begin_tx(conn.pager.read().clone()).unwrap();
let tx_id = mvcc_store.begin_tx(conn.pager.load().clone()).unwrap();
let row = mvcc_store
.read(tx_id, RowID::new((-2).into(), 2))
.unwrap()

View File

@@ -65,7 +65,7 @@ mod tests {
let conn = db.get_db().connect().unwrap();
let mvcc_store = db.get_db().mv_store.as_ref().unwrap().clone();
for _ in 0..iterations {
let tx = mvcc_store.begin_tx(conn.pager.read().clone()).unwrap();
let tx = mvcc_store.begin_tx(conn.pager.load().clone()).unwrap();
let id = IDS.fetch_add(1, Ordering::SeqCst);
let id = RowID {
table_id: (-2).into(),
@@ -74,7 +74,7 @@ mod tests {
let row = generate_simple_string_row((-2).into(), id.row_id, "Hello");
mvcc_store.insert(tx, row.clone()).unwrap();
commit_tx_no_conn(&db, tx, &conn).unwrap();
let tx = mvcc_store.begin_tx(conn.pager.read().clone()).unwrap();
let tx = mvcc_store.begin_tx(conn.pager.load().clone()).unwrap();
let committed_row = mvcc_store.read(tx, id).unwrap();
commit_tx_no_conn(&db, tx, &conn).unwrap();
assert_eq!(committed_row, Some(row));
@@ -86,7 +86,7 @@ mod tests {
let conn = db.get_db().connect().unwrap();
let mvcc_store = db.get_db().mv_store.as_ref().unwrap().clone();
for _ in 0..iterations {
let tx = mvcc_store.begin_tx(conn.pager.read().clone()).unwrap();
let tx = mvcc_store.begin_tx(conn.pager.load().clone()).unwrap();
let id = IDS.fetch_add(1, Ordering::SeqCst);
let id = RowID {
table_id: (-2).into(),
@@ -95,7 +95,7 @@ mod tests {
let row = generate_simple_string_row((-2).into(), id.row_id, "World");
mvcc_store.insert(tx, row.clone()).unwrap();
commit_tx_no_conn(&db, tx, &conn).unwrap();
let tx = mvcc_store.begin_tx(conn.pager.read().clone()).unwrap();
let tx = mvcc_store.begin_tx(conn.pager.load().clone()).unwrap();
let committed_row = mvcc_store.read(tx, id).unwrap();
commit_tx_no_conn(&db, tx, &conn).unwrap();
assert_eq!(committed_row, Some(row));
@@ -127,7 +127,7 @@ mod tests {
let dropped = mvcc_store.drop_unused_row_versions();
tracing::debug!("garbage collected {dropped} versions");
}
let tx = mvcc_store.begin_tx(conn.pager.read().clone()).unwrap();
let tx = mvcc_store.begin_tx(conn.pager.load().clone()).unwrap();
let id = i % 16;
let id = RowID {
table_id: (-2).into(),

View File

@@ -513,7 +513,7 @@ mod tests {
let db = MvccTestDbNoConn::new_with_random_db();
let (io, pager) = {
let conn = db.connect();
let pager = conn.pager.read().clone();
let pager = conn.pager.load().clone();
let mvcc_store = db.get_mvcc_store();
let tx_id = mvcc_store.begin_tx(pager.clone()).unwrap();
// insert table id -2 into sqlite_schema table (table_id -1)
@@ -580,7 +580,7 @@ mod tests {
let db = MvccTestDbNoConn::new_with_random_db();
let (io, pager) = {
let conn = db.connect();
let pager = conn.pager.read().clone();
let pager = conn.pager.load().clone();
let mvcc_store = db.get_mvcc_store();
let tx_id = mvcc_store.begin_tx(pager.clone()).unwrap();
@@ -691,7 +691,7 @@ mod tests {
let mut db = MvccTestDbNoConn::new_with_random_db();
let pager = {
let conn = db.connect();
let pager = conn.pager.read().clone();
let pager = conn.pager.load().clone();
let mvcc_store = db.get_mvcc_store();
// insert table id -2 into sqlite_schema table (table_id -1)

View File

@@ -7864,11 +7864,11 @@ mod tests {
pos,
&record,
4096,
conn.pager.read().clone(),
conn.pager.load().clone(),
&mut fill_cell_payload_state,
)
},
&conn.pager.read().clone(),
&conn.pager.load().clone(),
)
.unwrap();
insert_into_cell(page.get_contents(), &payload, pos, 4096).unwrap();
@@ -8137,7 +8137,7 @@ mod tests {
let io: Arc<dyn IO> = Arc::new(MemoryIO::new());
let db = Database::open_file(io.clone(), ":memory:", false, false).unwrap();
let conn = db.connect().unwrap();
let pager = conn.pager.read().clone();
let pager = conn.pager.load().clone();
// FIXME: handle page cache is full
@@ -8157,7 +8157,7 @@ mod tests {
let io: Arc<dyn IO> = Arc::new(MemoryIO::new());
let db = Database::open_file(io.clone(), ":memory:", false, false).unwrap();
let conn = db.connect().unwrap();
let pager = conn.pager.read().clone();
let pager = conn.pager.load().clone();
let mut cursor = BTreeCursor::new(pager, 1, 5);
let result = cursor.rewind()?;
@@ -9626,11 +9626,11 @@ mod tests {
cell_idx,
&record,
4096,
conn.pager.read().clone(),
conn.pager.load().clone(),
&mut fill_cell_payload_state,
)
},
&conn.pager.read().clone(),
&conn.pager.load().clone(),
)
.unwrap();
if (free as usize) < payload.len() + 2 {
@@ -9708,11 +9708,11 @@ mod tests {
cell_idx,
&record,
4096,
conn.pager.read().clone(),
conn.pager.load().clone(),
&mut fill_cell_payload_state,
)
},
&conn.pager.read().clone(),
&conn.pager.load().clone(),
)
.unwrap();
if (free as usize) < payload.len() - 2 {
@@ -10081,11 +10081,11 @@ mod tests {
0,
&record,
4096,
conn.pager.read().clone(),
conn.pager.load().clone(),
&mut fill_cell_payload_state,
)
},
&conn.pager.read().clone(),
&conn.pager.load().clone(),
)
.unwrap();
@@ -10167,11 +10167,11 @@ mod tests {
0,
&record,
4096,
conn.pager.read().clone(),
conn.pager.load().clone(),
&mut fill_cell_payload_state,
)
},
&conn.pager.read().clone(),
&conn.pager.load().clone(),
)
.unwrap();
insert_into_cell(page.get_contents(), &payload, 0, 4096).unwrap();

View File

@@ -2560,7 +2560,7 @@ pub mod test {
for _i in 0..25 {
let _ = conn.execute("insert into test (value) values (randomblob(1024)), (randomblob(1024)), (randomblob(1024))");
}
let pager = conn.pager.write();
let pager = conn.pager.load();
let _ = pager.cacheflush();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
@@ -2651,7 +2651,7 @@ pub mod test {
conn.execute("create table test(id integer primary key, value text)")
.unwrap();
bulk_inserts(&conn, 20, 3);
let completions = conn.pager.write().cacheflush().unwrap();
let completions = conn.pager.load().cacheflush().unwrap();
for c in completions {
db.io.wait_for_completion(c).unwrap();
}
@@ -2677,7 +2677,7 @@ pub mod test {
// Run a RESTART checkpoint, should backfill everything and reset WAL counters,
// but NOT truncate the file.
{
let pager = conn.pager.read();
let pager = conn.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
let res = run_checkpoint_until_done(&mut *wal, &pager, CheckpointMode::Restart);
assert_eq!(res.num_attempted, mx_before);
@@ -2723,7 +2723,7 @@ pub mod test {
conn.execute("insert into test(value) values ('post_restart')")
.unwrap();
conn.pager
.write()
.load()
.wal
.as_ref()
.unwrap()
@@ -2746,14 +2746,14 @@ pub mod test {
.execute("create table test(id integer primary key, value text)")
.unwrap();
bulk_inserts(&conn1.clone(), 15, 2);
let completions = conn1.pager.write().cacheflush().unwrap();
let completions = conn1.pager.load().cacheflush().unwrap();
for c in completions {
db.io.wait_for_completion(c).unwrap();
}
// Force a read transaction that will freeze a lower read mark
let readmark = {
let pager = conn2.pager.write();
let pager = conn2.pager.load();
let mut wal2 = pager.wal.as_ref().unwrap().borrow_mut();
wal2.begin_read_tx().unwrap();
wal2.get_max_frame()
@@ -2761,14 +2761,14 @@ pub mod test {
// generate more frames that the reader will not see.
bulk_inserts(&conn1.clone(), 15, 2);
let completions = conn1.pager.write().cacheflush().unwrap();
let completions = conn1.pager.load().cacheflush().unwrap();
for c in completions {
db.io.wait_for_completion(c).unwrap();
}
// Run passive checkpoint, expect partial
let (res1, max_before) = {
let pager = conn1.pager.read();
let pager = conn1.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
let res = run_checkpoint_until_done(
&mut *wal,
@@ -2793,13 +2793,13 @@ pub mod test {
);
// Release reader
{
let pager = conn2.pager.write();
let pager = conn2.pager.load();
let wal2 = pager.wal.as_ref().unwrap().borrow_mut();
wal2.end_read_tx();
}
// Second passive checkpoint should finish
let pager = conn1.pager.read();
let pager = conn1.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
let res2 = run_checkpoint_until_done(
&mut *wal,
@@ -2823,7 +2823,7 @@ pub mod test {
// Start a read transaction
conn2
.pager
.write()
.load()
.wal
.as_ref()
.unwrap()
@@ -2833,7 +2833,7 @@ pub mod test {
// checkpoint should succeed here because the wal is fully checkpointed (empty)
// so the reader is using readmark0 to read directly from the db file.
let p = conn1.pager.read();
let p = conn1.pager.load();
let mut w = p.wal.as_ref().unwrap().borrow_mut();
loop {
match w.checkpoint(&p, CheckpointMode::Restart) {
@@ -2850,7 +2850,7 @@ pub mod test {
}
}
drop(w);
conn2.pager.write().end_read_tx();
conn2.pager.load().end_read_tx();
conn1
.execute("create table test(id integer primary key, value text)")
@@ -2861,8 +2861,8 @@ pub mod test {
.unwrap();
}
// now that we have some frames to checkpoint, try again
conn2.pager.write().begin_read_tx().unwrap();
let p = conn1.pager.read();
conn2.pager.load().begin_read_tx().unwrap();
let p = conn1.pager.load();
let mut w = p.wal.as_ref().unwrap().borrow_mut();
loop {
match w.checkpoint(&p, CheckpointMode::Restart) {
@@ -2894,7 +2894,7 @@ pub mod test {
bulk_inserts(&conn, 10, 5);
// Checkpoint with restart
{
let pager = conn.pager.read();
let pager = conn.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
let result = run_checkpoint_until_done(&mut *wal, &pager, CheckpointMode::Restart);
assert!(result.everything_backfilled());
@@ -2935,7 +2935,7 @@ pub mod test {
// R1 starts reading
let r1_max_frame = {
let pager = conn_r1.pager.write();
let pager = conn_r1.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
wal.begin_read_tx().unwrap();
wal.get_max_frame()
@@ -2944,7 +2944,7 @@ pub mod test {
// R2 starts reading, sees more frames than R1
let r2_max_frame = {
let pager = conn_r2.pager.write();
let pager = conn_r2.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
wal.begin_read_tx().unwrap();
wal.get_max_frame()
@@ -2952,7 +2952,7 @@ pub mod test {
// try passive checkpoint, should only checkpoint up to R1's position
let checkpoint_result = {
let pager = conn_writer.pager.read();
let pager = conn_writer.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
run_checkpoint_until_done(
&mut *wal,
@@ -2976,7 +2976,7 @@ pub mod test {
assert_eq!(
conn_r2
.pager
.read()
.load()
.wal
.as_ref()
.unwrap()
@@ -3001,7 +3001,7 @@ pub mod test {
let max_frame_before = wal_shared.read().max_frame.load(Ordering::SeqCst);
{
let pager = conn.pager.read();
let pager = conn.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
let _result = run_checkpoint_until_done(
&mut *wal,
@@ -3034,7 +3034,7 @@ pub mod test {
// start a write transaction
{
let pager = conn2.pager.write();
let pager = conn2.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
let _ = wal.begin_read_tx().unwrap();
wal.begin_write_tx().unwrap();
@@ -3042,7 +3042,7 @@ pub mod test {
// should fail because writer lock is held
let result = {
let pager = conn1.pager.read();
let pager = conn1.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
wal.checkpoint(&pager, CheckpointMode::Restart)
};
@@ -3054,7 +3054,7 @@ pub mod test {
conn2
.pager
.read()
.load()
.wal
.as_ref()
.unwrap()
@@ -3063,7 +3063,7 @@ pub mod test {
// release write lock
conn2
.pager
.read()
.load()
.wal
.as_ref()
.unwrap()
@@ -3072,7 +3072,7 @@ pub mod test {
// now restart should succeed
let result = {
let pager = conn1.pager.read();
let pager = conn1.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
run_checkpoint_until_done(&mut *wal, &pager, CheckpointMode::Restart)
};
@@ -3090,13 +3090,13 @@ pub mod test {
.unwrap();
// Attempt to start a write transaction without a read transaction
let pager = conn.pager.read();
let pager = conn.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
let _ = wal.begin_write_tx();
}
fn check_read_lock_slot(conn: &Arc<Connection>, expected_slot: usize) -> bool {
let pager = conn.pager.read();
let pager = conn.pager.load();
let wal = pager.wal.as_ref().unwrap().borrow();
#[cfg(debug_assertions)]
{
@@ -3124,7 +3124,7 @@ pub mod test {
stmt.step().unwrap();
let frame = conn
.pager
.read()
.load()
.wal
.as_ref()
.unwrap()
@@ -3152,7 +3152,7 @@ pub mod test {
// passive checkpoint #1
let result1 = {
let pager = conn_writer.pager.read();
let pager = conn_writer.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
run_checkpoint_until_done(
&mut *wal,
@@ -3169,7 +3169,7 @@ pub mod test {
// passive checkpoint #2
let result2 = {
let pager = conn_writer.pager.read();
let pager = conn_writer.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
run_checkpoint_until_done(
&mut *wal,
@@ -3218,7 +3218,7 @@ pub mod test {
// Do a TRUNCATE checkpoint
{
let pager = conn.pager.read();
let pager = conn.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
run_checkpoint_until_done(
&mut *wal,
@@ -3279,7 +3279,7 @@ pub mod test {
// Do a TRUNCATE checkpoint
{
let pager = conn.pager.read();
let pager = conn.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
run_checkpoint_until_done(
&mut *wal,
@@ -3317,7 +3317,7 @@ pub mod test {
assert_eq!(hdr.page_size, 4096, "invalid page size");
assert_eq!(hdr.checkpoint_seq, 1, "invalid checkpoint_seq");
{
let pager = conn.pager.read();
let pager = conn.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
run_checkpoint_until_done(
&mut *wal,
@@ -3367,7 +3367,7 @@ pub mod test {
.unwrap();
// Start a read transaction on conn2
{
let pager = conn2.pager.write();
let pager = conn2.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
wal.begin_read_tx().unwrap();
}
@@ -3375,7 +3375,7 @@ pub mod test {
bulk_inserts(&conn1, 5, 5);
// Try to start a write transaction on conn2 with a stale snapshot
let result = {
let pager = conn2.pager.read();
let pager = conn2.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
wal.begin_write_tx()
};
@@ -3384,14 +3384,14 @@ pub mod test {
// End read transaction and start a fresh one
{
let pager = conn2.pager.read();
let pager = conn2.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
wal.end_read_tx();
wal.begin_read_tx().unwrap();
}
// Now write transaction should work
let result = {
let pager = conn2.pager.read();
let pager = conn2.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
wal.begin_write_tx()
};
@@ -3410,7 +3410,7 @@ pub mod test {
bulk_inserts(&conn1, 5, 5);
// Do a full checkpoint to move all data to DB file
{
let pager = conn1.pager.read();
let pager = conn1.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
run_checkpoint_until_done(
&mut *wal,
@@ -3423,14 +3423,14 @@ pub mod test {
// Start a read transaction on conn2
{
let pager = conn2.pager.write();
let pager = conn2.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
wal.begin_read_tx().unwrap();
}
// should use slot 0, as everything is backfilled
assert!(check_read_lock_slot(&conn2, 0));
{
let pager = conn1.pager.read();
let pager = conn1.pager.load();
let wal = pager.wal.as_ref().unwrap().borrow();
let frame = wal.find_frame(5, None);
// since we hold readlock0, we should ignore the db file and find_frame should return none
@@ -3438,7 +3438,7 @@ pub mod test {
}
// Try checkpoint, should fail because reader has slot 0
{
let pager = conn1.pager.read();
let pager = conn1.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
let result = wal.checkpoint(&pager, CheckpointMode::Restart);
@@ -3449,12 +3449,12 @@ pub mod test {
}
// End the read transaction
{
let pager = conn2.pager.read();
let pager = conn2.pager.load();
let wal = pager.wal.as_ref().unwrap().borrow();
wal.end_read_tx();
}
{
let pager = conn1.pager.read();
let pager = conn1.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
let result = run_checkpoint_until_done(&mut *wal, &pager, CheckpointMode::Restart);
assert!(
@@ -3475,7 +3475,7 @@ pub mod test {
bulk_inserts(&conn, 8, 4);
// Ensure frames are flushed to the WAL
let completions = conn.pager.write().cacheflush().unwrap();
let completions = conn.pager.load().cacheflush().unwrap();
for c in completions {
db.io.wait_for_completion(c).unwrap();
}
@@ -3487,7 +3487,7 @@ pub mod test {
// Run FULL checkpoint - must backfill *all* frames up to mx_before
let result = {
let pager = conn.pager.read();
let pager = conn.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
run_checkpoint_until_done(&mut *wal, &pager, CheckpointMode::Full)
};
@@ -3508,26 +3508,26 @@ pub mod test {
// First commit some data and flush (reader will snapshot here)
bulk_inserts(&writer, 2, 3);
let completions = writer.pager.write().cacheflush().unwrap();
let completions = writer.pager.load().cacheflush().unwrap();
for c in completions {
db.io.wait_for_completion(c).unwrap();
}
// Start a read transaction pinned at the current snapshot
{
let pager = reader.pager.write();
let pager = reader.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
wal.begin_read_tx().unwrap();
}
let r_snapshot = {
let pager = reader.pager.read();
let pager = reader.pager.load();
let wal = pager.wal.as_ref().unwrap().borrow();
wal.get_max_frame()
};
// Advance WAL beyond the reader's snapshot
bulk_inserts(&writer, 3, 4);
let completions = writer.pager.write().cacheflush().unwrap();
let completions = writer.pager.load().cacheflush().unwrap();
for c in completions {
db.io.wait_for_completion(c).unwrap();
}
@@ -3536,7 +3536,7 @@ pub mod test {
// FULL must return Busy while a reader is stuck behind
{
let pager = writer.pager.read();
let pager = writer.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
loop {
match wal.checkpoint(&pager, CheckpointMode::Full) {
@@ -3554,13 +3554,13 @@ pub mod test {
// Release the reader, now full mode should succeed and backfill everything
{
let pager = reader.pager.read();
let pager = reader.pager.load();
let wal = pager.wal.as_ref().unwrap().borrow();
wal.end_read_tx();
}
let result = {
let pager = writer.pager.read();
let pager = writer.pager.load();
let mut wal = pager.wal.as_ref().unwrap().borrow_mut();
run_checkpoint_until_done(&mut *wal, &pager, CheckpointMode::Full)
};

View File

@@ -408,7 +408,7 @@ pub fn op_checkpoint_inner(
let step_result = program
.connection
.pager
.write()
.load()
.wal_checkpoint_start(*checkpoint_mode);
match step_result {
Ok(IOResult::Done(result)) => {
@@ -429,7 +429,7 @@ pub fn op_checkpoint_inner(
let step_result = program
.connection
.pager
.write()
.load()
.wal_checkpoint_finish(result.as_mut().unwrap());
match step_result {
Ok(IOResult::Done(())) => {
@@ -7692,7 +7692,7 @@ pub fn op_open_ephemeral(
let page_size =
return_if_io!(with_header(pager, mv_store, program, |header| header.page_size));
let conn = program.connection.clone();
let io = conn.pager.read().io.clone();
let io = conn.pager.load().io.clone();
let rand_num = io.generate_random_number();
let db_file;
let db_file_io: Arc<dyn crate::IO>;