This repository was archived by the owner on Oct 18, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathlib.rs
More file actions
107 lines (94 loc) · 3.18 KB
/
lib.rs
File metadata and controls
107 lines (94 loc) · 3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#![allow(improper_ctypes)]
pub mod ffi;
#[cfg(feature = "mwal_backend")]
pub mod mwal;
pub mod wal_hook;
use std::ops::Deref;
use anyhow::ensure;
use wal_hook::OwnedWalMethods;
use crate::{
ffi::libsql_wal_methods_register, ffi::libsql_wal_methods_unregister, wal_hook::WalMethodsHook,
};
use self::{
ffi::{libsql_wal_methods, libsql_wal_methods_find},
wal_hook::WalHook,
};
pub fn get_orig_wal_methods(with_bottomless: bool) -> anyhow::Result<*mut libsql_wal_methods> {
let orig: *mut libsql_wal_methods = if with_bottomless {
unsafe { libsql_wal_methods_find("bottomless\0".as_ptr() as *const _) }
} else {
unsafe { libsql_wal_methods_find(std::ptr::null()) }
};
if orig.is_null() {
anyhow::bail!("no underlying methods");
}
Ok(orig)
}
pub struct Connection {
// conn must be dropped first, do not reorder.
conn: rusqlite::Connection,
#[allow(dead_code)]
wal_methods: Option<OwnedWalMethods>,
}
impl Deref for Connection {
type Target = rusqlite::Connection;
fn deref(&self) -> &Self::Target {
&self.conn
}
}
// Registering WAL methods may be subject to race with the later call to libsql_wal_methods_find,
// if we overwrite methods with the same name. A short-term solution is to force register+find
// to be atomic.
// FIXME: a proper solution (Marin is working on it) is to be able to pass user data as a pointer
// directly to libsql_open()
static DB_OPENING_MUTEX: once_cell::sync::Lazy<parking_lot::Mutex<()>> =
once_cell::sync::Lazy::new(|| parking_lot::Mutex::new(()));
/// Opens a database with the regular wal methods in the directory pointed to by path
pub fn open_with_regular_wal(
path: impl AsRef<std::path::Path>,
flags: rusqlite::OpenFlags,
wal_hook: impl WalHook + 'static,
with_bottomless: bool,
) -> anyhow::Result<Connection> {
let opening_lock = DB_OPENING_MUTEX.lock();
let path = path.as_ref().join("data");
let mut wal_methods = unsafe {
let default_methods = get_orig_wal_methods(false)?;
let maybe_bottomless_methods = get_orig_wal_methods(with_bottomless)?;
let mut wrapped = WalMethodsHook::wrap(default_methods, maybe_bottomless_methods, wal_hook);
let res = libsql_wal_methods_register(wrapped.as_ptr());
ensure!(res == 0, "failed to register WAL methods");
wrapped
};
tracing::trace!(
"Opening a connection with regular WAL at {}",
path.display()
);
#[cfg(not(feature = "unix-excl-vfs"))]
let conn = rusqlite::Connection::open_with_flags_and_wal(
path,
flags,
WalMethodsHook::METHODS_NAME_STR,
)?;
#[cfg(feature = "unix-excl-vfs")]
let conn = rusqlite::Connection::open_with_flags_vfs_and_wal(
path,
flags,
"unix-excl",
WalMethodsHook::METHODS_NAME_STR,
)?;
unsafe {
libsql_wal_methods_unregister(wal_methods.as_ptr());
}
drop(opening_lock);
conn.pragma_update(None, "journal_mode", "wal")?;
conn.pragma(None, "journal_mode", "", |v| {
dbg!(v.get_unwrap::<_, String>(0));
Ok(())
})
.unwrap();
Ok(Connection {
conn,
wal_methods: Some(wal_methods),
})
}