From d5b96d5edfae557248792164cecbc33a7bb61d9c Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 9 May 2023 09:53:03 +0300 Subject: [PATCH 01/11] Move C bindings to separate crate --- core/mvcc/Cargo.toml | 3 +- core/mvcc/bindings/c/Cargo.toml | 18 +++++++ core/mvcc/bindings/c/src/lib.rs | 79 +++++++++++++++++++++++++++++++ core/mvcc/database/src/lib.rs | 84 +-------------------------------- 4 files changed, 100 insertions(+), 84 deletions(-) create mode 100644 core/mvcc/bindings/c/Cargo.toml create mode 100644 core/mvcc/bindings/c/src/lib.rs diff --git a/core/mvcc/Cargo.toml b/core/mvcc/Cargo.toml index ba0f2a813..c9e8d84ba 100644 --- a/core/mvcc/Cargo.toml +++ b/core/mvcc/Cargo.toml @@ -2,9 +2,10 @@ resolver = "2" members = [ "database", + "bindings/c", ] [profile.release] codegen-units = 1 panic = "abort" -strip = true +strip = true \ No newline at end of file diff --git a/core/mvcc/bindings/c/Cargo.toml b/core/mvcc/bindings/c/Cargo.toml new file mode 100644 index 000000000..a54329eca --- /dev/null +++ b/core/mvcc/bindings/c/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "mvcc-c" +version = "0.0.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] +doc = false + +[build-dependencies] +cbindgen = "0.24.0" + +[dependencies] +base64 = "0.21.0" +mvcc-rs = { path = "../../database", features = ["tokio"] } +tokio = { version = "1.27.0", features = ["full"] } +tracing = "0.1.37" +tracing-subscriber = { version = "0" } diff --git a/core/mvcc/bindings/c/src/lib.rs b/core/mvcc/bindings/c/src/lib.rs new file mode 100644 index 000000000..e0cc44fb4 --- /dev/null +++ b/core/mvcc/bindings/c/src/lib.rs @@ -0,0 +1,79 @@ +use mvcc_rs::*; + +type Clock = clock::LocalClock; +type Storage = persistent_storage::JsonOnDisk; +type Inner = database::DatabaseInner; +type Db = database::Database>; + +static INIT_RUST_LOG: std::sync::Once = std::sync::Once::new(); + +#[repr(C)] +pub struct DbContext { + db: Db, + runtime: tokio::runtime::Runtime, +} + +#[no_mangle] +pub extern "C" fn mvccrs_new_database(path: *const std::ffi::c_char) -> *mut DbContext { + INIT_RUST_LOG.call_once(|| { + tracing_subscriber::fmt::init(); + }); + + tracing::debug!("mvccrs_new_database"); + + let clock = clock::LocalClock::new(); + let path = unsafe { std::ffi::CStr::from_ptr(path) }; + let path = match path.to_str() { + Ok(path) => path, + Err(_) => { + tracing::error!("Invalid UTF-8 path"); + return std::ptr::null_mut(); + } + }; + tracing::debug!("mvccrs: opening persistent storage at {path}"); + let storage = crate::persistent_storage::JsonOnDisk::new(path); + let db = Db::new(clock, storage); + let runtime = tokio::runtime::Runtime::new().unwrap(); + Box::into_raw(Box::new(DbContext { db, runtime })) +} + +#[no_mangle] +pub unsafe extern "C" fn mvccrs_free_database(db: *mut Db) { + tracing::debug!("mvccrs_free_database"); + let _ = Box::from_raw(db); +} + +#[no_mangle] +pub unsafe extern "C" fn mvccrs_insert( + db: *mut DbContext, + id: u64, + value_ptr: *const u8, + value_len: usize, +) -> i32 { + let value = std::slice::from_raw_parts(value_ptr, value_len); + let data = match std::str::from_utf8(value) { + Ok(value) => value.to_string(), + Err(_) => { + tracing::info!("Invalid UTF-8, let's base64 this fellow"); + use base64::{engine::general_purpose, Engine as _}; + general_purpose::STANDARD.encode(value) + } + }; + let DbContext { db, runtime } = unsafe { &mut *db }; + let row = database::Row { id, data }; + tracing::debug!("mvccrs_insert: {row:?}"); + match runtime.block_on(async move { + let tx = db.begin_tx().await; + db.insert(tx, row).await?; + db.commit_tx(tx).await + }) { + Ok(_) => { + tracing::debug!("mvccrs_insert: success"); + 0 // SQLITE_OK + } + Err(e) => { + tracing::error!("mvccrs_insert: {e}"); + 778 // SQLITE_IOERR_WRITE + } + } +} diff --git a/core/mvcc/database/src/lib.rs b/core/mvcc/database/src/lib.rs index b671c908f..b14e27be3 100644 --- a/core/mvcc/database/src/lib.rs +++ b/core/mvcc/database/src/lib.rs @@ -35,86 +35,4 @@ pub mod clock; pub mod database; pub mod errors; pub mod persistent_storage; -pub mod sync; - -#[cfg(feature = "c_bindings")] -mod c_bindings { - use super::*; - type Clock = clock::LocalClock; - type Storage = persistent_storage::JsonOnDisk; - type Inner = database::DatabaseInner; - type Db = database::Database>; - - static INIT_RUST_LOG: std::sync::Once = std::sync::Once::new(); - - #[repr(C)] - pub struct DbContext { - db: Db, - runtime: tokio::runtime::Runtime, - } - - #[no_mangle] - pub extern "C" fn mvccrs_new_database(path: *const std::ffi::c_char) -> *mut DbContext { - INIT_RUST_LOG.call_once(|| { - tracing_subscriber::fmt::init(); - }); - - tracing::debug!("mvccrs_new_database"); - - let clock = clock::LocalClock::new(); - let path = unsafe { std::ffi::CStr::from_ptr(path) }; - let path = match path.to_str() { - Ok(path) => path, - Err(_) => { - tracing::error!("Invalid UTF-8 path"); - return std::ptr::null_mut(); - } - }; - tracing::debug!("mvccrs: opening persistent storage at {path}"); - let storage = crate::persistent_storage::JsonOnDisk::new(path); - let db = Db::new(clock, storage); - let runtime = tokio::runtime::Runtime::new().unwrap(); - Box::into_raw(Box::new(DbContext { db, runtime })) - } - - #[no_mangle] - pub unsafe extern "C" fn mvccrs_free_database(db: *mut Db) { - tracing::debug!("mvccrs_free_database"); - let _ = Box::from_raw(db); - } - - #[no_mangle] - pub unsafe extern "C" fn mvccrs_insert( - db: *mut DbContext, - id: u64, - value_ptr: *const u8, - value_len: usize, - ) -> i32 { - let value = std::slice::from_raw_parts(value_ptr, value_len); - let data = match std::str::from_utf8(value) { - Ok(value) => value.to_string(), - Err(_) => { - tracing::info!("Invalid UTF-8, let's base64 this fellow"); - use base64::{engine::general_purpose, Engine as _}; - general_purpose::STANDARD.encode(value) - } - }; - let DbContext { db, runtime } = unsafe { &mut *db }; - let row = database::Row { id, data }; - tracing::debug!("mvccrs_insert: {row:?}"); - match runtime.block_on(async move { - let tx = db.begin_tx().await; - db.insert(tx, row).await?; - db.commit_tx(tx).await - }) { - Ok(_) => { - tracing::debug!("mvccrs_insert: success"); - 0 // SQLITE_OK - } - Err(e) => { - tracing::error!("mvccrs_insert: {e}"); - 778 // SQLITE_IOERR_WRITE - } - } - } -} +pub mod sync; \ No newline at end of file From 124446f17c460cdd7ec987d89be90147d1a0d14b Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 9 May 2023 10:04:14 +0300 Subject: [PATCH 02/11] Generate C header file on `cargo build` --- core/mvcc/.gitignore | 3 ++- core/mvcc/bindings/c/build.rs | 6 ++++++ core/mvcc/bindings/c/cbindgen.toml | 6 ++++++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 core/mvcc/bindings/c/build.rs create mode 100644 core/mvcc/bindings/c/cbindgen.toml diff --git a/core/mvcc/.gitignore b/core/mvcc/.gitignore index 2c96eb1b6..48e69afa7 100644 --- a/core/mvcc/.gitignore +++ b/core/mvcc/.gitignore @@ -1,2 +1,3 @@ -target/ Cargo.lock +bindings/c/include +target/ diff --git a/core/mvcc/bindings/c/build.rs b/core/mvcc/bindings/c/build.rs new file mode 100644 index 000000000..af21fb9d8 --- /dev/null +++ b/core/mvcc/bindings/c/build.rs @@ -0,0 +1,6 @@ +use std::path::Path; + +fn main() { + let header_file = Path::new("include").join("mvcc.h"); + cbindgen::generate(".").expect("Failed to generate C bindings").write_to_file(header_file); +} diff --git a/core/mvcc/bindings/c/cbindgen.toml b/core/mvcc/bindings/c/cbindgen.toml new file mode 100644 index 000000000..b530dce1d --- /dev/null +++ b/core/mvcc/bindings/c/cbindgen.toml @@ -0,0 +1,6 @@ +language = "C" +cpp_compat = true +include_guard = "MVCC_H" +line_length = 120 +no_includes = true +style = "type" From 34a4f1a2697fdbd88089a3e51a1ea028e0951c15 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 9 May 2023 10:21:45 +0300 Subject: [PATCH 03/11] Improve generated C bindings Before: ```c typedef LocalClock Clock; typedef JsonOnDisk Storage; typedef DatabaseInner Inner; typedef Database> Db; typedef struct { Db db; Runtime runtime; } DbContext; extern "C" { DbContext *mvccrs_new_database(const char *path); void mvccrs_free_database(Db *db); int32_t mvccrs_insert(DbContext *db, uint64_t id, const uint8_t *value_ptr, uintptr_t value_len); } // extern "C" ``` After: ```c typedef struct DbContext DbContext; typedef const DbContext *MVCCDatabaseRef; extern "C" { MVCCDatabaseRef MVCCDatabaseOpen(const char *path); void MVCCDatabaseClose(MVCCDatabaseRef db); int32_t MVCCDatabaseInsert(MVCCDatabaseRef db, uint64_t id, const uint8_t *value_ptr, uintptr_t value_len); } // extern "C" ``` --- core/mvcc/bindings/c/src/lib.rs | 50 +++++++++++++++++++------------ core/mvcc/bindings/c/src/types.rs | 47 +++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 19 deletions(-) create mode 100644 core/mvcc/bindings/c/src/types.rs diff --git a/core/mvcc/bindings/c/src/lib.rs b/core/mvcc/bindings/c/src/lib.rs index e0cc44fb4..62b067c81 100644 --- a/core/mvcc/bindings/c/src/lib.rs +++ b/core/mvcc/bindings/c/src/lib.rs @@ -1,25 +1,31 @@ +#![allow(non_camel_case_types)] + +mod types; + +use types::{MVCCDatabaseRef, DbContext}; use mvcc_rs::*; +/// cbindgen:ignore type Clock = clock::LocalClock; + +/// cbindgen:ignore type Storage = persistent_storage::JsonOnDisk; + +/// cbindgen:ignore type Inner = database::DatabaseInner; + +/// cbindgen:ignore type Db = database::Database>; static INIT_RUST_LOG: std::sync::Once = std::sync::Once::new(); -#[repr(C)] -pub struct DbContext { - db: Db, - runtime: tokio::runtime::Runtime, -} - #[no_mangle] -pub extern "C" fn mvccrs_new_database(path: *const std::ffi::c_char) -> *mut DbContext { +pub extern "C" fn MVCCDatabaseOpen(path: *const std::ffi::c_char) -> MVCCDatabaseRef { INIT_RUST_LOG.call_once(|| { tracing_subscriber::fmt::init(); }); - tracing::debug!("mvccrs_new_database"); + tracing::debug!("MVCCDatabaseOpen"); let clock = clock::LocalClock::new(); let path = unsafe { std::ffi::CStr::from_ptr(path) }; @@ -27,29 +33,35 @@ pub extern "C" fn mvccrs_new_database(path: *const std::ffi::c_char) -> *mut DbC Ok(path) => path, Err(_) => { tracing::error!("Invalid UTF-8 path"); - return std::ptr::null_mut(); + return MVCCDatabaseRef::null(); } }; tracing::debug!("mvccrs: opening persistent storage at {path}"); let storage = crate::persistent_storage::JsonOnDisk::new(path); let db = Db::new(clock, storage); let runtime = tokio::runtime::Runtime::new().unwrap(); - Box::into_raw(Box::new(DbContext { db, runtime })) + let ctx = DbContext { db, runtime }; + let ctx = Box::leak(Box::new(ctx)); + MVCCDatabaseRef::from(ctx) } #[no_mangle] -pub unsafe extern "C" fn mvccrs_free_database(db: *mut Db) { - tracing::debug!("mvccrs_free_database"); - let _ = Box::from_raw(db); +pub unsafe extern "C" fn MVCCDatabaseClose(db: MVCCDatabaseRef) { + tracing::debug!("MVCCDatabaseClose"); + if db.is_null() { + return; + } + let _ = unsafe { Box::from_raw(db.get_ref_mut()) }; } #[no_mangle] -pub unsafe extern "C" fn mvccrs_insert( - db: *mut DbContext, +pub unsafe extern "C" fn MVCCDatabaseInsert( + db: MVCCDatabaseRef, id: u64, value_ptr: *const u8, value_len: usize, ) -> i32 { + let db = db.get_ref(); let value = std::slice::from_raw_parts(value_ptr, value_len); let data = match std::str::from_utf8(value) { Ok(value) => value.to_string(), @@ -59,20 +71,20 @@ pub unsafe extern "C" fn mvccrs_insert( general_purpose::STANDARD.encode(value) } }; - let DbContext { db, runtime } = unsafe { &mut *db }; + let (db, runtime) = (&db.db, &db.runtime); let row = database::Row { id, data }; - tracing::debug!("mvccrs_insert: {row:?}"); + tracing::debug!("MVCCDatabaseInsert: {row:?}"); match runtime.block_on(async move { let tx = db.begin_tx().await; db.insert(tx, row).await?; db.commit_tx(tx).await }) { Ok(_) => { - tracing::debug!("mvccrs_insert: success"); + tracing::debug!("MVCCDatabaseInsert: success"); 0 // SQLITE_OK } Err(e) => { - tracing::error!("mvccrs_insert: {e}"); + tracing::error!("MVCCDatabaseInsert: {e}"); 778 // SQLITE_IOERR_WRITE } } diff --git a/core/mvcc/bindings/c/src/types.rs b/core/mvcc/bindings/c/src/types.rs new file mode 100644 index 000000000..acb929dcd --- /dev/null +++ b/core/mvcc/bindings/c/src/types.rs @@ -0,0 +1,47 @@ +use crate::Db; + +#[repr(transparent)] +pub struct MVCCDatabaseRef { + ptr: *const DbContext, +} + +impl MVCCDatabaseRef { + pub fn null() -> MVCCDatabaseRef { + MVCCDatabaseRef { + ptr: std::ptr::null(), + } + } + + pub fn is_null(&self) -> bool { + self.ptr.is_null() + } + + pub fn get_ref(&self) -> &DbContext { + unsafe { &*(self.ptr) } + } + + #[allow(clippy::mut_from_ref)] + pub fn get_ref_mut(&self) -> &mut DbContext { + let ptr_mut = self.ptr as *mut DbContext; + unsafe { &mut (*ptr_mut) } + } +} + +#[allow(clippy::from_over_into)] +impl From<&DbContext> for MVCCDatabaseRef { + fn from(value: &DbContext) -> Self { + Self { ptr: value } + } +} + +#[allow(clippy::from_over_into)] +impl From<&mut DbContext> for MVCCDatabaseRef { + fn from(value: &mut DbContext) -> Self { + Self { ptr: value } + } +} + +pub struct DbContext { + pub(crate) db: Db, + pub(crate) runtime: tokio::runtime::Runtime, +} From 779ad3066a38cdfc88c3ca43c0cd46036b4087c2 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 9 May 2023 10:41:13 +0300 Subject: [PATCH 04/11] Add error codes to C bindings --- core/mvcc/bindings/c/src/errors.rs | 3 +++ core/mvcc/bindings/c/src/lib.rs | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 core/mvcc/bindings/c/src/errors.rs diff --git a/core/mvcc/bindings/c/src/errors.rs b/core/mvcc/bindings/c/src/errors.rs new file mode 100644 index 000000000..e260394f6 --- /dev/null +++ b/core/mvcc/bindings/c/src/errors.rs @@ -0,0 +1,3 @@ +pub const MVCC_OK: i32 = 0; + +pub const MVCC_IO_ERROR_WRITE: i32 = 778; diff --git a/core/mvcc/bindings/c/src/lib.rs b/core/mvcc/bindings/c/src/lib.rs index 62b067c81..6f4fc755a 100644 --- a/core/mvcc/bindings/c/src/lib.rs +++ b/core/mvcc/bindings/c/src/lib.rs @@ -1,8 +1,10 @@ #![allow(non_camel_case_types)] +mod errors; mod types; use types::{MVCCDatabaseRef, DbContext}; +use errors::*; use mvcc_rs::*; /// cbindgen:ignore @@ -81,11 +83,11 @@ pub unsafe extern "C" fn MVCCDatabaseInsert( }) { Ok(_) => { tracing::debug!("MVCCDatabaseInsert: success"); - 0 // SQLITE_OK + MVCC_OK } Err(e) => { tracing::error!("MVCCDatabaseInsert: {e}"); - 778 // SQLITE_IOERR_WRITE + MVCC_IO_ERROR_WRITE } } } From c94561a646b57a061c058c380c28f9c3a9a8fbb8 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 9 May 2023 10:41:33 +0300 Subject: [PATCH 05/11] Add `mvcc.h` to the tree --- core/mvcc/.gitignore | 1 - core/mvcc/bindings/c/include/mvcc.h | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 core/mvcc/bindings/c/include/mvcc.h diff --git a/core/mvcc/.gitignore b/core/mvcc/.gitignore index 48e69afa7..1e7caa9ea 100644 --- a/core/mvcc/.gitignore +++ b/core/mvcc/.gitignore @@ -1,3 +1,2 @@ Cargo.lock -bindings/c/include target/ diff --git a/core/mvcc/bindings/c/include/mvcc.h b/core/mvcc/bindings/c/include/mvcc.h new file mode 100644 index 000000000..92595e41b --- /dev/null +++ b/core/mvcc/bindings/c/include/mvcc.h @@ -0,0 +1,26 @@ +#ifndef MVCC_H +#define MVCC_H + +#define MVCC_OK 0 + +#define MVCC_IO_ERROR_WRITE 778 + +typedef struct DbContext DbContext; + +typedef const DbContext *MVCCDatabaseRef; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +MVCCDatabaseRef MVCCDatabaseOpen(const char *path); + +void MVCCDatabaseClose(MVCCDatabaseRef db); + +int32_t MVCCDatabaseInsert(MVCCDatabaseRef db, uint64_t id, const uint8_t *value_ptr, uintptr_t value_len); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif /* MVCC_H */ From 1fc99181f13f3765548c0ed05f68d47366e873f1 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 9 May 2023 10:42:05 +0300 Subject: [PATCH 06/11] Update README.md --- core/mvcc/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core/mvcc/README.md b/core/mvcc/README.md index fa279fcba..e48c3ac45 100644 --- a/core/mvcc/README.md +++ b/core/mvcc/README.md @@ -7,6 +7,7 @@ The aim of the project is to provide a building block for implementing database * Main memory architecture, rows are accessed via an index * Optimistic multi-version concurrency control +* Rust and C APIs ## Experimental Evaluation From db1e313aca8cc22f0569307e99cdb02fcd076c2f Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 9 May 2023 10:43:42 +0300 Subject: [PATCH 07/11] Silence clippy --- core/mvcc/bindings/c/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/core/mvcc/bindings/c/src/lib.rs b/core/mvcc/bindings/c/src/lib.rs index 6f4fc755a..85f5a07df 100644 --- a/core/mvcc/bindings/c/src/lib.rs +++ b/core/mvcc/bindings/c/src/lib.rs @@ -1,4 +1,5 @@ #![allow(non_camel_case_types)] +#![allow(clippy::missing_safety_doc)] mod errors; mod types; From 3ecb0fb2a96844a949c0a245b81be36136a65580 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 9 May 2023 10:44:06 +0300 Subject: [PATCH 08/11] Mark MVCCDatabaseOpen() as unsafe --- core/mvcc/bindings/c/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/mvcc/bindings/c/src/lib.rs b/core/mvcc/bindings/c/src/lib.rs index 85f5a07df..6efecf8d5 100644 --- a/core/mvcc/bindings/c/src/lib.rs +++ b/core/mvcc/bindings/c/src/lib.rs @@ -23,7 +23,7 @@ type Db = database::Database>; static INIT_RUST_LOG: std::sync::Once = std::sync::Once::new(); #[no_mangle] -pub extern "C" fn MVCCDatabaseOpen(path: *const std::ffi::c_char) -> MVCCDatabaseRef { +pub unsafe extern "C" fn MVCCDatabaseOpen(path: *const std::ffi::c_char) -> MVCCDatabaseRef { INIT_RUST_LOG.call_once(|| { tracing_subscriber::fmt::init(); }); From b2f46e156bdd6afa4472cb68bc68705263d922d5 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 9 May 2023 10:46:56 +0300 Subject: [PATCH 09/11] Improve C binding error reporting --- core/mvcc/bindings/c/include/mvcc.h | 9 +++++---- core/mvcc/bindings/c/src/errors.rs | 8 +++++--- core/mvcc/bindings/c/src/lib.rs | 10 +++++----- core/mvcc/database/src/lib.rs | 2 +- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/core/mvcc/bindings/c/include/mvcc.h b/core/mvcc/bindings/c/include/mvcc.h index 92595e41b..808c4047e 100644 --- a/core/mvcc/bindings/c/include/mvcc.h +++ b/core/mvcc/bindings/c/include/mvcc.h @@ -1,9 +1,10 @@ #ifndef MVCC_H #define MVCC_H -#define MVCC_OK 0 - -#define MVCC_IO_ERROR_WRITE 778 +typedef enum { + MVCC_OK = 0, + MVCC_IO_ERROR_WRITE = 778, +} MVCCError; typedef struct DbContext DbContext; @@ -17,7 +18,7 @@ MVCCDatabaseRef MVCCDatabaseOpen(const char *path); void MVCCDatabaseClose(MVCCDatabaseRef db); -int32_t MVCCDatabaseInsert(MVCCDatabaseRef db, uint64_t id, const uint8_t *value_ptr, uintptr_t value_len); +MVCCError MVCCDatabaseInsert(MVCCDatabaseRef db, uint64_t id, const uint8_t *value_ptr, uintptr_t value_len); #ifdef __cplusplus } // extern "C" diff --git a/core/mvcc/bindings/c/src/errors.rs b/core/mvcc/bindings/c/src/errors.rs index e260394f6..8b40ad2ba 100644 --- a/core/mvcc/bindings/c/src/errors.rs +++ b/core/mvcc/bindings/c/src/errors.rs @@ -1,3 +1,5 @@ -pub const MVCC_OK: i32 = 0; - -pub const MVCC_IO_ERROR_WRITE: i32 = 778; +#[repr(C)] +pub enum MVCCError { + MVCC_OK = 0, + MVCC_IO_ERROR_WRITE = 778, +} diff --git a/core/mvcc/bindings/c/src/lib.rs b/core/mvcc/bindings/c/src/lib.rs index 6efecf8d5..2a429cbdb 100644 --- a/core/mvcc/bindings/c/src/lib.rs +++ b/core/mvcc/bindings/c/src/lib.rs @@ -4,9 +4,9 @@ mod errors; mod types; -use types::{MVCCDatabaseRef, DbContext}; -use errors::*; +use errors::MVCCError; use mvcc_rs::*; +use types::{DbContext, MVCCDatabaseRef}; /// cbindgen:ignore type Clock = clock::LocalClock; @@ -63,7 +63,7 @@ pub unsafe extern "C" fn MVCCDatabaseInsert( id: u64, value_ptr: *const u8, value_len: usize, -) -> i32 { +) -> MVCCError { let db = db.get_ref(); let value = std::slice::from_raw_parts(value_ptr, value_len); let data = match std::str::from_utf8(value) { @@ -84,11 +84,11 @@ pub unsafe extern "C" fn MVCCDatabaseInsert( }) { Ok(_) => { tracing::debug!("MVCCDatabaseInsert: success"); - MVCC_OK + MVCCError::MVCC_OK } Err(e) => { tracing::error!("MVCCDatabaseInsert: {e}"); - MVCC_IO_ERROR_WRITE + MVCCError::MVCC_IO_ERROR_WRITE } } } diff --git a/core/mvcc/database/src/lib.rs b/core/mvcc/database/src/lib.rs index b14e27be3..d88011290 100644 --- a/core/mvcc/database/src/lib.rs +++ b/core/mvcc/database/src/lib.rs @@ -35,4 +35,4 @@ pub mod clock; pub mod database; pub mod errors; pub mod persistent_storage; -pub mod sync; \ No newline at end of file +pub mod sync; From 5ce2bc41f9209db71d78c4437ea42f18a124149a Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 9 May 2023 10:47:43 +0300 Subject: [PATCH 10/11] cargo fmt --- core/mvcc/bindings/c/build.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/mvcc/bindings/c/build.rs b/core/mvcc/bindings/c/build.rs index af21fb9d8..f418d0a9a 100644 --- a/core/mvcc/bindings/c/build.rs +++ b/core/mvcc/bindings/c/build.rs @@ -2,5 +2,7 @@ use std::path::Path; fn main() { let header_file = Path::new("include").join("mvcc.h"); - cbindgen::generate(".").expect("Failed to generate C bindings").write_to_file(header_file); + cbindgen::generate(".") + .expect("Failed to generate C bindings") + .write_to_file(header_file); } From 41bed4154415ec47a3bef8c2c6b607144ef3cc2d Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 9 May 2023 10:51:14 +0300 Subject: [PATCH 11/11] Improve logging --- core/mvcc/bindings/c/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/core/mvcc/bindings/c/src/lib.rs b/core/mvcc/bindings/c/src/lib.rs index 2a429cbdb..6eeffdeca 100644 --- a/core/mvcc/bindings/c/src/lib.rs +++ b/core/mvcc/bindings/c/src/lib.rs @@ -52,6 +52,7 @@ pub unsafe extern "C" fn MVCCDatabaseOpen(path: *const std::ffi::c_char) -> MVCC pub unsafe extern "C" fn MVCCDatabaseClose(db: MVCCDatabaseRef) { tracing::debug!("MVCCDatabaseClose"); if db.is_null() { + tracing::debug!("warning: `db` is null in MVCCDatabaseClose()"); return; } let _ = unsafe { Box::from_raw(db.get_ref_mut()) };