parity_rocksdb_sys/
ffi.rs

1// Copyright 2014 Tyler Neely
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15
16use std::ffi::CStr;
17
18use libc;
19use libc::{c_char, c_uchar, c_int, c_void, size_t};
20use local_encoding::{Encoding, Encoder};
21
22pub enum DBOptionsOpaque {}
23pub type DBOptions = *const DBOptionsOpaque;
24
25pub enum DBInstanceOpaque {}
26pub type DBInstance = *const DBInstanceOpaque;
27
28pub enum DBWriteOptionsOpaque {}
29pub type DBWriteOptions = *const DBWriteOptionsOpaque;
30
31pub enum DBReadOptionsOpaque {}
32pub type DBReadOptions = *const DBReadOptionsOpaque;
33
34pub enum DBMergeOperatorOpaque {}
35pub type DBMergeOperator = *const DBMergeOperatorOpaque;
36
37pub enum DBBlockBasedTableOptionsOpaque {}
38pub type DBBlockBasedTableOptions = *const DBBlockBasedTableOptionsOpaque;
39
40pub enum DBCacheOpaque {}
41pub type DBCache = *const DBCacheOpaque;
42
43pub enum DBFilterPolicyOpaque {}
44pub type DBFilterPolicy = *const DBFilterPolicyOpaque;
45
46pub enum DBSnapshotOpaque {}
47pub type DBSnapshot = *const DBSnapshotOpaque;
48
49pub enum DBIteratorOpaque {}
50pub type DBIterator = *const DBIteratorOpaque;
51
52pub enum DBCFHandleOpaque {}
53pub type DBCFHandle = *const DBCFHandleOpaque;
54
55pub enum DBWriteBatchOpaque {}
56pub type DBWriteBatch = *const DBWriteBatchOpaque;
57
58pub enum DBComparatorOpaque {}
59pub type DBComparator = *const DBComparatorOpaque;
60
61pub enum DBSliceTransformOpaque {}
62pub type DBSliceTransform = *const DBSliceTransformOpaque;
63
64pub const BLOCK_BASED_INDEX_TYPE_BINARY_SEARCH: c_int = 0;
65pub const BLOCK_BASED_INDEX_TYPE_HASH_SEARCH: c_int = 1;
66
67pub fn new_bloom_filter(bits: c_int) -> DBFilterPolicy {
68    unsafe { rocksdb_filterpolicy_create_bloom(bits) }
69}
70
71pub fn new_cache(capacity: size_t) -> DBCache {
72    unsafe { rocksdb_cache_create_lru(capacity) }
73}
74
75#[repr(C)]
76pub enum DBCompressionType {
77    DBNoCompression = 0,
78    DBSnappyCompression = 1,
79    DBZlibCompression = 2,
80    DBBz2Compression = 3,
81    DBLz4Compression = 4,
82    DBLz4hcCompression = 5,
83}
84
85#[repr(C)]
86pub enum DBCompactionStyle {
87    DBLevelCompaction = 0,
88    DBUniversalCompaction = 1,
89    DBFifoCompaction = 2,
90}
91
92#[repr(C)]
93pub enum DBUniversalCompactionStyle {
94    rocksdb_similar_size_compaction_stop_style = 0,
95    rocksdb_total_size_compaction_stop_style = 1,
96}
97
98pub fn error_message(ptr: *const i8) -> String {
99    let c_str = unsafe { CStr::from_ptr(ptr as *const _) };
100    let s = Encoding::ANSI.to_string(c_str.to_bytes())
101        .unwrap_or_else(|_| "Error converting string".to_owned());
102    unsafe {
103        libc::free(ptr as *mut libc::c_void);
104    }
105    s
106}
107
108// TODO audit the use of boolean arguments, b/c I think they need to be u8
109// instead...
110#[link(name = "rocksdb")]
111extern "C" {
112    pub fn rocksdb_options_create() -> DBOptions;
113    pub fn rocksdb_options_destroy(opts: DBOptions);
114    pub fn rocksdb_cache_create_lru(capacity: size_t) -> DBCache;
115    pub fn rocksdb_cache_destroy(cache: DBCache);
116    pub fn rocksdb_block_based_options_create() -> DBBlockBasedTableOptions;
117    pub fn rocksdb_block_based_options_destroy(opts: DBBlockBasedTableOptions);
118    pub fn rocksdb_block_based_options_set_block_size(
119        block_options: DBBlockBasedTableOptions,
120        block_size: size_t);
121    pub fn rocksdb_block_based_options_set_block_size_deviation(
122        block_options: DBBlockBasedTableOptions,
123        block_size_deviation: c_int);
124    pub fn rocksdb_block_based_options_set_block_restart_interval(
125        block_options: DBBlockBasedTableOptions,
126        block_restart_interval: c_int);
127    pub fn rocksdb_block_based_options_set_filter_policy(
128        block_options: DBBlockBasedTableOptions,
129        filter_policy: DBFilterPolicy);
130    pub fn rocksdb_block_based_options_set_no_block_cache(
131        block_options: DBBlockBasedTableOptions, no_block_cache: bool);
132    pub fn rocksdb_block_based_options_set_block_cache(
133        block_options: DBBlockBasedTableOptions, block_cache: DBCache);
134    pub fn rocksdb_block_based_options_set_block_cache_compressed(
135        block_options: DBBlockBasedTableOptions,
136        block_cache_compressed: DBCache);
137    pub fn rocksdb_block_based_options_set_whole_key_filtering(
138        ck_options: DBBlockBasedTableOptions, doit: bool);
139    pub fn rocksdb_options_set_block_based_table_factory(
140        options: DBOptions,
141        block_options: DBBlockBasedTableOptions);
142    pub fn rocksdb_block_based_options_set_index_type(
143        block_options: DBBlockBasedTableOptions,
144        index_type: c_int);
145    pub fn rocksdb_options_increase_parallelism(options: DBOptions,
146                                                threads: c_int);
147    pub fn rocksdb_options_optimize_level_style_compaction(
148        options: DBOptions, memtable_memory_budget: c_int);
149    pub fn rocksdb_options_set_create_if_missing(options: DBOptions, v: bool);
150    pub fn rocksdb_options_set_max_open_files(options: DBOptions,
151                                              files: c_int);
152    pub fn rocksdb_options_set_use_fsync(options: DBOptions, v: c_int);
153    pub fn rocksdb_options_set_bytes_per_sync(options: DBOptions, bytes: u64);
154    pub fn rocksdb_options_optimize_for_point_lookup(options: DBOptions,
155                                                     block_cache_size_mb: u64);
156    pub fn rocksdb_options_set_table_cache_numshardbits(options: DBOptions,
157                                                        bits: c_int);
158    pub fn rocksdb_options_set_max_write_buffer_number(options: DBOptions,
159                                                       bufno: c_int);
160    pub fn rocksdb_options_set_min_write_buffer_number_to_merge(
161        options: DBOptions, bufno: c_int);
162    pub fn rocksdb_options_set_level0_file_num_compaction_trigger(
163        options: DBOptions, no: c_int);
164    pub fn rocksdb_options_set_level0_slowdown_writes_trigger(
165        options: DBOptions, no: c_int);
166    pub fn rocksdb_options_set_level0_stop_writes_trigger(options: DBOptions,
167                                                          no: c_int);
168    pub fn rocksdb_options_set_write_buffer_size(options: DBOptions,
169                                                 bytes: usize);
170    pub fn rocksdb_options_set_db_write_buffer_size(options: DBOptions,
171                                                 bytes: usize);
172    pub fn rocksdb_options_set_target_file_size_base(options: DBOptions,
173                                                     bytes: u64);
174    pub fn rocksdb_options_set_target_file_size_multiplier(options: DBOptions,
175                                                           mul: c_int);
176    pub fn rocksdb_options_set_max_log_file_size(options: DBOptions,
177                                                 bytes: usize);
178    pub fn rocksdb_options_set_max_manifest_file_size(options: DBOptions,
179                                                      bytes: usize);
180    pub fn rocksdb_options_set_hash_skip_list_rep(options: DBOptions,
181                                                  bytes: usize,
182                                                  a1: i32,
183                                                  a2: i32);
184    pub fn rocksdb_options_set_compaction_style(options: DBOptions,
185                                                cs: DBCompactionStyle);
186    pub fn rocksdb_options_set_compression(options: DBOptions,
187                                           compression_style_no: c_int);
188    pub fn rocksdb_options_set_max_background_compactions(
189        options: DBOptions, max_bg_compactions: c_int);
190    pub fn rocksdb_options_set_max_background_flushes(options: DBOptions,
191                                                      max_bg_flushes: c_int);
192    pub fn rocksdb_options_set_disable_auto_compactions(options: DBOptions,
193                                                        v: c_int);
194    pub fn rocksdb_options_set_prefix_extractor(options: DBOptions,
195                                                slice_transform: DBSliceTransform);
196    pub fn rocksdb_filterpolicy_create_bloom(bits_per_key: c_int)
197                                             -> DBFilterPolicy;
198    pub fn rocksdb_filterpolicy_destroy(filter: DBFilterPolicy);
199    pub fn rocksdb_open(options: DBOptions,
200                        path: *const i8,
201                        err: *mut *const i8)
202                        -> DBInstance;
203    pub fn rocksdb_writeoptions_create() -> DBWriteOptions;
204    pub fn rocksdb_writeoptions_destroy(writeopts: DBWriteOptions);
205    pub fn rocksdb_writeoptions_set_sync(writeopts: DBWriteOptions, v: bool);
206    pub fn rocksdb_writeoptions_disable_WAL(writeopts: DBWriteOptions,
207                                            v: c_int);
208    pub fn rocksdb_put(db: DBInstance,
209                       writeopts: DBWriteOptions,
210                       k: *const u8,
211                       kLen: size_t,
212                       v: *const u8,
213                       vLen: size_t,
214                       err: *mut *const i8);
215    pub fn rocksdb_put_cf(db: DBInstance,
216                          writeopts: DBWriteOptions,
217                          cf: DBCFHandle,
218                          k: *const u8,
219                          kLen: size_t,
220                          v: *const u8,
221                          vLen: size_t,
222                          err: *mut *const i8);
223    pub fn rocksdb_readoptions_create() -> DBReadOptions;
224    pub fn rocksdb_readoptions_destroy(readopts: DBReadOptions);
225    pub fn rocksdb_readoptions_set_verify_checksums(readopts: DBReadOptions,
226                                                    v: bool);
227    pub fn rocksdb_readoptions_set_fill_cache(readopts: DBReadOptions,
228                                              v: bool);
229    pub fn rocksdb_readoptions_set_snapshot(readopts: DBReadOptions,
230                                            snapshot: DBSnapshot); //TODO how do I make this a const ref?
231    pub fn rocksdb_readoptions_set_iterate_upper_bound(readopts: DBReadOptions,
232                                                       k: *const u8,
233                                                       kLen: size_t);
234    pub fn rocksdb_readoptions_set_read_tier(readopts: DBReadOptions,
235                                             tier: c_int);
236    pub fn rocksdb_readoptions_set_tailing(readopts: DBReadOptions, v: bool);
237
238    pub fn rocksdb_get(db: DBInstance,
239                       readopts: DBReadOptions,
240                       k: *const u8,
241                       kLen: size_t,
242                       valLen: *const size_t,
243                       err: *mut *const i8)
244                       -> *mut c_void;
245    pub fn rocksdb_get_cf(db: DBInstance,
246                          readopts: DBReadOptions,
247                          cf_handle: DBCFHandle,
248                          k: *const u8,
249                          kLen: size_t,
250                          valLen: *const size_t,
251                          err: *mut *const i8)
252                          -> *mut c_void;
253    pub fn rocksdb_create_iterator(db: DBInstance,
254                                   readopts: DBReadOptions)
255                                   -> DBIterator;
256    pub fn rocksdb_create_iterator_cf(db: DBInstance,
257                                      readopts: DBReadOptions,
258                                      cf_handle: DBCFHandle)
259                                      -> DBIterator;
260    pub fn rocksdb_create_snapshot(db: DBInstance) -> DBSnapshot;
261    pub fn rocksdb_release_snapshot(db: DBInstance, snapshot: DBSnapshot);
262
263    pub fn rocksdb_delete(db: DBInstance,
264                          writeopts: DBWriteOptions,
265                          k: *const u8,
266                          kLen: size_t,
267                          err: *mut *const i8)
268                          -> *mut c_void;
269    pub fn rocksdb_delete_cf(db: DBInstance,
270                             writeopts: DBWriteOptions,
271                             cf: DBCFHandle,
272                             k: *const u8,
273                             kLen: size_t,
274                             err: *mut *const i8)
275                             -> *mut c_void;
276    pub fn rocksdb_close(db: DBInstance);
277    pub fn rocksdb_destroy_db(options: DBOptions,
278                              path: *const i8,
279                              err: *mut *const i8);
280    pub fn rocksdb_repair_db(options: DBOptions,
281                             path: *const i8,
282                             err: *mut *const i8);
283    // Merge
284    pub fn rocksdb_merge(db: DBInstance,
285                         writeopts: DBWriteOptions,
286                         k: *const u8,
287                         kLen: size_t,
288                         v: *const u8,
289                         vLen: size_t,
290                         err: *mut *const i8);
291    pub fn rocksdb_merge_cf(db: DBInstance,
292                            writeopts: DBWriteOptions,
293                            cf: DBCFHandle,
294                            k: *const u8,
295                            kLen: size_t,
296                            v: *const u8,
297                            vLen: size_t,
298                            err: *mut *const i8);
299    pub fn rocksdb_mergeoperator_create(
300        state: *mut c_void,
301        destroy: extern fn(*mut c_void) -> (),
302        full_merge: extern fn (arg: *mut c_void,
303                               key: *const c_char, key_len: size_t,
304                               existing_value: *const c_char,
305                               existing_value_len: size_t,
306                               operands_list: *const *const c_char,
307                               operands_list_len: *const size_t,
308                               num_operands: c_int, success: *mut u8,
309                               new_value_length: *mut size_t
310                               ) -> *const c_char,
311        partial_merge: extern fn(arg: *mut c_void,
312                                 key: *const c_char, key_len: size_t,
313                                 operands_list: *const *const c_char,
314                                 operands_list_len: *const size_t,
315                                 num_operands: c_int, success: *mut u8,
316                                 new_value_length: *mut size_t
317                                 ) -> *const c_char,
318        delete_value: Option<extern "C" fn(*mut c_void,
319                                           value: *const c_char,
320                                           value_len: *mut size_t
321                                           ) -> ()>,
322        name_fn: extern fn(*mut c_void) -> *const c_char,
323    ) -> DBMergeOperator;
324    pub fn rocksdb_mergeoperator_destroy(mo: DBMergeOperator);
325    pub fn rocksdb_options_set_merge_operator(options: DBOptions,
326                                              mo: DBMergeOperator);
327    // Iterator
328    pub fn rocksdb_iter_destroy(iter: DBIterator);
329    pub fn rocksdb_iter_valid(iter: DBIterator) -> bool;
330    pub fn rocksdb_iter_seek_to_first(iter: DBIterator);
331    pub fn rocksdb_iter_seek_to_last(iter: DBIterator);
332    pub fn rocksdb_iter_seek(iter: DBIterator, key: *const u8, klen: size_t);
333    pub fn rocksdb_iter_next(iter: DBIterator);
334    pub fn rocksdb_iter_prev(iter: DBIterator);
335    pub fn rocksdb_iter_key(iter: DBIterator, klen: *mut size_t) -> *mut u8;
336    pub fn rocksdb_iter_value(iter: DBIterator, vlen: *mut size_t) -> *mut u8;
337    pub fn rocksdb_iter_get_error(iter: DBIterator, err: *mut *const u8);
338    // Write batch
339    pub fn rocksdb_write(db: DBInstance,
340                         writeopts: DBWriteOptions,
341                         batch: DBWriteBatch,
342                         err: *mut *const i8);
343    pub fn rocksdb_writebatch_create() -> DBWriteBatch;
344    pub fn rocksdb_writebatch_create_from(rep: *const u8,
345                                          size: size_t)
346                                          -> DBWriteBatch;
347    pub fn rocksdb_writebatch_destroy(batch: DBWriteBatch);
348    pub fn rocksdb_writebatch_clear(batch: DBWriteBatch);
349    pub fn rocksdb_writebatch_count(batch: DBWriteBatch) -> c_int;
350    pub fn rocksdb_writebatch_put(batch: DBWriteBatch,
351                                  key: *const u8,
352                                  klen: size_t,
353                                  val: *const u8,
354                                  vlen: size_t);
355    pub fn rocksdb_writebatch_put_cf(batch: DBWriteBatch,
356                                     cf: DBCFHandle,
357                                     key: *const u8,
358                                     klen: size_t,
359                                     val: *const u8,
360                                     vlen: size_t);
361    pub fn rocksdb_writebatch_merge(batch: DBWriteBatch,
362                                    key: *const u8,
363                                    klen: size_t,
364                                    val: *const u8,
365                                    vlen: size_t);
366    pub fn rocksdb_writebatch_merge_cf(batch: DBWriteBatch,
367                                       cf: DBCFHandle,
368                                       key: *const u8,
369                                       klen: size_t,
370                                       val: *const u8,
371                                       vlen: size_t);
372    pub fn rocksdb_writebatch_delete(batch: DBWriteBatch,
373                                     key: *const u8,
374                                     klen: size_t);
375    pub fn rocksdb_writebatch_delete_cf(batch: DBWriteBatch,
376                                        cf: DBCFHandle,
377                                        key: *const u8,
378                                        klen: size_t);
379    pub fn rocksdb_writebatch_iterate(
380        batch: DBWriteBatch,
381        state: *mut c_void,
382        put_fn: extern fn(state: *mut c_void,
383                          k: *const u8, klen: size_t,
384                          v: *const u8, vlen: size_t),
385        deleted_fn: extern fn(state: *mut c_void,
386                              k: *const u8, klen: size_t));
387    pub fn rocksdb_writebatch_data(batch: DBWriteBatch,
388                                   size: *mut size_t)
389                                   -> *const u8;
390
391    // Comparator
392    pub fn rocksdb_options_set_comparator(options: DBOptions,
393                                          cb: DBComparator);
394    pub fn rocksdb_comparator_create(state: *mut c_void,
395                                     destroy: extern "C" fn(*mut c_void) -> (),
396                                     compare: extern "C" fn(arg: *mut c_void,
397                                                            a: *const c_char,
398                                                            alen: size_t,
399                                                            b: *const c_char,
400                                                            blen: size_t)
401                                                            -> c_int,
402                                     name_fn: extern "C" fn(*mut c_void)
403                                                            -> *const c_char)
404                                     -> DBComparator;
405    pub fn rocksdb_comparator_destroy(cmp: DBComparator);
406
407    // Column Family
408    pub fn rocksdb_open_column_families(options: DBOptions,
409                                        path: *const i8,
410                                        num_column_families: c_int,
411                                        column_family_names: *const *const i8,
412                                        column_family_options: *const DBOptions,
413                                        column_family_handles: *const DBCFHandle,
414                                        err: *mut *const i8
415                                        ) -> DBInstance;
416    pub fn rocksdb_create_column_family(db: DBInstance,
417                                        column_family_options: DBOptions,
418                                        column_family_name: *const i8,
419                                        err: *mut *const i8)
420                                        -> DBCFHandle;
421    pub fn rocksdb_drop_column_family(db: DBInstance,
422                                      column_family_handle: DBCFHandle,
423                                      err: *mut *const i8);
424    pub fn rocksdb_column_family_handle_destroy(column_family_handle: DBCFHandle);
425
426    // Slice transformation
427    pub fn rocksdb_slicetransform_create(state: *mut c_void,
428                                         destructor: Option<extern "C" fn(arg1: *mut c_void) -> ()>,
429                                         transform: Option<extern "C" fn(arg1: *mut c_void,
430                                                                                 key: *const c_char,
431                                                                                 length: size_t,
432                                                                                 dst_length: *mut size_t)
433                                                                       -> *mut c_char>,
434                                         in_domain: Option<extern "C" fn(arg1: *mut c_void,
435                                                                                 key: *const c_char,
436                                                                                 length: size_t)
437                                                                       -> c_uchar>,
438                                         in_range: Option<extern "C" fn(arg1: *mut c_void,
439                                                                                 key: *const c_char,
440                                                                                 length: size_t)
441                                                                       -> c_uchar>,
442                                         name: Option<extern "C" fn(arg1: *mut c_void)
443                                                                       -> *const c_char>) -> DBSliceTransform;
444    pub fn rocksdb_slicetransform_create_fixed_prefix(size: size_t) -> DBSliceTransform;
445    pub fn rocksdb_slicetransform_create_noop() -> DBSliceTransform;
446    pub fn rocksdb_slicetransform_destroy(slice_transform: DBSliceTransform);
447
448    pub fn rocksdb_get_options_from_string(base_options: DBOptions, opts: *const i8, new_options: DBOptions, err: *mut *const i8);
449
450    pub fn rocksdb_property_int(
451        db: DBInstance,
452        prop: *const c_char,
453        value: *mut u64
454    ) -> c_int;
455
456    pub fn rocksdb_property_value(
457        db: DBInstance,
458        prop: *const c_char,
459    ) -> *const c_char;
460
461    pub fn rocksdb_property_value_cf(
462        db: DBInstance,
463        cf: DBCFHandle,
464        prop: *const c_char,
465    ) -> *const c_char;
466}
467
468#[test]
469fn internal() {
470    unsafe {
471        use std::ffi::CString;
472        let opts = rocksdb_options_create();
473        assert!(!opts.is_null());
474
475        rocksdb_options_increase_parallelism(opts, 0);
476        rocksdb_options_optimize_level_style_compaction(opts, 0);
477        rocksdb_options_set_create_if_missing(opts, true);
478
479        let rustpath = "_rust_rocksdb_internaltest";
480        let cpath = CString::new(rustpath).unwrap();
481        let cpath_ptr = cpath.as_ptr();
482
483        let mut err: *const i8 = 0 as *const i8;
484        let err_ptr: *mut *const i8 = &mut err;
485        let db = rocksdb_open(opts, cpath_ptr as *const _, err_ptr);
486        if !err.is_null() {
487            println!("failed to open rocksdb: {}", error_message(err));
488        }
489        assert!(err.is_null());
490
491        let writeopts = rocksdb_writeoptions_create();
492        assert!(!writeopts.is_null());
493
494        let key = b"name\x00";
495        let val = b"spacejam\x00";
496        rocksdb_put(db,
497                    writeopts.clone(),
498                    key.as_ptr(),
499                    4,
500                    val.as_ptr(),
501                    8,
502                    err_ptr);
503        rocksdb_writeoptions_destroy(writeopts);
504        assert!(err.is_null());
505
506        let readopts = rocksdb_readoptions_create();
507        assert!(!readopts.is_null());
508
509        let val_len: size_t = 0;
510        let val_len_ptr = &val_len as *const size_t;
511        rocksdb_get(db,
512                    readopts.clone(),
513                    key.as_ptr(),
514                    4,
515                    val_len_ptr,
516                    err_ptr);
517        rocksdb_readoptions_destroy(readopts);
518        assert!(err.is_null());
519        rocksdb_close(db);
520        rocksdb_destroy_db(opts, cpath_ptr as *const _, err_ptr);
521        assert!(err.is_null());
522
523        let base_options = rocksdb_options_create();
524        let opts_string = CString::new("rate_limiter_bytes_per_sec=1024").unwrap();
525        let opts_string_ptr = opts_string.as_ptr();
526        let new_options = rocksdb_options_create();
527        let mut err: *const i8 = 0 as *const i8;
528        let err_ptr: *mut *const i8 = &mut err;
529        rocksdb_get_options_from_string(base_options, opts_string_ptr as *const _, new_options, err_ptr);
530        if !err.is_null() {
531            println!("failed to open rocksdb: {}", error_message(err));
532        }
533    }
534}