Skip to main content

sled/
lib.rs

1use sled;
2
3use std::ffi::CString;
4use std::mem;
5use std::ptr;
6use std::slice;
7
8use libc::*;
9
10use sled::{Config, Db, IVec, Iter};
11
12fn leak_buf(v: Vec<u8>, vallen: *mut size_t) -> *mut c_char {
13    unsafe {
14        *vallen = v.len();
15    }
16    let mut bsv = v.into_boxed_slice();
17    let val = bsv.as_mut_ptr() as *mut _;
18    mem::forget(bsv);
19    val
20}
21
22/// Create a new configuration.
23#[no_mangle]
24pub unsafe extern "C" fn sled_create_config() -> *mut Config {
25    Box::into_raw(Box::new(Config::new()))
26}
27
28/// Destroy a configuration.
29#[no_mangle]
30pub unsafe extern "C" fn sled_free_config(config: *mut Config) {
31    drop(Box::from_raw(config));
32}
33
34/// Set the configured file path. The caller is responsible for freeing the path
35/// string after calling this (it is copied in this function).
36#[no_mangle]
37pub unsafe extern "C" fn sled_config_set_path(
38    config: *mut Config,
39    path: *const c_char,
40) -> *mut Config {
41    let c_str = CString::from_raw(path as *mut _);
42    let value = c_str.into_string().unwrap();
43
44    let config = Box::from_raw(config);
45    Box::into_raw(Box::from(config.path(value)))
46}
47
48/// Set the configured cache capacity in bytes.
49#[no_mangle]
50pub unsafe extern "C" fn sled_config_set_cache_capacity(
51    config: *mut Config,
52    capacity: size_t,
53) -> *mut Config {
54    let config = Box::from_raw(config);
55    Box::into_raw(Box::from(config.cache_capacity(capacity as u64)))
56}
57
58/// Configure the use of the zstd compression library.
59#[no_mangle]
60pub unsafe extern "C" fn sled_config_use_compression(
61    config: *mut Config,
62    use_compression: c_uchar,
63) -> *mut Config {
64    let config = Box::from_raw(config);
65    Box::into_raw(Box::from(config.use_compression(use_compression == 1)))
66}
67
68/// Set the configured IO buffer flush interval in milliseconds.
69#[no_mangle]
70pub unsafe extern "C" fn sled_config_flush_every_ms(
71    config: *mut Config,
72    flush_every: c_int,
73) -> *mut Config {
74    let val = if flush_every < 0 { None } else { Some(flush_every as u64) };
75    let config = Box::from_raw(config);
76    Box::into_raw(Box::from(config.flush_every_ms(val)))
77}
78
79/// Open a sled lock-free log-structured tree. Consumes the passed-in config.
80#[no_mangle]
81pub unsafe extern "C" fn sled_open_db(config: *mut Config) -> *mut Db {
82    let config = Box::from_raw(config);
83    Box::into_raw(Box::new(config.open().unwrap()))
84}
85
86/// Close a sled lock-free log-structured tree.
87#[no_mangle]
88pub unsafe extern "C" fn sled_close(db: *mut Db) {
89    drop(Box::from_raw(db));
90}
91
92/// Free a buffer originally allocated by sled.
93#[no_mangle]
94pub unsafe extern "C" fn sled_free_buf(buf: *mut c_char, sz: size_t) {
95    drop(Vec::from_raw_parts(buf, sz, sz));
96}
97
98/// Free an iterator.
99#[no_mangle]
100pub unsafe extern "C" fn sled_free_iter(iter: *mut Iter) {
101    drop(Box::from_raw(iter));
102}
103
104/// Set a key to a value.
105#[no_mangle]
106pub unsafe extern "C" fn sled_set(
107    db: *mut Db,
108    key: *const c_uchar,
109    keylen: size_t,
110    val: *const c_uchar,
111    vallen: size_t,
112) {
113    let k = IVec::from(slice::from_raw_parts(key, keylen));
114    let v = IVec::from(slice::from_raw_parts(val, vallen));
115    (*db).insert(k, v).unwrap();
116}
117
118/// Get the value of a key.
119/// Caller is responsible for freeing the returned value with `sled_free_buf` if
120/// it's non-null.
121#[no_mangle]
122pub unsafe extern "C" fn sled_get(
123    db: *mut Db,
124    key: *const c_char,
125    keylen: size_t,
126    vallen: *mut size_t,
127) -> *mut c_char {
128    let k = slice::from_raw_parts(key as *const u8, keylen);
129    let res = (*db).get(k);
130    match res {
131        Ok(Some(v)) => leak_buf(v.to_vec(), vallen),
132        Ok(None) => ptr::null_mut(),
133        // TODO proper error propagation
134        Err(e) => panic!("{:?}", e),
135    }
136}
137
138/// Delete the value of a key.
139#[no_mangle]
140pub unsafe extern "C" fn sled_del(
141    db: *mut Db,
142    key: *const c_char,
143    keylen: size_t,
144) {
145    let k = slice::from_raw_parts(key as *const u8, keylen);
146    (*db).remove(k).unwrap();
147}
148
149/// Compare and swap.
150/// Returns 1 if successful, 0 if unsuccessful.
151/// Otherwise sets `actual_val` and `actual_vallen` to the current value,
152/// which must be freed using `sled_free_buf` by the caller if non-null.
153/// `actual_val` will be null and `actual_vallen` 0 if the current value is not
154/// set.
155#[no_mangle]
156pub unsafe extern "C" fn sled_compare_and_swap(
157    db: *mut Db,
158    key: *const c_char,
159    keylen: size_t,
160    old_val: *const c_uchar,
161    old_vallen: size_t,
162    new_val: *const c_uchar,
163    new_vallen: size_t,
164    actual_val: *mut *const c_uchar,
165    actual_vallen: *mut size_t,
166) -> c_uchar {
167    let k = IVec::from(slice::from_raw_parts(key as *const u8, keylen));
168
169    let old = if old_vallen == 0 {
170        None
171    } else {
172        let copy =
173            IVec::from(slice::from_raw_parts(old_val as *const u8, old_vallen));
174        Some(copy)
175    };
176
177    let new = if new_vallen == 0 {
178        None
179    } else {
180        let copy =
181            IVec::from(slice::from_raw_parts(new_val as *const u8, new_vallen));
182        Some(copy)
183    };
184
185    let res = (*db).compare_and_swap(k, old, new);
186
187    match res {
188        Ok(Ok(())) => 1,
189        Ok(Err(sled::CompareAndSwapError { current: None, .. })) => {
190            *actual_vallen = 0;
191            0
192        }
193        Ok(Err(sled::CompareAndSwapError { current: Some(v), .. })) => {
194            *actual_val = leak_buf(v.to_vec(), actual_vallen) as *const u8;
195            0
196        }
197        // TODO proper error propagation
198        Err(e) => panic!("{:?}", e),
199    }
200}
201
202/// Iterate over tuples which have specified key prefix.
203/// Caller is responsible for freeing the returned iterator with
204/// `sled_free_iter`.
205#[no_mangle]
206pub unsafe extern "C" fn sled_scan_prefix(
207    db: *mut Db,
208    key: *const c_char,
209    keylen: size_t,
210) -> *mut Iter {
211    let k = slice::from_raw_parts(key as *const u8, keylen);
212    Box::into_raw(Box::new((*db).scan_prefix(k)))
213}
214
215/// Get they next kv pair from an iterator.
216/// Caller is responsible for freeing the key and value with `sled_free_buf`.
217/// Returns 0 when exhausted.
218#[no_mangle]
219pub unsafe extern "C" fn sled_iter_next(
220    iter: *mut Iter,
221    key: *mut *const c_char,
222    keylen: *mut size_t,
223    val: *mut *const c_char,
224    vallen: *mut size_t,
225) -> c_uchar {
226    match (*iter).next() {
227        Some(Ok((k, v))) => {
228            *key = leak_buf(k.to_vec(), keylen);
229            *val = leak_buf(v.to_vec(), vallen);
230            1
231        }
232        // TODO proper error propagation
233        Some(Err(e)) => panic!("{:?}", e),
234        None => 0,
235    }
236}