Skip to content
This repository was archived by the owner on Oct 18, 2023. It is now read-only.

Commit 99ff0c9

Browse files
authored
Stop spawning long-lasting threads for libsql connections (#693)
* remove long lasting connection blocking thread * lock stealing * rollback when txn detects timeout. * busy handler fast path * fix deadlock and add more tests
1 parent b940b6d commit 99ff0c9

File tree

11 files changed

+632
-265
lines changed

11 files changed

+632
-265
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ members = [
88
]
99

1010
[workspace.dependencies]
11-
rusqlite = { version = "0.29.0", git = "https://github.com/psarna/rusqlite", rev = "2e28bca6", default-features = false, features = [
11+
rusqlite = { version = "0.29.0", git = "https://github.com/tursodatabase/rusqlite.git", rev = "a72d529", default-features = false, features = [
1212
"buildtime_bindgen",
1313
"bundled-libsql-wasm-experimental",
1414
"column_decltype",
15-
"load_extension"
15+
"load_extension",
16+
"modern_sqlite"
1617
] }
1718

1819
# Config for 'cargo dist'

sqld-libsql-bindings/src/lib.rs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
pub mod ffi;
44
pub mod wal_hook;
55

6-
use std::{ffi::CString, marker::PhantomData, ops::Deref, time::Duration};
6+
use std::{ffi::CString, ops::Deref, time::Duration};
77

88
pub use crate::wal_hook::WalMethodsHook;
99
pub use once_cell::sync::Lazy;
10+
use rusqlite::ffi::sqlite3;
11+
use wal_hook::TransparentMethods;
1012

1113
use self::{
1214
ffi::{libsql_wal_methods, libsql_wal_methods_find},
@@ -22,40 +24,45 @@ pub fn get_orig_wal_methods() -> anyhow::Result<*mut libsql_wal_methods> {
2224
Ok(orig)
2325
}
2426

25-
pub struct Connection<'a> {
27+
pub struct Connection<W: WalHook> {
2628
conn: rusqlite::Connection,
27-
_pth: PhantomData<&'a mut ()>,
29+
// Safety: _ctx MUST be dropped after the connection, because the connection has a pointer
30+
// This pointer MUST NOT move out of the connection
31+
_ctx: Box<W::Context>,
2832
}
2933

30-
impl Deref for Connection<'_> {
34+
impl<W: WalHook> Deref for Connection<W> {
3135
type Target = rusqlite::Connection;
3236

3337
fn deref(&self) -> &Self::Target {
3438
&self.conn
3539
}
3640
}
3741

38-
impl<'a> Connection<'a> {
42+
impl Connection<TransparentMethods> {
3943
/// returns a dummy, in-memory connection. For testing purposes only
40-
pub fn test(_: &mut ()) -> Self {
44+
pub fn test() -> Self {
4145
let conn = rusqlite::Connection::open_in_memory().unwrap();
4246
Self {
4347
conn,
44-
_pth: PhantomData,
48+
_ctx: Box::new(()),
4549
}
4650
}
51+
}
4752

53+
impl<W: WalHook> Connection<W> {
4854
/// Opens a database with the regular wal methods in the directory pointed to by path
49-
pub fn open<W: WalHook>(
55+
pub fn open(
5056
path: impl AsRef<std::path::Path>,
5157
flags: rusqlite::OpenFlags,
5258
// we technically _only_ need to know about W, but requiring a static ref to the wal_hook ensures that
5359
// it has been instanciated and lives for long enough
5460
_wal_hook: &'static WalMethodsHook<W>,
55-
hook_ctx: &'a mut W::Context,
61+
hook_ctx: W::Context,
5662
auto_checkpoint: u32,
5763
) -> Result<Self, rusqlite::Error> {
5864
let path = path.as_ref().join("data");
65+
let mut _ctx = Box::new(hook_ctx);
5966
tracing::trace!(
6067
"Opening a connection with regular WAL at {}",
6168
path.display()
@@ -75,7 +82,7 @@ impl<'a> Connection<'a> {
7582
flags.bits(),
7683
std::ptr::null_mut(),
7784
W::name().as_ptr(),
78-
hook_ctx as *mut _ as *mut _,
85+
_ctx.as_mut() as *mut _ as *mut _,
7986
);
8087

8188
if rc == 0 {
@@ -96,9 +103,14 @@ impl<'a> Connection<'a> {
96103
let conn = unsafe { rusqlite::Connection::from_handle_owned(db)? };
97104
conn.busy_timeout(Duration::from_millis(5000))?;
98105

99-
Ok(Connection {
100-
conn,
101-
_pth: PhantomData,
102-
})
106+
Ok(Connection { conn, _ctx })
107+
}
108+
109+
/// Returns the raw sqlite handle
110+
///
111+
/// # Safety
112+
/// The caller is responsible for the returned pointer.
113+
pub unsafe fn handle(&mut self) -> *mut sqlite3 {
114+
self.conn.handle()
103115
}
104116
}

0 commit comments

Comments
 (0)