mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-07-07 12:35:00 +00:00
add option to disable wal checkpoint
This commit is contained in:
parent
9e92325bad
commit
db005c81a0
6 changed files with 44 additions and 17 deletions
16
core/lib.rs
16
core/lib.rs
|
@ -118,8 +118,8 @@ pub struct Database {
|
|||
maybe_shared_wal: RwLock<Option<Arc<UnsafeCell<WalFileShared>>>>,
|
||||
is_empty: Arc<AtomicUsize>,
|
||||
init_lock: Arc<Mutex<()>>,
|
||||
|
||||
open_flags: OpenFlags,
|
||||
wal_checkpoint_disabled: Cell<bool>,
|
||||
}
|
||||
|
||||
unsafe impl Send for Database {}
|
||||
|
@ -211,6 +211,7 @@ impl Database {
|
|||
open_flags: flags,
|
||||
is_empty: Arc::new(AtomicUsize::new(is_empty)),
|
||||
init_lock: Arc::new(Mutex::new(())),
|
||||
wal_checkpoint_disabled: Cell::new(false),
|
||||
};
|
||||
let db = Arc::new(db);
|
||||
|
||||
|
@ -674,7 +675,8 @@ impl Connection {
|
|||
/// If the WAL size is over the checkpoint threshold, it will checkpoint the WAL to
|
||||
/// the database file and then fsync the database file.
|
||||
pub fn cacheflush(&self) -> Result<PagerCacheflushStatus> {
|
||||
self.pager.cacheflush()
|
||||
self.pager
|
||||
.cacheflush(self._db.wal_checkpoint_disabled.get())
|
||||
}
|
||||
|
||||
pub fn clear_page_cache(&self) -> Result<()> {
|
||||
|
@ -683,12 +685,18 @@ impl Connection {
|
|||
}
|
||||
|
||||
pub fn checkpoint(&self) -> Result<CheckpointResult> {
|
||||
self.pager.wal_checkpoint()
|
||||
self.pager
|
||||
.wal_checkpoint(self._db.wal_checkpoint_disabled.get())
|
||||
}
|
||||
|
||||
/// Close a connection and checkpoint.
|
||||
pub fn close(&self) -> Result<()> {
|
||||
self.pager.checkpoint_shutdown()
|
||||
self.pager
|
||||
.checkpoint_shutdown(self._db.wal_checkpoint_disabled.get())
|
||||
}
|
||||
|
||||
pub fn wal_disable_checkpoint(&self) {
|
||||
self._db.wal_checkpoint_disabled.set(true);
|
||||
}
|
||||
|
||||
pub fn last_insert_rowid(&self) -> i64 {
|
||||
|
|
|
@ -7057,7 +7057,7 @@ mod tests {
|
|||
)
|
||||
.unwrap();
|
||||
loop {
|
||||
match pager.end_tx(false, false, &conn).unwrap() {
|
||||
match pager.end_tx(false, false, &conn, false).unwrap() {
|
||||
crate::PagerCacheflushStatus::Done(_) => break,
|
||||
crate::PagerCacheflushStatus::IO => {
|
||||
pager.io.run_once().unwrap();
|
||||
|
@ -7183,7 +7183,7 @@ mod tests {
|
|||
.unwrap();
|
||||
cursor.move_to_root();
|
||||
loop {
|
||||
match pager.end_tx(false, false, &conn).unwrap() {
|
||||
match pager.end_tx(false, false, &conn, false).unwrap() {
|
||||
crate::PagerCacheflushStatus::Done(_) => break,
|
||||
crate::PagerCacheflushStatus::IO => {
|
||||
pager.io.run_once().unwrap();
|
||||
|
|
|
@ -636,6 +636,7 @@ impl Pager {
|
|||
rollback: bool,
|
||||
change_schema: bool,
|
||||
connection: &Connection,
|
||||
wal_checkpoint_disabled: bool,
|
||||
) -> Result<PagerCacheflushStatus> {
|
||||
tracing::trace!("end_tx(rollback={})", rollback);
|
||||
if rollback {
|
||||
|
@ -643,7 +644,7 @@ impl Pager {
|
|||
self.wal.borrow().end_read_tx()?;
|
||||
return Ok(PagerCacheflushStatus::Done(PagerCacheflushResult::Rollback));
|
||||
}
|
||||
let cacheflush_status = self.cacheflush()?;
|
||||
let cacheflush_status = self.cacheflush(wal_checkpoint_disabled)?;
|
||||
match cacheflush_status {
|
||||
PagerCacheflushStatus::IO => Ok(PagerCacheflushStatus::IO),
|
||||
PagerCacheflushStatus::Done(_) => {
|
||||
|
@ -758,7 +759,7 @@ impl Pager {
|
|||
/// In the base case, it will write the dirty pages to the WAL and then fsync the WAL.
|
||||
/// If the WAL size is over the checkpoint threshold, it will checkpoint the WAL to
|
||||
/// the database file and then fsync the database file.
|
||||
pub fn cacheflush(&self) -> Result<PagerCacheflushStatus> {
|
||||
pub fn cacheflush(&self, wal_checkpoint_disabled: bool) -> Result<PagerCacheflushStatus> {
|
||||
let mut checkpoint_result = CheckpointResult::default();
|
||||
loop {
|
||||
let state = self.flush_info.borrow().state;
|
||||
|
@ -804,7 +805,7 @@ impl Pager {
|
|||
return Ok(PagerCacheflushStatus::IO);
|
||||
}
|
||||
|
||||
if !self.wal.borrow().should_checkpoint() {
|
||||
if wal_checkpoint_disabled || !self.wal.borrow().should_checkpoint() {
|
||||
self.flush_info.borrow_mut().state = FlushState::Start;
|
||||
return Ok(PagerCacheflushStatus::Done(
|
||||
PagerCacheflushResult::WalWritten,
|
||||
|
@ -912,7 +913,7 @@ impl Pager {
|
|||
.expect("Failed to clear page cache");
|
||||
}
|
||||
|
||||
pub fn checkpoint_shutdown(&self) -> Result<()> {
|
||||
pub fn checkpoint_shutdown(&self, wal_checkpoint_disabled: bool) -> Result<()> {
|
||||
let mut attempts = 0;
|
||||
{
|
||||
let mut wal = self.wal.borrow_mut();
|
||||
|
@ -927,11 +928,17 @@ impl Pager {
|
|||
attempts += 1;
|
||||
}
|
||||
}
|
||||
self.wal_checkpoint()?;
|
||||
self.wal_checkpoint(wal_checkpoint_disabled)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn wal_checkpoint(&self) -> Result<CheckpointResult> {
|
||||
pub fn wal_checkpoint(&self, wal_checkpoint_disabled: bool) -> Result<CheckpointResult> {
|
||||
if wal_checkpoint_disabled {
|
||||
return Ok(CheckpointResult {
|
||||
num_wal_frames: 0,
|
||||
num_checkpointed_frames: 0,
|
||||
});
|
||||
}
|
||||
let checkpoint_result: CheckpointResult;
|
||||
loop {
|
||||
match self.wal.borrow_mut().checkpoint(
|
||||
|
|
|
@ -469,7 +469,8 @@ impl Program {
|
|||
rollback: bool,
|
||||
change_schema: bool,
|
||||
) -> Result<StepResult> {
|
||||
let cacheflush_status = pager.end_tx(rollback, change_schema, connection)?;
|
||||
let cacheflush_status =
|
||||
pager.end_tx(rollback, change_schema, connection, connection._db.wal_checkpoint_disabled.get())?;
|
||||
match cacheflush_status {
|
||||
PagerCacheflushStatus::Done(_) => {
|
||||
if self.change_cnt_on {
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
# SQLite3 Implementation for Limbo
|
||||
# SQLite3 Implementation for Turso
|
||||
|
||||
This directory contains a Rust implementation of the SQLite3 C API. The implementation serves as a compatibility layer between SQLite's C API and Limbo's native Rust database implementation.
|
||||
This directory contains a Rust implementation of the SQLite3 C API. The implementation serves as a compatibility layer between SQLite's C API and Turso's native Rust database implementation.
|
||||
|
||||
## Purpose
|
||||
|
||||
This implementation provides SQLite3 API compatibility for Limbo, allowing existing applications that use SQLite to work with Limbo without modification. The code:
|
||||
This implementation provides SQLite3 API compatibility for Turso, allowing existing applications that use SQLite to work with Turso without modification. The code:
|
||||
|
||||
1. Implements the SQLite3 C API functions in Rust
|
||||
2. Translates between C and Rust data structures
|
||||
3. Maps SQLite operations to equivalent Limbo operations
|
||||
3. Maps SQLite operations to equivalent Turso operations
|
||||
4. Maintains API compatibility with SQLite version 3.42.0
|
||||
|
||||
## Testing Strategy
|
||||
|
|
|
@ -1188,6 +1188,17 @@ pub unsafe extern "C" fn libsql_wal_get_frame(
|
|||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn libsql_wal_disable_checkpoint(db: *mut sqlite3) -> ffi::c_int {
|
||||
if db.is_null() {
|
||||
return SQLITE_MISUSE;
|
||||
}
|
||||
let db: &mut sqlite3 = &mut *db;
|
||||
let db = db.inner.lock().unwrap();
|
||||
db.conn.wal_disable_checkpoint();
|
||||
SQLITE_OK
|
||||
}
|
||||
|
||||
fn sqlite3_safety_check_sick_or_ok(db: &sqlite3Inner) -> bool {
|
||||
match db.e_open_state {
|
||||
SQLITE_STATE_SICK | SQLITE_STATE_OPEN | SQLITE_STATE_BUSY => true,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue