Skip to content

Commit 682ac9d

Browse files
committed
libsql: add wal frame_count and get_frame safe fn
This just moves unsafe wal code from safe database code to their own self contained safe fn. This clears up the safe and unsafe boundary instead of mixing and matching like before. This also creates a clear point of audit of our unsafe usage.
1 parent 265bd83 commit 682ac9d

File tree

2 files changed

+40
-18
lines changed

2 files changed

+40
-18
lines changed

libsql/src/local/connection.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,43 @@ impl Connection {
445445
}
446446
}
447447
}
448+
449+
pub(crate) fn wal_frame_count(&self) -> u32 {
450+
let mut max_frame_no: std::os::raw::c_uint = 0;
451+
unsafe { libsql_sys::ffi::libsql_wal_frame_count(self.handle(), &mut max_frame_no) };
452+
453+
max_frame_no
454+
}
455+
456+
pub(crate) fn wal_get_frame(&self, frame_no: u32, page_size: u32) -> Result<bytes::BytesMut> {
457+
use bytes::BufMut;
458+
459+
let frame_size: usize = 24 + page_size as usize;
460+
461+
// Use a BytesMut to provide cheaper clones of frame data (think retries)
462+
// and more efficient buffer usage for extracting wal frames and spliting them off.
463+
let mut buf = bytes::BytesMut::with_capacity(frame_size);
464+
465+
let rc = unsafe {
466+
libsql_sys::ffi::libsql_wal_get_frame(
467+
self.handle(),
468+
frame_no,
469+
buf.chunk_mut().as_mut_ptr() as *mut _,
470+
frame_size as u32,
471+
)
472+
};
473+
474+
if rc != 0 {
475+
return Err(crate::errors::Error::SqliteFailure(
476+
rc as std::ffi::c_int,
477+
format!("Failed to get frame: {}", frame_no),
478+
));
479+
}
480+
481+
unsafe { buf.advance_mut(frame_size) };
482+
483+
Ok(buf)
484+
}
448485
}
449486

450487
impl fmt::Debug for Connection {

libsql/src/local/database.rs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -395,8 +395,7 @@ impl Database {
395395
page_size
396396
};
397397

398-
let mut max_frame_no: std::os::raw::c_uint = 0;
399-
unsafe { libsql_sys::ffi::libsql_wal_frame_count(conn.handle(), &mut max_frame_no) };
398+
let max_frame_no = conn.wal_frame_count();
400399

401400
let generation = 1; // TODO: Probe from WAL.
402401
let start_frame_no = sync_ctx.durable_frame_num + 1;
@@ -432,22 +431,8 @@ impl Database {
432431
frame_no: u32,
433432
page_size: u32,
434433
) -> Result<u32> {
435-
let frame_size: usize = 24 + page_size as usize;
436-
let frame = vec![0; frame_size];
437-
let rc = unsafe {
438-
libsql_sys::ffi::libsql_wal_get_frame(
439-
conn.handle(),
440-
frame_no,
441-
frame.as_ptr() as *mut _,
442-
frame_size as u32,
443-
)
444-
};
445-
if rc != 0 {
446-
return Err(crate::errors::Error::SqliteFailure(
447-
rc as std::ffi::c_int,
448-
format!("Failed to get frame: {}", frame_no),
449-
));
450-
}
434+
let frame = conn.wal_get_frame(frame_no, page_size)?;
435+
451436
let uri = format!(
452437
"{}/sync/{}/{}/{}",
453438
sync_ctx.sync_url,

0 commit comments

Comments
 (0)