parent
f342a62ac2
commit
ffefbd0907
@ -1,500 +0,0 @@ |
||||
// Copyright 2014 Tyler Neely
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
extern crate libc; |
||||
use self::libc::{c_char, c_uchar, c_int, c_void, size_t}; |
||||
use std::ffi::CStr; |
||||
use std::str::from_utf8; |
||||
|
||||
pub enum DBOptionsOpaque {} |
||||
pub type DBOptions = *const DBOptionsOpaque; |
||||
|
||||
pub enum DBInstanceOpaque {} |
||||
pub type DBInstance = *const DBInstanceOpaque; |
||||
|
||||
pub enum DBWriteOptionsOpaque {} |
||||
pub type DBWriteOptions = *const DBWriteOptionsOpaque; |
||||
|
||||
pub enum DBReadOptionsOpaque {} |
||||
pub type DBReadOptions = *const DBReadOptionsOpaque; |
||||
|
||||
pub enum DBMergeOperatorOpaque {} |
||||
pub type DBMergeOperator = *const DBMergeOperatorOpaque; |
||||
|
||||
pub enum DBBlockBasedTableOptionsOpaque {} |
||||
pub type DBBlockBasedTableOptions = *const DBBlockBasedTableOptionsOpaque; |
||||
|
||||
pub enum DBCacheOpaque {} |
||||
pub type DBCache = *const DBCacheOpaque; |
||||
|
||||
pub enum DBFilterPolicyOpaque {} |
||||
pub type DBFilterPolicy = *const DBFilterPolicyOpaque; |
||||
|
||||
pub enum DBSnapshotOpaque {} |
||||
pub type DBSnapshot = *const DBSnapshotOpaque; |
||||
|
||||
pub enum DBIteratorOpaque {} |
||||
pub type DBIterator = *const DBIteratorOpaque; |
||||
|
||||
pub enum DBCFHandleOpaque {} |
||||
pub type DBCFHandle = *const DBCFHandleOpaque; |
||||
|
||||
pub enum DBWriteBatchOpaque {} |
||||
pub type DBWriteBatch = *const DBWriteBatchOpaque; |
||||
|
||||
pub enum DBComparatorOpaque {} |
||||
pub type DBComparator = *const DBComparatorOpaque; |
||||
|
||||
pub enum DBSliceTransformOpaque {} |
||||
pub type DBSliceTransform = *const DBSliceTransformOpaque; |
||||
|
||||
pub const BLOCK_BASED_INDEX_TYPE_BINARY_SEARCH: c_int = 0; |
||||
pub const BLOCK_BASED_INDEX_TYPE_HASH_SEARCH: c_int = 1; |
||||
|
||||
pub fn new_bloom_filter(bits: c_int) -> DBFilterPolicy { |
||||
unsafe { rocksdb_filterpolicy_create_bloom(bits) } |
||||
} |
||||
|
||||
pub fn new_cache(capacity: size_t) -> DBCache { |
||||
unsafe { rocksdb_cache_create_lru(capacity) } |
||||
} |
||||
|
||||
#[derive(Copy, Clone)] |
||||
#[repr(C)] |
||||
pub enum DBCompressionType { |
||||
None = 0, |
||||
Snappy = 1, |
||||
Zlib = 2, |
||||
Bz2 = 3, |
||||
Lz4 = 4, |
||||
Lz4hc = 5, |
||||
} |
||||
|
||||
#[repr(C)] |
||||
pub enum DBCompactionStyle { |
||||
Level = 0, |
||||
Universal = 1, |
||||
Fifo = 2, |
||||
} |
||||
|
||||
#[repr(C)] |
||||
pub enum DBUniversalCompactionStyle { |
||||
rocksdb_similar_size_compaction_stop_style = 0, |
||||
rocksdb_total_size_compaction_stop_style = 1, |
||||
} |
||||
|
||||
#[derive(Copy, Clone, PartialEq)] |
||||
#[repr(C)] |
||||
pub enum DBRecoveryMode { |
||||
TolerateCorruptedTailRecords = 0, |
||||
AbsoluteConsistency = 1, |
||||
PointInTime = 2, |
||||
SkipAnyCorruptedRecords = 3, |
||||
} |
||||
|
||||
pub fn error_message(ptr: *const i8) -> String { |
||||
let c_str = unsafe { CStr::from_ptr(ptr as *const _) }; |
||||
let s = from_utf8(c_str.to_bytes()).unwrap().to_owned(); |
||||
unsafe { |
||||
libc::free(ptr as *mut libc::c_void); |
||||
} |
||||
s |
||||
} |
||||
|
||||
// TODO audit the use of boolean arguments, b/c I think they need to be u8
|
||||
// instead...
|
||||
#[link(name = "rocksdb")] |
||||
extern "C" { |
||||
pub fn rocksdb_options_create() -> DBOptions; |
||||
pub fn rocksdb_options_destroy(opts: DBOptions); |
||||
pub fn rocksdb_cache_create_lru(capacity: size_t) -> DBCache; |
||||
pub fn rocksdb_cache_destroy(cache: DBCache); |
||||
pub fn rocksdb_block_based_options_create() -> DBBlockBasedTableOptions; |
||||
pub fn rocksdb_block_based_options_destroy(opts: DBBlockBasedTableOptions); |
||||
pub fn rocksdb_block_based_options_set_block_size( |
||||
block_options: DBBlockBasedTableOptions, |
||||
block_size: size_t); |
||||
pub fn rocksdb_block_based_options_set_block_size_deviation( |
||||
block_options: DBBlockBasedTableOptions, |
||||
block_size_deviation: c_int); |
||||
pub fn rocksdb_block_based_options_set_block_restart_interval( |
||||
block_options: DBBlockBasedTableOptions, |
||||
block_restart_interval: c_int); |
||||
pub fn rocksdb_block_based_options_set_cache_index_and_filter_blocks( |
||||
block_options: DBBlockBasedTableOptions, v: c_uchar); |
||||
pub fn rocksdb_block_based_options_set_filter_policy( |
||||
block_options: DBBlockBasedTableOptions, |
||||
filter_policy: DBFilterPolicy); |
||||
pub fn rocksdb_block_based_options_set_no_block_cache( |
||||
block_options: DBBlockBasedTableOptions, no_block_cache: bool); |
||||
pub fn rocksdb_block_based_options_set_block_cache( |
||||
block_options: DBBlockBasedTableOptions, block_cache: DBCache); |
||||
pub fn rocksdb_block_based_options_set_block_cache_compressed( |
||||
block_options: DBBlockBasedTableOptions, |
||||
block_cache_compressed: DBCache); |
||||
pub fn rocksdb_block_based_options_set_whole_key_filtering( |
||||
ck_options: DBBlockBasedTableOptions, doit: bool); |
||||
pub fn rocksdb_options_set_block_based_table_factory( |
||||
options: DBOptions, |
||||
block_options: DBBlockBasedTableOptions); |
||||
pub fn rocksdb_options_increase_parallelism(options: DBOptions, |
||||
threads: c_int); |
||||
pub fn rocksdb_options_optimize_level_style_compaction( |
||||
options: DBOptions, memtable_memory_budget: c_int); |
||||
pub fn rocksdb_options_set_create_if_missing(options: DBOptions, v: bool); |
||||
pub fn rocksdb_options_set_max_open_files(options: DBOptions, |
||||
files: c_int); |
||||
pub fn rocksdb_options_set_use_fsync(options: DBOptions, v: c_int); |
||||
pub fn rocksdb_options_set_bytes_per_sync(options: DBOptions, bytes: u64); |
||||
pub fn rocksdb_options_set_disable_data_sync(options: DBOptions, |
||||
v: c_int); |
||||
pub fn rocksdb_options_set_allow_os_buffer(options: DBOptions, is_allow: bool); |
||||
pub fn rocksdb_options_optimize_for_point_lookup(options: DBOptions, |
||||
block_cache_size_mb: u64); |
||||
pub fn rocksdb_options_set_table_cache_numshardbits(options: DBOptions, |
||||
bits: c_int); |
||||
pub fn rocksdb_options_set_max_write_buffer_number(options: DBOptions, |
||||
bufno: c_int); |
||||
pub fn rocksdb_options_set_min_write_buffer_number_to_merge( |
||||
options: DBOptions, bufno: c_int); |
||||
pub fn rocksdb_options_set_level0_file_num_compaction_trigger( |
||||
options: DBOptions, no: c_int); |
||||
pub fn rocksdb_options_set_level0_slowdown_writes_trigger( |
||||
options: DBOptions, no: c_int); |
||||
pub fn rocksdb_options_set_level0_stop_writes_trigger(options: DBOptions, |
||||
no: c_int); |
||||
pub fn rocksdb_options_set_write_buffer_size(options: DBOptions, |
||||
bytes: usize); |
||||
pub fn rocksdb_options_set_target_file_size_base(options: DBOptions, |
||||
bytes: u64); |
||||
pub fn rocksdb_options_set_target_file_size_multiplier(options: DBOptions, |
||||
mul: c_int); |
||||
pub fn rocksdb_options_set_max_bytes_for_level_base(options: DBOptions, bytes: u64); |
||||
pub fn rocksdb_options_set_max_bytes_for_level_multiplier(options: DBOptions, mul: c_int); |
||||
pub fn rocksdb_options_set_max_log_file_size(options: DBOptions, |
||||
bytes: usize); |
||||
pub fn rocksdb_options_set_max_manifest_file_size(options: DBOptions, |
||||
bytes: usize); |
||||
pub fn rocksdb_options_set_hash_skip_list_rep(options: DBOptions, |
||||
bytes: usize, |
||||
a1: i32, |
||||
a2: i32); |
||||
pub fn rocksdb_options_set_compaction_style(options: DBOptions, |
||||
cs: DBCompactionStyle); |
||||
pub fn rocksdb_options_set_compression(options: DBOptions, |
||||
compression_style_no: DBCompressionType); |
||||
pub fn rocksdb_options_set_compression_per_level(options: DBOptions, |
||||
level_values: *const DBCompressionType, |
||||
num_levels: size_t); |
||||
pub fn rocksdb_options_set_max_background_compactions( |
||||
options: DBOptions, max_bg_compactions: c_int); |
||||
pub fn rocksdb_options_set_max_background_flushes(options: DBOptions, |
||||
max_bg_flushes: c_int); |
||||
pub fn rocksdb_options_set_disable_auto_compactions(options: DBOptions, |
||||
v: c_int); |
||||
pub fn rocksdb_options_set_report_bg_io_stats(options: DBOptions, v: c_int); |
||||
pub fn rocksdb_options_set_wal_recovery_mode(options: DBOptions, mode: DBRecoveryMode); |
||||
pub fn rocksdb_options_enable_statistics(options: DBOptions); |
||||
pub fn rocksdb_options_statistics_get_string(options: DBOptions) -> *const c_char; |
||||
pub fn rocksdb_options_set_stats_dump_period_sec(options: DBOptions, v: usize); |
||||
pub fn rocksdb_options_set_num_levels(options: DBOptions, v: c_int); |
||||
pub fn rocksdb_filterpolicy_create_bloom_full(bits_per_key: c_int) |
||||
-> DBFilterPolicy; |
||||
pub fn rocksdb_filterpolicy_create_bloom(bits_per_key: c_int) |
||||
-> DBFilterPolicy; |
||||
pub fn rocksdb_open(options: DBOptions, |
||||
path: *const i8, |
||||
err: *mut *const i8) |
||||
-> DBInstance; |
||||
pub fn rocksdb_writeoptions_create() -> DBWriteOptions; |
||||
pub fn rocksdb_writeoptions_destroy(writeopts: DBWriteOptions); |
||||
pub fn rocksdb_writeoptions_set_sync(writeopts: DBWriteOptions, v: bool); |
||||
pub fn rocksdb_writeoptions_disable_WAL(writeopts: DBWriteOptions, |
||||
v: c_int); |
||||
pub fn rocksdb_put(db: DBInstance, |
||||
writeopts: DBWriteOptions, |
||||
k: *const u8, |
||||
kLen: size_t, |
||||
v: *const u8, |
||||
vLen: size_t, |
||||
err: *mut *const i8); |
||||
pub fn rocksdb_put_cf(db: DBInstance, |
||||
writeopts: DBWriteOptions, |
||||
cf: DBCFHandle, |
||||
k: *const u8, |
||||
kLen: size_t, |
||||
v: *const u8, |
||||
vLen: size_t, |
||||
err: *mut *const i8); |
||||
pub fn rocksdb_readoptions_create() -> DBReadOptions; |
||||
pub fn rocksdb_readoptions_destroy(readopts: DBReadOptions); |
||||
pub fn rocksdb_readoptions_set_verify_checksums(readopts: DBReadOptions, |
||||
v: bool); |
||||
pub fn rocksdb_readoptions_set_fill_cache(readopts: DBReadOptions, |
||||
v: bool); |
||||
pub fn rocksdb_readoptions_set_snapshot(readopts: DBReadOptions, |
||||
snapshot: DBSnapshot); //TODO how do I make this a const ref?
|
||||
pub fn rocksdb_readoptions_set_iterate_upper_bound(readopts: DBReadOptions, |
||||
k: *const u8, |
||||
kLen: size_t); |
||||
pub fn rocksdb_readoptions_set_read_tier(readopts: DBReadOptions, |
||||
tier: c_int); |
||||
pub fn rocksdb_readoptions_set_tailing(readopts: DBReadOptions, v: bool); |
||||
|
||||
pub fn rocksdb_get(db: DBInstance, |
||||
readopts: DBReadOptions, |
||||
k: *const u8, |
||||
kLen: size_t, |
||||
valLen: *const size_t, |
||||
err: *mut *const i8) |
||||
-> *mut c_void; |
||||
pub fn rocksdb_get_cf(db: DBInstance, |
||||
readopts: DBReadOptions, |
||||
cf_handle: DBCFHandle, |
||||
k: *const u8, |
||||
kLen: size_t, |
||||
valLen: *const size_t, |
||||
err: *mut *const i8) |
||||
-> *mut c_void; |
||||
pub fn rocksdb_create_iterator(db: DBInstance, |
||||
readopts: DBReadOptions) |
||||
-> DBIterator; |
||||
pub fn rocksdb_create_iterator_cf(db: DBInstance, |
||||
readopts: DBReadOptions, |
||||
cf_handle: DBCFHandle) |
||||
-> DBIterator; |
||||
pub fn rocksdb_create_snapshot(db: DBInstance) -> DBSnapshot; |
||||
pub fn rocksdb_release_snapshot(db: DBInstance, snapshot: DBSnapshot); |
||||
|
||||
pub fn rocksdb_delete(db: DBInstance, |
||||
writeopts: DBWriteOptions, |
||||
k: *const u8, |
||||
kLen: size_t, |
||||
err: *mut *const i8) |
||||
-> *mut c_void; |
||||
pub fn rocksdb_delete_cf(db: DBInstance, |
||||
writeopts: DBWriteOptions, |
||||
cf: DBCFHandle, |
||||
k: *const u8, |
||||
kLen: size_t, |
||||
err: *mut *const i8) |
||||
-> *mut c_void; |
||||
pub fn rocksdb_close(db: DBInstance); |
||||
pub fn rocksdb_destroy_db(options: DBOptions, |
||||
path: *const i8, |
||||
err: *mut *const i8); |
||||
pub fn rocksdb_repair_db(options: DBOptions, |
||||
path: *const i8, |
||||
err: *mut *const i8); |
||||
// Merge
|
||||
pub fn rocksdb_merge(db: DBInstance, |
||||
writeopts: DBWriteOptions, |
||||
k: *const u8, |
||||
kLen: size_t, |
||||
v: *const u8, |
||||
vLen: size_t, |
||||
err: *mut *const i8); |
||||
pub fn rocksdb_merge_cf(db: DBInstance, |
||||
writeopts: DBWriteOptions, |
||||
cf: DBCFHandle, |
||||
k: *const u8, |
||||
kLen: size_t, |
||||
v: *const u8, |
||||
vLen: size_t, |
||||
err: *mut *const i8); |
||||
pub fn rocksdb_mergeoperator_create( |
||||
state: *mut c_void, |
||||
destroy: extern fn(*mut c_void) -> (), |
||||
full_merge: extern fn (arg: *mut c_void, |
||||
key: *const c_char, key_len: size_t, |
||||
existing_value: *const c_char, |
||||
existing_value_len: size_t, |
||||
operands_list: *const *const c_char, |
||||
operands_list_len: *const size_t, |
||||
num_operands: c_int, success: *mut u8, |
||||
new_value_length: *mut size_t |
||||
) -> *const c_char, |
||||
partial_merge: extern fn(arg: *mut c_void, |
||||
key: *const c_char, key_len: size_t, |
||||
operands_list: *const *const c_char, |
||||
operands_list_len: *const size_t, |
||||
num_operands: c_int, success: *mut u8, |
||||
new_value_length: *mut size_t |
||||
) -> *const c_char, |
||||
delete_value: Option<extern "C" fn(*mut c_void, |
||||
value: *const c_char, |
||||
value_len: *mut size_t |
||||
) -> ()>, |
||||
name_fn: extern fn(*mut c_void) -> *const c_char, |
||||
) -> DBMergeOperator; |
||||
pub fn rocksdb_mergeoperator_destroy(mo: DBMergeOperator); |
||||
pub fn rocksdb_options_set_merge_operator(options: DBOptions, |
||||
mo: DBMergeOperator); |
||||
// Iterator
|
||||
pub fn rocksdb_iter_destroy(iter: DBIterator); |
||||
pub fn rocksdb_iter_valid(iter: DBIterator) -> bool; |
||||
pub fn rocksdb_iter_seek_to_first(iter: DBIterator); |
||||
pub fn rocksdb_iter_seek_to_last(iter: DBIterator); |
||||
pub fn rocksdb_iter_seek(iter: DBIterator, key: *const u8, klen: size_t); |
||||
pub fn rocksdb_iter_next(iter: DBIterator); |
||||
pub fn rocksdb_iter_prev(iter: DBIterator); |
||||
pub fn rocksdb_iter_key(iter: DBIterator, klen: *mut size_t) -> *mut u8; |
||||
pub fn rocksdb_iter_value(iter: DBIterator, vlen: *mut size_t) -> *mut u8; |
||||
pub fn rocksdb_iter_get_error(iter: DBIterator, err: *mut *const u8); |
||||
// Write batch
|
||||
pub fn rocksdb_write(db: DBInstance, |
||||
writeopts: DBWriteOptions, |
||||
batch: DBWriteBatch, |
||||
err: *mut *const i8); |
||||
pub fn rocksdb_writebatch_create() -> DBWriteBatch; |
||||
pub fn rocksdb_writebatch_create_from(rep: *const u8, |
||||
size: size_t) |
||||
-> DBWriteBatch; |
||||
pub fn rocksdb_writebatch_destroy(batch: DBWriteBatch); |
||||
pub fn rocksdb_writebatch_clear(batch: DBWriteBatch); |
||||
pub fn rocksdb_writebatch_count(batch: DBWriteBatch) -> c_int; |
||||
pub fn rocksdb_writebatch_put(batch: DBWriteBatch, |
||||
key: *const u8, |
||||
klen: size_t, |
||||
val: *const u8, |
||||
vlen: size_t); |
||||
pub fn rocksdb_writebatch_put_cf(batch: DBWriteBatch, |
||||
cf: DBCFHandle, |
||||
key: *const u8, |
||||
klen: size_t, |
||||
val: *const u8, |
||||
vlen: size_t); |
||||
pub fn rocksdb_writebatch_merge(batch: DBWriteBatch, |
||||
key: *const u8, |
||||
klen: size_t, |
||||
val: *const u8, |
||||
vlen: size_t); |
||||
pub fn rocksdb_writebatch_merge_cf(batch: DBWriteBatch, |
||||
cf: DBCFHandle, |
||||
key: *const u8, |
||||
klen: size_t, |
||||
val: *const u8, |
||||
vlen: size_t); |
||||
pub fn rocksdb_writebatch_delete(batch: DBWriteBatch, |
||||
key: *const u8, |
||||
klen: size_t); |
||||
pub fn rocksdb_writebatch_delete_cf(batch: DBWriteBatch, |
||||
cf: DBCFHandle, |
||||
key: *const u8, |
||||
klen: size_t); |
||||
pub fn rocksdb_writebatch_iterate( |
||||
batch: DBWriteBatch, |
||||
state: *mut c_void, |
||||
put_fn: extern fn(state: *mut c_void, |
||||
k: *const u8, klen: size_t, |
||||
v: *const u8, vlen: size_t), |
||||
deleted_fn: extern fn(state: *mut c_void, |
||||
k: *const u8, klen: size_t)); |
||||
pub fn rocksdb_writebatch_data(batch: DBWriteBatch, |
||||
size: *mut size_t) |
||||
-> *const u8; |
||||
|
||||
// Comparator
|
||||
pub fn rocksdb_options_set_comparator(options: DBOptions, |
||||
cb: DBComparator); |
||||
pub fn rocksdb_comparator_create(state: *mut c_void, |
||||
destroy: extern "C" fn(*mut c_void) -> (), |
||||
compare: extern "C" fn(arg: *mut c_void, |
||||
a: *const c_char, |
||||
alen: size_t, |
||||
b: *const c_char, |
||||
blen: size_t) |
||||
-> c_int, |
||||
name_fn: extern "C" fn(*mut c_void) |
||||
-> *const c_char) |
||||
-> DBComparator; |
||||
pub fn rocksdb_comparator_destroy(cmp: DBComparator); |
||||
|
||||
// Column Family
|
||||
pub fn rocksdb_open_column_families(options: DBOptions, |
||||
path: *const i8, |
||||
num_column_families: c_int, |
||||
column_family_names: *const *const i8, |
||||
column_family_options: *const DBOptions, |
||||
column_family_handles: *const DBCFHandle, |
||||
err: *mut *const i8 |
||||
) -> DBInstance; |
||||
pub fn rocksdb_create_column_family(db: DBInstance, |
||||
column_family_options: DBOptions, |
||||
column_family_name: *const i8, |
||||
err: *mut *const i8) |
||||
-> DBCFHandle; |
||||
pub fn rocksdb_drop_column_family(db: DBInstance, |
||||
column_family_handle: DBCFHandle, |
||||
err: *mut *const i8); |
||||
pub fn rocksdb_column_family_handle_destroy(column_family_handle: DBCFHandle); |
||||
|
||||
} |
||||
|
||||
#[test] |
||||
fn internal() { |
||||
unsafe { |
||||
use std::ffi::CString; |
||||
let opts = rocksdb_options_create(); |
||||
assert!(!opts.is_null()); |
||||
|
||||
rocksdb_options_increase_parallelism(opts, 0); |
||||
rocksdb_options_optimize_level_style_compaction(opts, 0); |
||||
rocksdb_options_set_create_if_missing(opts, true); |
||||
|
||||
let rustpath = "_rust_rocksdb_internaltest"; |
||||
let cpath = CString::new(rustpath).unwrap(); |
||||
let cpath_ptr = cpath.as_ptr(); |
||||
|
||||
let mut err: *const i8 = 0 as *const i8; |
||||
let err_ptr: *mut *const i8 = &mut err; |
||||
let db = rocksdb_open(opts, cpath_ptr as *const _, err_ptr); |
||||
if !err.is_null() { |
||||
println!("failed to open rocksdb: {}", error_message(err)); |
||||
} |
||||
assert!(err.is_null()); |
||||
|
||||
let writeopts = rocksdb_writeoptions_create(); |
||||
assert!(!writeopts.is_null()); |
||||
|
||||
let key = b"name\x00"; |
||||
let val = b"spacejam\x00"; |
||||
rocksdb_put(db, |
||||
writeopts.clone(), |
||||
key.as_ptr(), |
||||
4, |
||||
val.as_ptr(), |
||||
8, |
||||
err_ptr); |
||||
rocksdb_writeoptions_destroy(writeopts); |
||||
assert!(err.is_null()); |
||||
|
||||
let readopts = rocksdb_readoptions_create(); |
||||
assert!(!readopts.is_null()); |
||||
|
||||
let val_len: size_t = 0; |
||||
let val_len_ptr = &val_len as *const size_t; |
||||
rocksdb_get(db, |
||||
readopts.clone(), |
||||
key.as_ptr(), |
||||
4, |
||||
val_len_ptr, |
||||
err_ptr); |
||||
rocksdb_readoptions_destroy(readopts); |
||||
assert!(err.is_null()); |
||||
rocksdb_close(db); |
||||
rocksdb_destroy_db(opts, cpath_ptr as *const _, err_ptr); |
||||
assert!(err.is_null()); |
||||
} |
||||
} |
@ -0,0 +1,86 @@ |
||||
// Copyright 2014 Tyler Neely
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
use libc::*; |
||||
use std::ffi::{CStr, CString}; |
||||
use std::ptr; |
||||
use std::str; |
||||
|
||||
use super::*; |
||||
|
||||
pub fn error_message(ptr: *const i8) -> String { |
||||
let c_str = unsafe { CStr::from_ptr(ptr as *const _) }; |
||||
let s = str::from_utf8(c_str.to_bytes()).unwrap().to_owned(); |
||||
unsafe { |
||||
free(ptr as *mut c_void); |
||||
} |
||||
s |
||||
} |
||||
|
||||
#[test] |
||||
fn internal() { |
||||
unsafe { |
||||
let opts = rocksdb_options_create(); |
||||
assert!(!opts.is_null()); |
||||
|
||||
rocksdb_options_increase_parallelism(opts, 0); |
||||
rocksdb_options_optimize_level_style_compaction(opts, 0); |
||||
rocksdb_options_set_create_if_missing(opts, true as c_uchar); |
||||
|
||||
let rustpath = "_rust_rocksdb_internaltest"; |
||||
let cpath = CString::new(rustpath).unwrap(); |
||||
let cpath_ptr = cpath.as_ptr(); |
||||
|
||||
let mut err: *mut c_char = ptr::null_mut(); |
||||
let err_ptr: *mut *mut c_char = &mut err; |
||||
let db = rocksdb_open(opts, cpath_ptr as *const _, err_ptr); |
||||
if !err.is_null() { |
||||
println!("failed to open rocksdb: {}", error_message(err)); |
||||
} |
||||
assert!(err.is_null()); |
||||
|
||||
let writeopts = rocksdb_writeoptions_create(); |
||||
assert!(!writeopts.is_null()); |
||||
|
||||
let key = b"name\x00"; |
||||
let val = b"spacejam\x00"; |
||||
rocksdb_put(db, |
||||
writeopts.clone(), |
||||
key.as_ptr() as *const c_char, |
||||
4, |
||||
val.as_ptr() as *const c_char, |
||||
8, |
||||
err_ptr); |
||||
rocksdb_writeoptions_destroy(writeopts); |
||||
assert!(err.is_null()); |
||||
|
||||
let readopts = rocksdb_readoptions_create(); |
||||
assert!(!readopts.is_null()); |
||||
|
||||
let mut val_len: size_t = 0; |
||||
let val_len_ptr = &mut val_len as *mut size_t; |
||||
rocksdb_get(db, |
||||
readopts.clone(), |
||||
key.as_ptr() as *const c_char, |
||||
4, |
||||
val_len_ptr, |
||||
err_ptr); |
||||
rocksdb_readoptions_destroy(readopts); |
||||
assert!(err.is_null()); |
||||
rocksdb_close(db); |
||||
rocksdb_destroy_db(opts, cpath_ptr as *const _, err_ptr); |
||||
assert!(err.is_null()); |
||||
} |
||||
} |
@ -0,0 +1,950 @@ |
||||
// This code is based on <https://github.com/facebook/rocksdb/blob/master/db/c_test.c>, revision a10e8a056d569acf6a52045124e6414ad33bdfcd.
|
||||
|
||||
#![allow(non_snake_case, non_upper_case_globals, unused_mut, unused_unsafe, unused_variables)] |
||||
|
||||
#[macro_use] |
||||
extern crate const_cstr; |
||||
extern crate libc; |
||||
extern crate rocksdb_sys as ffi; |
||||
|
||||
use ::ffi::*; |
||||
use ::libc::*; |
||||
use ::std::borrow::Cow; |
||||
use ::std::env; |
||||
use ::std::ffi::{CStr, CString}; |
||||
use ::std::io::Write; |
||||
use ::std::mem; |
||||
use ::std::path::PathBuf; |
||||
use ::std::ptr; |
||||
use ::std::slice; |
||||
use ::std::str; |
||||
|
||||
macro_rules! err_println { |
||||
($($arg:tt)*) => (writeln!(&mut ::std::io::stderr(), $($arg)*).expect("failed printing to stderr")); |
||||
} |
||||
|
||||
macro_rules! cstr { |
||||
($($arg:tt)*) => (const_cstr!($($arg)*)); |
||||
} |
||||
|
||||
macro_rules! cstrp { |
||||
($($arg:tt)*) => (const_cstr!($($arg)*).as_ptr()); |
||||
} |
||||
|
||||
static mut phase: &'static str = ""; |
||||
// static mut dbname: *mut c_uchar = ptr::null_mut();
|
||||
// static mut dbbackupname: *mut c_uchar = ptr::null_mut();
|
||||
|
||||
unsafe fn strndup(s: *const c_char, n: size_t) -> *mut c_char { |
||||
let r: *mut c_char = malloc(n + 1) as *mut c_char; |
||||
if r.is_null() { |
||||
return r; |
||||
} |
||||
strncpy(r, s, n) |
||||
} |
||||
|
||||
unsafe fn rstr<'a>(s: *const c_char) -> Cow<'a, str> { |
||||
CStr::from_ptr(s).to_string_lossy() |
||||
} |
||||
|
||||
fn GetTempDir() -> PathBuf { |
||||
return match option_env!("TEST_TMPDIR") { |
||||
Some("") | None => env::temp_dir(), |
||||
Some(s) => s.into(), |
||||
}; |
||||
} |
||||
|
||||
unsafe fn StartPhase(name: &'static str) { |
||||
err_println!("=== Test {}\n", name); |
||||
phase = name; |
||||
} |
||||
|
||||
macro_rules! CheckNoError { |
||||
($err:ident) => { unsafe { |
||||
assert!($err.is_null(), "{}: {}", phase, rstr($err)); |
||||
} }; |
||||
} |
||||
|
||||
macro_rules! CheckCondition { |
||||
($cond:expr) => { unsafe { |
||||
assert!($cond, "{}: {}", phase, stringify!($cond)); |
||||
} }; |
||||
} |
||||
|
||||
unsafe fn CheckEqual(expected: *const c_char, v: *const c_char, n: size_t) { |
||||
if expected.is_null() && v.is_null() { |
||||
// ok
|
||||
} else if !expected.is_null() && !v.is_null() && n == strlen(expected) && memcmp(expected as *const c_void, v as *const c_void, n) == 0 { |
||||
// ok
|
||||
} else { |
||||
panic!("{}: expected '{}', got '{}'", phase, rstr(strndup(expected, n)), rstr(strndup(v, 5))); |
||||
} |
||||
} |
||||
|
||||
unsafe fn Free<T>(ptr: *mut *mut T) { |
||||
if !(*ptr).is_null() { |
||||
free(*ptr as *mut c_void); |
||||
*ptr = ptr::null_mut(); |
||||
} |
||||
} |
||||
|
||||
unsafe fn CheckGet(mut db: *mut rocksdb_t, options: *mut rocksdb_readoptions_t, key: *const c_char, expected: *const c_char) { |
||||
let mut err: *mut c_char = ptr::null_mut(); |
||||
let mut val_len: size_t = 0; |
||||
let mut val: *mut c_char = rocksdb_get(db, options, key, strlen(key), &mut val_len, &mut err); |
||||
CheckNoError!(err); |
||||
CheckEqual(expected, val, val_len); |
||||
Free(&mut val); |
||||
} |
||||
|
||||
unsafe fn CheckGetCF(db: *mut rocksdb_t, options: *const rocksdb_readoptions_t, handle: *mut rocksdb_column_family_handle_t, key: *const c_char, expected: *const c_char) { |
||||
let mut err: *mut c_char = ptr::null_mut(); |
||||
let mut val_len: size_t = 0; |
||||
let mut val: *mut c_char = rocksdb_get_cf(db, options, handle, key, strlen(key), &mut val_len, &mut err); |
||||
CheckNoError!(err); |
||||
CheckEqual(expected, val, val_len); |
||||
Free(&mut val); |
||||
} |
||||
|
||||
unsafe fn CheckIter(iter: *mut rocksdb_iterator_t, key: *const c_char, val: *const c_char) { |
||||
let mut len: size_t = 0; |
||||
let mut str: *const c_char; |
||||
str = rocksdb_iter_key(iter, &mut len); |
||||
CheckEqual(key, str, len); |
||||
str = rocksdb_iter_value(iter, &mut len); |
||||
CheckEqual(val, str, len); |
||||
} |
||||
|
||||
// Callback from rocksdb_writebatch_iterate()
|
||||
unsafe extern "C" fn CheckPut(ptr: *mut c_void, k: *const c_char, klen: size_t, v: *const c_char, vlen: size_t) { |
||||
let mut state: *mut c_int = ptr as *mut c_int; |
||||
CheckCondition!(*state < 2); |
||||
match *state { |
||||
0 => { |
||||
CheckEqual(cstrp!("bar"), k, klen); |
||||
CheckEqual(cstrp!("b"), v, vlen); |
||||
}, |
||||
1 => { |
||||
CheckEqual(cstrp!("box"), k, klen); |
||||
CheckEqual(cstrp!("c"), v, vlen); |
||||
}, |
||||
_ => { }, |
||||
} |
||||
*state += 1; |
||||
} |
||||
|
||||
// Callback from rocksdb_writebatch_iterate()
|
||||
unsafe extern "C" fn CheckDel(ptr: *mut c_void, k: *const c_char, klen: size_t) { |
||||
let mut state: *mut c_int = ptr as *mut c_int; |
||||
CheckCondition!(*state == 2); |
||||
CheckEqual(cstrp!("bar"), k, klen); |
||||
*state += 1; |
||||
} |
||||
|
||||
unsafe extern "C" fn CmpDestroy(arg: *mut c_void) { } |
||||
|
||||
unsafe extern "C" fn CmpCompare(arg: *mut c_void, a: *const c_char, alen: size_t, b: *const c_char, blen: size_t) -> c_int { |
||||
let n = if alen < blen { alen } else { blen }; |
||||
let mut r = memcmp(a as *const c_void, b as *const c_void, n); |
||||
if r == 0 { |
||||
if alen < blen { |
||||
r = -1; |
||||
} else if alen > blen { |
||||
r = 1; |
||||
} |
||||
} |
||||
r |
||||
} |
||||
|
||||
unsafe extern "C" fn CmpName(arg: *mut c_void) -> *const c_char { |
||||
cstrp!("foo") |
||||
} |
||||
|
||||
// Custom filter policy
|
||||
|
||||
static mut fake_filter_result: c_uchar = 1; |
||||
|
||||
unsafe extern "C" fn FilterDestroy(arg: *mut c_void) { } |
||||
|
||||
unsafe extern "C" fn FilterName(arg: *mut c_void) -> *const c_char { |
||||
cstrp!("TestFilter") |
||||
} |
||||
|
||||
unsafe extern "C" fn FilterCreate(arg: *mut c_void, key_array: *const *const c_char, key_length_array: *const size_t, num_keys: c_int, filter_length: *mut size_t) -> *mut c_char { |
||||
*filter_length = 4; |
||||
let result = malloc(4); |
||||
memcpy(result, cstrp!("fake") as *const c_void, 4); |
||||
result as *mut c_char |
||||
} |
||||
|
||||
unsafe extern "C" fn FilterKeyMatch(arg: *mut c_void, key: *const c_char, length: size_t, filter: *const c_char, filter_length: size_t) -> c_uchar { |
||||
CheckCondition!(filter_length == 4); |
||||
CheckCondition!(memcmp(filter as *const c_void, cstrp!("fake") as *const c_void, filter_length) == 0); |
||||
fake_filter_result |
||||
} |
||||
|
||||
// Custom compaction filter
|
||||
|
||||
unsafe extern "C" fn CFilterDestroy(arg: *mut c_void) { } |
||||
|
||||
unsafe extern "C" fn CFilterName(arg: *mut c_void) -> *const c_char { |
||||
cstrp!("foo") |
||||
} |
||||
|
||||
unsafe extern "C" fn CFilterFilter(arg: *mut c_void, level: c_int, key: *const c_char, key_length: size_t, existing_value: *const c_char, value_length: size_t, new_value: *mut *mut c_char, new_value_length: *mut size_t, value_changed: *mut u8) -> c_uchar { |
||||
if key_length == 3 { |
||||
if memcmp(mem::transmute(key), mem::transmute(cstrp!("bar")), key_length) == 0 { |
||||
return 1; |
||||
} else if memcmp(mem::transmute(key), mem::transmute(cstrp!("baz")), key_length) == 0 { |
||||
*value_changed = 1; |
||||
*new_value = cstrp!("newbazvalue") as *mut c_char; |
||||
*new_value_length = 11; |
||||
return 0; |
||||
} |
||||
} |
||||
0 |
||||
} |
||||
|
||||
unsafe extern "C" fn CFilterFactoryDestroy(arg: *mut c_void) { } |
||||
|
||||
unsafe extern "C" fn CFilterFactoryName(arg: *mut c_void) -> *const c_char { |
||||
cstrp!("foo") |
||||
} |
||||
|
||||
unsafe extern "C" fn CFilterCreate(arg: *mut c_void, context: *mut rocksdb_compactionfiltercontext_t) -> *mut rocksdb_compactionfilter_t { |
||||
rocksdb_compactionfilter_create(ptr::null_mut(), Some(CFilterDestroy), Some(CFilterFilter), Some(CFilterName)) |
||||
} |
||||
|
||||
unsafe fn CheckCompaction(dbname: *const c_char, db: *mut rocksdb_t, options: *const rocksdb_options_t, roptions: *mut rocksdb_readoptions_t, woptions: *mut rocksdb_writeoptions_t) -> *mut rocksdb_t { |
||||
let mut err: *mut c_char = ptr::null_mut(); |
||||
let db = rocksdb_open(options, dbname, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_put(db, woptions, cstrp!("foo"), 3, cstrp!("foovalue"), 8, &mut err); |
||||
CheckNoError!(err); |
||||
CheckGet(db, roptions, cstrp!("foo"), cstrp!("foovalue")); |
||||
rocksdb_put(db, woptions, cstrp!("bar"), 3, cstrp!("barvalue"), 8, &mut err); |
||||
CheckNoError!(err); |
||||
CheckGet(db, roptions, cstrp!("bar"), cstrp!("barvalue")); |
||||
rocksdb_put(db, woptions, cstrp!("baz"), 3, cstrp!("bazvalue"), 8, &mut err); |
||||
CheckNoError!(err); |
||||
CheckGet(db, roptions, cstrp!("baz"), cstrp!("bazvalue")); |
||||
|
||||
// Force compaction
|
||||
rocksdb_compact_range(db, ptr::null(), 0, ptr::null(), 0); |
||||
// should have filtered bar, but not foo
|
||||
CheckGet(db, roptions, cstrp!("foo"), cstrp!("foovalue")); |
||||
CheckGet(db, roptions, cstrp!("bar"), ptr::null()); |
||||
CheckGet(db, roptions, cstrp!("baz"), cstrp!("newbazvalue")); |
||||
db |
||||
} |
||||
|
||||
// Custom merge operator
|
||||
|
||||
unsafe extern "C" fn MergeOperatorDestroy(arg: *mut c_void) { } |
||||
|
||||
unsafe extern "C" fn MergeOperatorName(arg: *mut c_void) -> *const c_char { |
||||
cstrp!("foo") |
||||
} |
||||
|
||||
unsafe extern "C" fn MergeOperatorFullMerge(arg: *mut c_void, key: *const c_char, key_length: size_t, existing_value: *const c_char, existing_value_length: size_t, operands_list: *const *const c_char, operands_list_length: *const size_t, num_operands: c_int, success: *mut u8, new_value_length: *mut size_t) -> *mut c_char { |
||||
*new_value_length = 4; |
||||
*success = 1; |
||||
let result: *mut c_char = malloc(4) as *mut _; |
||||
memcpy(result as *mut _, cstrp!("fake") as *mut _, 4); |
||||
result |
||||
} |
||||
|
||||
unsafe extern "C" fn MergeOperatorPartialMerge(arg: *mut c_void, key: *const c_char, key_length: size_t, operands_list: *const *const c_char, operands_list_length: *const size_t, num_operands: c_int, success: *mut u8, new_value_length: *mut size_t) -> *mut c_char { |
||||
*new_value_length = 4; |
||||
*success = 1; |
||||
let result: *mut c_char = malloc(4) as *mut _; |
||||
memcpy(result as *mut _, cstrp!("fake") as *const _, 4); |
||||
result |
||||
} |
||||
|
||||
#[test] |
||||
fn ffi() { |
||||
unsafe { |
||||
let mut db: *mut rocksdb_t; |
||||
let mut cmp: *mut rocksdb_comparator_t; |
||||
let mut cache: *mut rocksdb_cache_t; |
||||
let mut env: *mut rocksdb_env_t; |
||||
let mut options: *mut rocksdb_options_t; |
||||
let mut table_options: *mut rocksdb_block_based_table_options_t; |
||||
let mut roptions: *mut rocksdb_readoptions_t; |
||||
let mut woptions: *mut rocksdb_writeoptions_t; |
||||
let mut err: *mut c_char = ptr::null_mut(); |
||||
let run: c_int = -1; |
||||
|
||||
let dbname = { |
||||
let mut dir = GetTempDir(); |
||||
dir.push(format!("rocksdb_c_test-{}", geteuid())); |
||||
let path = dir.to_str().unwrap(); |
||||
CString::new(path).unwrap() |
||||
}; |
||||
let dbbackupname = { |
||||
let mut dir = GetTempDir(); |
||||
dir.push(format!("rocksdb_c_test-{}-backup", geteuid())); |
||||
let path = dir.to_str().unwrap(); |
||||
CString::new(path).unwrap() |
||||
}; |
||||
|
||||
let dbname = dbname.as_ptr(); |
||||
let dbbackupname = dbbackupname.as_ptr(); |
||||
|
||||
StartPhase("create_objects"); |
||||
cmp = rocksdb_comparator_create(ptr::null_mut(), Some(CmpDestroy), Some(CmpCompare), Some(CmpName)); |
||||
env = rocksdb_create_default_env(); |
||||
cache = rocksdb_cache_create_lru(100000); |
||||
|
||||
options = rocksdb_options_create(); |
||||
rocksdb_options_set_comparator(options, cmp); |
||||
rocksdb_options_set_error_if_exists(options, 1); |
||||
rocksdb_options_set_env(options, env); |
||||
rocksdb_options_set_info_log(options, ptr::null_mut()); |
||||
rocksdb_options_set_write_buffer_size(options, 100000); |
||||
rocksdb_options_set_paranoid_checks(options, 1); |
||||
rocksdb_options_set_max_open_files(options, 10); |
||||
table_options = rocksdb_block_based_options_create(); |
||||
rocksdb_block_based_options_set_block_cache(table_options, cache); |
||||
rocksdb_options_set_block_based_table_factory(options, table_options); |
||||
|
||||
let no_compression = rocksdb_no_compression; |
||||
rocksdb_options_set_compression(options, no_compression); |
||||
rocksdb_options_set_compression_options(options, -14, -1, 0, 0); |
||||
let compression_levels = vec![ |
||||
no_compression, |
||||
no_compression, |
||||
no_compression, |
||||
no_compression, |
||||
]; |
||||
rocksdb_options_set_compression_per_level(options, |
||||
mem::transmute(compression_levels.as_ptr()), |
||||
compression_levels.len() as size_t); |
||||
|
||||
roptions = rocksdb_readoptions_create(); |
||||
rocksdb_readoptions_set_verify_checksums(roptions, 1); |
||||
rocksdb_readoptions_set_fill_cache(roptions, 0); |
||||
|
||||
woptions = rocksdb_writeoptions_create(); |
||||
rocksdb_writeoptions_set_sync(woptions, 1); |
||||
|
||||
StartPhase("destroy"); |
||||
rocksdb_destroy_db(options, dbname, &mut err); |
||||
Free(&mut err); |
||||
|
||||
StartPhase("open_error"); |
||||
rocksdb_open(options, dbname, &mut err); |
||||
CheckCondition!(!err.is_null()); |
||||
Free(&mut err); |
||||
|
||||
StartPhase("open"); |
||||
rocksdb_options_set_create_if_missing(options, 1); |
||||
db = rocksdb_open(options, dbname, &mut err); |
||||
CheckNoError!(err); |
||||
CheckGet(db, roptions, cstrp!("foo") as *const _, ptr::null()); |
||||
|
||||
StartPhase("put"); |
||||
rocksdb_put(db, woptions, cstrp!("foo"), 3, cstrp!("hello"), 5, &mut err); |
||||
CheckNoError!(err); |
||||
CheckGet(db, roptions, cstrp!("foo"), cstrp!("hello")); |
||||
|
||||
StartPhase("backup_and_restore"); |
||||
{ |
||||
rocksdb_destroy_db(options, dbbackupname, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
let be = rocksdb_backup_engine_open(options, dbbackupname, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
rocksdb_backup_engine_create_new_backup(be, db, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
// need a change to trigger a new backup
|
||||
rocksdb_delete(db, woptions, cstrp!("does-not-exist"), 14, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
rocksdb_backup_engine_create_new_backup(be, db, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
let bei: *const rocksdb_backup_engine_info_t = rocksdb_backup_engine_get_backup_info(be); |
||||
CheckCondition!(rocksdb_backup_engine_info_count(bei) > 1); |
||||
rocksdb_backup_engine_info_destroy(bei); |
||||
|
||||
rocksdb_backup_engine_purge_old_backups(be, 1, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
let bei: *const rocksdb_backup_engine_info_t = rocksdb_backup_engine_get_backup_info(be); |
||||
CheckCondition!(rocksdb_backup_engine_info_count(bei) == 1); |
||||
rocksdb_backup_engine_info_destroy(bei); |
||||
|
||||
rocksdb_delete(db, woptions, cstrp!("foo"), 3, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
rocksdb_close(db); |
||||
|
||||
rocksdb_destroy_db(options, dbname, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
let restore_options = rocksdb_restore_options_create(); |
||||
rocksdb_restore_options_set_keep_log_files(restore_options, 0); |
||||
rocksdb_backup_engine_restore_db_from_latest_backup(be, dbname, dbname, restore_options, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_restore_options_destroy(restore_options); |
||||
|
||||
rocksdb_options_set_error_if_exists(options, 0); |
||||
db = rocksdb_open(options, dbname, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_options_set_error_if_exists(options, 1); |
||||
|
||||
CheckGet(db, roptions, cstrp!("foo"), cstrp!("hello")); |
||||
|
||||
rocksdb_backup_engine_close(be); |
||||
} |
||||
|
||||
StartPhase("compactall"); |
||||
rocksdb_compact_range(db, ptr::null(), 0, ptr::null(), 0); |
||||
CheckGet(db, roptions, cstrp!("foo"), cstrp!("hello")); |
||||
|
||||
StartPhase("compactrange"); |
||||
rocksdb_compact_range(db, cstrp!("a"), 1, cstrp!("z"), 1); |
||||
CheckGet(db, roptions, cstrp!("foo"), cstrp!("hello")); |
||||
|
||||
StartPhase("writebatch"); |
||||
{ |
||||
let mut wb = rocksdb_writebatch_create(); |
||||
rocksdb_writebatch_put(wb, cstrp!("foo"), 3, cstrp!("a"), 1); |
||||
rocksdb_writebatch_clear(wb); |
||||
rocksdb_writebatch_put(wb, cstrp!("bar"), 3, cstrp!("b"), 1); |
||||
rocksdb_writebatch_put(wb, cstrp!("box"), 3, cstrp!("c"), 1); |
||||
rocksdb_writebatch_delete(wb, cstrp!("bar"), 3); |
||||
rocksdb_write(db, woptions, wb, &mut err); |
||||
CheckNoError!(err); |
||||
CheckGet(db, roptions, cstrp!("foo"), cstrp!("hello")); |
||||
CheckGet(db, roptions, cstrp!("bar"), ptr::null()); |
||||
CheckGet(db, roptions, cstrp!("box"), cstrp!("c")); |
||||
let mut pos: c_int = 0; |
||||
rocksdb_writebatch_iterate(wb, mem::transmute(&mut pos), Some(CheckPut), Some(CheckDel)); |
||||
CheckCondition!(pos == 3); |
||||
rocksdb_writebatch_destroy(wb); |
||||
} |
||||
|
||||
StartPhase("writebatch_vectors"); |
||||
{ |
||||
let wb = rocksdb_writebatch_create(); |
||||
let k_list: [*const c_char; 2] = [cstrp!("z"), cstrp!("ap")]; |
||||
let k_sizes: [size_t; 2] = [1, 2]; |
||||
let v_list: [*const c_char; 3] = [cstrp!("x"), cstrp!("y"), cstrp!("z")]; |
||||
let v_sizes: [size_t; 3] = [1, 1, 1]; |
||||
rocksdb_writebatch_putv(wb, k_list.len() as c_int, k_list.as_ptr(), k_sizes.as_ptr(), v_list.len() as c_int, v_list.as_ptr(), v_sizes.as_ptr()); |
||||
rocksdb_write(db, woptions, wb, &mut err); |
||||
CheckNoError!(err); |
||||
CheckGet(db, roptions, cstrp!("zap"), cstrp!("xyz")); |
||||
rocksdb_writebatch_delete(wb, cstrp!("zap"), 3); |
||||
rocksdb_write(db, woptions, wb, &mut err); |
||||
CheckNoError!(err); |
||||
CheckGet(db, roptions, cstrp!("zap"), ptr::null()); |
||||
rocksdb_writebatch_destroy(wb); |
||||
} |
||||
|
||||
StartPhase("writebatch_rep"); |
||||
{ |
||||
let wb1: *mut rocksdb_writebatch_t = rocksdb_writebatch_create(); |
||||
rocksdb_writebatch_put(wb1, cstrp!("baz"), 3, cstrp!("d"), 1); |
||||
rocksdb_writebatch_put(wb1, cstrp!("quux"), 4, cstrp!("e"), 1); |
||||
rocksdb_writebatch_delete(wb1, cstrp!("quux"), 4); |
||||
let mut repsize1: size_t = 0; |
||||
let mut rep = rocksdb_writebatch_data(wb1, &mut repsize1) as *const c_void; |
||||
let mut wb2 = rocksdb_writebatch_create_from(rep as *const c_char, repsize1); |
||||
CheckCondition!(rocksdb_writebatch_count(wb1) == rocksdb_writebatch_count(wb2)); |
||||
let mut repsize2: size_t = 0; |
||||
CheckCondition!(memcmp(rep, rocksdb_writebatch_data(wb2, &mut repsize2) as *const c_void, repsize1) == 0); |
||||
rocksdb_writebatch_destroy(wb1); |
||||
rocksdb_writebatch_destroy(wb2); |
||||
} |
||||
|
||||
StartPhase("iter"); |
||||
{ |
||||
let mut iter = rocksdb_create_iterator(db, roptions); |
||||
CheckCondition!(rocksdb_iter_valid(iter) == 0); |
||||
rocksdb_iter_seek_to_first(iter); |
||||
CheckCondition!(rocksdb_iter_valid(iter) != 0); |
||||
CheckIter(iter, cstrp!("box"), cstrp!("c")); |
||||
rocksdb_iter_next(iter); |
||||
CheckIter(iter, cstrp!("foo"), cstrp!("hello")); |
||||
rocksdb_iter_prev(iter); |
||||
CheckIter(iter, cstrp!("box"), cstrp!("c")); |
||||
rocksdb_iter_prev(iter); |
||||
CheckCondition!(rocksdb_iter_valid(iter) == 0); |
||||
rocksdb_iter_seek_to_last(iter); |
||||
CheckIter(iter, cstrp!("foo"), cstrp!("hello")); |
||||
rocksdb_iter_seek(iter, cstrp!("b"), 1); |
||||
CheckIter(iter, cstrp!("box"), cstrp!("c")); |
||||
rocksdb_iter_get_error(iter, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_iter_destroy(iter); |
||||
} |
||||
|
||||
StartPhase("multiget"); |
||||
{ |
||||
let keys: [*const c_char; 3] = [cstrp!("box"), cstrp!("foo"), cstrp!("notfound")]; |
||||
let keys_sizes: [size_t; 3] = [3, 3, 8]; |
||||
let mut vals: [*mut c_char; 3] = [ptr::null_mut(), ptr::null_mut(), ptr::null_mut()]; |
||||
let mut vals_sizes: [size_t; 3] = [0, 0, 0]; |
||||
let mut errs: [*mut c_char; 3] = [ptr::null_mut(), ptr::null_mut(), ptr::null_mut()]; |
||||
rocksdb_multi_get(db, roptions, 3, keys.as_ptr(), keys_sizes.as_ptr(), vals.as_mut_ptr(), vals_sizes.as_mut_ptr(), errs.as_mut_ptr()); |
||||
|
||||
for i in 0..3 { |
||||
CheckEqual(ptr::null(), errs[i], 0); |
||||
match i { |
||||
0 => CheckEqual(cstrp!("c"), vals[i], vals_sizes[i]), |
||||
1 => CheckEqual(cstrp!("hello"), vals[i], vals_sizes[i]), |
||||
2 => CheckEqual(ptr::null(), vals[i], vals_sizes[i]), |
||||
_ => { }, |
||||
} |
||||
Free(&mut vals[i]); |
||||
} |
||||
} |
||||
|
||||
StartPhase("approximate_sizes"); |
||||
{ |
||||
let mut sizes: [uint64_t; 2] = [0, 0]; |
||||
let start: [*const c_char; 2] = [cstrp!("a"), cstrp!("k00000000000000010000")]; |
||||
let start_len: [size_t; 2] = [1, 21]; |
||||
let limit: [*const c_char; 2] = [cstrp!("k00000000000000010000"), cstrp!("z")]; |
||||
let limit_len: [size_t; 2] = [21, 1]; |
||||
rocksdb_writeoptions_set_sync(woptions, 0); |
||||
for i in 0 .. 20000 { |
||||
let keybuf = CString::new(format!("k{:020}", i)).unwrap(); |
||||
let key = keybuf.to_bytes_with_nul(); |
||||
let valbuf = CString::new(format!("v{:020}", i)).unwrap(); |
||||
let val = valbuf.to_bytes_with_nul(); |
||||
rocksdb_put(db, woptions, key.as_ptr() as *const c_char, key.len() as size_t, val.as_ptr() as *const c_char, val.len() as size_t, &mut err); |
||||
CheckNoError!(err); |
||||
} |
||||
rocksdb_approximate_sizes(db, 2, start.as_ptr(), start_len.as_ptr(), limit.as_ptr(), limit_len.as_ptr(), sizes.as_mut_ptr()); |
||||
CheckCondition!(sizes[0] > 0); |
||||
CheckCondition!(sizes[1] > 0); |
||||
} |
||||
|
||||
StartPhase("property"); |
||||
{ |
||||
let mut prop: *mut c_char; |
||||
prop = rocksdb_property_value(db, cstrp!("nosuchprop")); |
||||
CheckCondition!(prop.is_null()); |
||||
prop = rocksdb_property_value(db, cstrp!("rocksdb.stats")); |
||||
CheckCondition!(!prop.is_null()); |
||||
Free(&mut prop); |
||||
} |
||||
|
||||
StartPhase("snapshot"); |
||||
{ |
||||
let snap: *const rocksdb_snapshot_t = rocksdb_create_snapshot(db); |
||||
rocksdb_delete(db, woptions, cstrp!("foo"), 3, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_readoptions_set_snapshot(roptions, snap); |
||||
CheckGet(db, roptions, cstrp!("foo"), cstrp!("hello")); |
||||
rocksdb_readoptions_set_snapshot(roptions, ptr::null()); |
||||
CheckGet(db, roptions, cstrp!("foo"), ptr::null()); |
||||
rocksdb_release_snapshot(db, snap); |
||||
} |
||||
|
||||
StartPhase("repair"); |
||||
{ |
||||
// If we do not compact here, then the lazy deletion of files (https://reviews.facebook.net/D6123) would leave around deleted files and the repair process will find those files and put them back into the database.
|
||||
rocksdb_compact_range(db, ptr::null(), 0, ptr::null(), 0); |
||||
rocksdb_close(db); |
||||
rocksdb_options_set_create_if_missing(options, 0); |
||||
rocksdb_options_set_error_if_exists(options, 0); |
||||
// rocksdb_options_set_wal_recovery_mode(options, 2);
|
||||
rocksdb_repair_db(options, dbname, &mut err); |
||||
CheckNoError!(err); |
||||
db = rocksdb_open(options, dbname, &mut err); |
||||
CheckNoError!(err); |
||||
CheckGet(db, roptions, cstrp!("foo"), ptr::null()); |
||||
CheckGet(db, roptions, cstrp!("bar"), ptr::null()); |
||||
CheckGet(db, roptions, cstrp!("box"), cstrp!("c")); |
||||
rocksdb_options_set_create_if_missing(options, 1); |
||||
rocksdb_options_set_error_if_exists(options, 1); |
||||
} |
||||
|
||||
StartPhase("filter"); |
||||
for run in 0 .. 2 { |
||||
// First run uses custom filter, second run uses bloom filter
|
||||
CheckNoError!(err); |
||||
let mut policy: *mut rocksdb_filterpolicy_t = if run == 0 { |
||||
rocksdb_filterpolicy_create(ptr::null_mut(), Some(FilterDestroy), Some(FilterCreate), Some(FilterKeyMatch), None, Some(FilterName)) |
||||
} else { |
||||
rocksdb_filterpolicy_create_bloom(10) |
||||
}; |
||||
|
||||
rocksdb_block_based_options_set_filter_policy(table_options, policy); |
||||
|
||||
// Create new database
|
||||
rocksdb_close(db); |
||||
rocksdb_destroy_db(options, dbname, &mut err); |
||||
rocksdb_options_set_block_based_table_factory(options, table_options); |
||||
db = rocksdb_open(options, dbname, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_put(db, woptions, cstrp!("foo"), 3, cstrp!("foovalue"), 8, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_put(db, woptions, cstrp!("bar"), 3, cstrp!("barvalue"), 8, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_compact_range(db, ptr::null(), 0, ptr::null(), 0); |
||||
|
||||
fake_filter_result = 1; |
||||
CheckGet(db, roptions, cstrp!("foo"), cstrp!("foovalue")); |
||||
CheckGet(db, roptions, cstrp!("bar"), cstrp!("barvalue")); |
||||
if phase == "" { |
||||
// Must not find value when custom filter returns false
|
||||
fake_filter_result = 0; |
||||
CheckGet(db, roptions, cstrp!("foo"), ptr::null()); |
||||
CheckGet(db, roptions, cstrp!("bar"), ptr::null()); |
||||
fake_filter_result = 1; |
||||
|
||||
CheckGet(db, roptions, cstrp!("foo"), cstrp!("foovalue")); |
||||
CheckGet(db, roptions, cstrp!("bar"), cstrp!("barvalue")); |
||||
} |
||||
// Reset the policy
|
||||
rocksdb_block_based_options_set_filter_policy(table_options, ptr::null_mut()); |
||||
rocksdb_options_set_block_based_table_factory(options, table_options); |
||||
} |
||||
|
||||
StartPhase("compaction_filter"); |
||||
{ |
||||
let options_with_filter = rocksdb_options_create(); |
||||
rocksdb_options_set_create_if_missing(options_with_filter, 1); |
||||
let cfilter = rocksdb_compactionfilter_create(ptr::null_mut(), Some(CFilterDestroy), Some(CFilterFilter), Some(CFilterName)); |
||||
// Create new database
|
||||
rocksdb_close(db); |
||||
rocksdb_destroy_db(options_with_filter, dbname, &mut err); |
||||
rocksdb_options_set_compaction_filter(options_with_filter, cfilter); |
||||
db = CheckCompaction(dbname, db, options_with_filter, roptions, woptions); |
||||
|
||||
rocksdb_options_set_compaction_filter(options_with_filter, ptr::null_mut()); |
||||
rocksdb_compactionfilter_destroy(cfilter); |
||||
rocksdb_options_destroy(options_with_filter); |
||||
} |
||||
|
||||
StartPhase("compaction_filter_factory"); |
||||
{ |
||||
let mut options_with_filter_factory = rocksdb_options_create(); |
||||
rocksdb_options_set_create_if_missing(options_with_filter_factory, 1); |
||||
let mut factory = rocksdb_compactionfilterfactory_create(ptr::null_mut(), Some(CFilterFactoryDestroy), Some(CFilterCreate), Some(CFilterFactoryName)); |
||||
// Create new database
|
||||
rocksdb_close(db); |
||||
rocksdb_destroy_db(options_with_filter_factory, dbname, &mut err); |
||||
rocksdb_options_set_compaction_filter_factory(options_with_filter_factory, factory); |
||||
db = CheckCompaction(dbname, db, options_with_filter_factory, roptions, woptions); |
||||
|
||||
rocksdb_options_set_compaction_filter_factory(options_with_filter_factory, ptr::null_mut()); |
||||
rocksdb_options_destroy(options_with_filter_factory); |
||||
} |
||||
|
||||
StartPhase("merge_operator"); |
||||
{ |
||||
let mut merge_operator = rocksdb_mergeoperator_create(ptr::null_mut(), Some(MergeOperatorDestroy), Some(MergeOperatorFullMerge), Some(MergeOperatorPartialMerge), None, Some(MergeOperatorName)); |
||||
// Create new database
|
||||
rocksdb_close(db); |
||||
rocksdb_destroy_db(options, dbname, &mut err); |
||||
rocksdb_options_set_merge_operator(options, merge_operator); |
||||
db = rocksdb_open(options, dbname, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_put(db, woptions, cstrp!("foo"), 3, cstrp!("foovalue"), 8, &mut err); |
||||
CheckNoError!(err); |
||||
CheckGet(db, roptions, cstrp!("foo"), cstrp!("foovalue")); |
||||
rocksdb_merge(db, woptions, cstrp!("foo"), 3, cstrp!("barvalue"), 8, &mut err); |
||||
CheckNoError!(err); |
||||
CheckGet(db, roptions, cstrp!("foo"), cstrp!("fake")); |
||||
|
||||
// Merge of a non-existing value
|
||||
rocksdb_merge(db, woptions, cstrp!("bar"), 3, cstrp!("barvalue"), 8, &mut err); |
||||
CheckNoError!(err); |
||||
CheckGet(db, roptions, cstrp!("bar"), cstrp!("fake")); |
||||
} |
||||
|
||||
StartPhase("columnfamilies"); |
||||
{ |
||||
rocksdb_close(db); |
||||
rocksdb_destroy_db(options, dbname, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
let mut db_options = rocksdb_options_create(); |
||||
rocksdb_options_set_create_if_missing(db_options, 1); |
||||
db = rocksdb_open(db_options, dbname, &mut err); |
||||
CheckNoError!(err); |
||||
let mut cfh = rocksdb_create_column_family(db, db_options, cstrp!("cf1"), & mut err); |
||||
rocksdb_column_family_handle_destroy(cfh); |
||||
CheckNoError!(err); |
||||
rocksdb_close(db); |
||||
|
||||
let mut cflen: size_t = 0; |
||||
let column_fams_raw = rocksdb_list_column_families(db_options, dbname, &mut cflen, &mut err); |
||||
let column_fams = slice::from_raw_parts(column_fams_raw, cflen as usize); |
||||
CheckEqual(cstrp!("default"), column_fams[0], 7); |
||||
CheckEqual(cstrp!("cf1"), column_fams[1], 3); |
||||
CheckCondition!(cflen == 2); |
||||
rocksdb_list_column_families_destroy(column_fams_raw, cflen); |
||||
|
||||
let mut cf_options = rocksdb_options_create(); |
||||
|
||||
let cf_names: [*const c_char; 2] = [cstrp!("default"), cstrp!("cf1")]; |
||||
let cf_opts: [*const rocksdb_options_t; 2] = [cf_options, cf_options]; |
||||
let mut handles: [*mut rocksdb_column_family_handle_t; 2] = [ptr::null_mut(), ptr::null_mut()]; |
||||
db = rocksdb_open_column_families(db_options, dbname, 2, cf_names.as_ptr(), cf_opts.as_ptr(), handles.as_mut_ptr(), &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
rocksdb_put_cf(db, woptions, handles[1], cstrp!("foo"), 3, cstrp!("hello"), 5, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
CheckGetCF(db, roptions, handles[1], cstrp!("foo"), cstrp!("hello")); |
||||
|
||||
rocksdb_delete_cf(db, woptions, handles[1], cstrp!("foo"), 3, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
CheckGetCF(db, roptions, handles[1], cstrp!("foo"), ptr::null()); |
||||
|
||||
let mut wb = rocksdb_writebatch_create(); |
||||
rocksdb_writebatch_put_cf(wb, handles[1], cstrp!("baz"), 3, cstrp!("a"), 1); |
||||
rocksdb_writebatch_clear(wb); |
||||
rocksdb_writebatch_put_cf(wb, handles[1], cstrp!("bar"), 3, cstrp!("b"), 1); |
||||
rocksdb_writebatch_put_cf(wb, handles[1], cstrp!("box"), 3, cstrp!("c"), 1); |
||||
rocksdb_writebatch_delete_cf(wb, handles[1], cstrp!("bar"), 3); |
||||
rocksdb_write(db, woptions, wb, &mut err); |
||||
CheckNoError!(err); |
||||
CheckGetCF(db, roptions, handles[1], cstrp!("baz"), ptr::null()); |
||||
CheckGetCF(db, roptions, handles[1], cstrp!("bar"), ptr::null()); |
||||
CheckGetCF(db, roptions, handles[1], cstrp!("box"), cstrp!("c")); |
||||
rocksdb_writebatch_destroy(wb); |
||||
|
||||
let keys: [*const c_char; 3] = [cstrp!("box"), cstrp!("box"), cstrp!("barfooxx")]; |
||||
let get_handles: [*const rocksdb_column_family_handle_t; 3] = [handles[0], handles[1], handles[1]]; |
||||
let keys_sizes: [size_t; 3] = [3, 3, 8]; |
||||
let mut vals: [*mut c_char; 3] = [ptr::null_mut(), ptr::null_mut(), ptr::null_mut()]; |
||||
let mut vals_sizes: [size_t; 3] = [0, 0, 0]; |
||||
let mut errs: [*mut c_char; 3] = [ptr::null_mut(), ptr::null_mut(), ptr::null_mut()]; |
||||
rocksdb_multi_get_cf(db, roptions, get_handles.as_ptr(), 3, keys.as_ptr(), keys_sizes.as_ptr(), vals.as_mut_ptr(), vals_sizes.as_mut_ptr(), errs.as_mut_ptr()); |
||||
|
||||
for i in 0 .. 3 { |
||||
CheckEqual(ptr::null(), errs[i], 0); |
||||
match i { |
||||
0 => CheckEqual(ptr::null(), vals[i], vals_sizes[i]), // wrong cf
|
||||
1 => CheckEqual(cstrp!("c"), vals[i], vals_sizes[i]), // bingo
|
||||
2 => CheckEqual(ptr::null(), vals[i], vals_sizes[i]), // normal not found
|
||||
_ => { }, |
||||
} |
||||
Free(&mut vals[i]); |
||||
} |
||||
|
||||
let mut iter = rocksdb_create_iterator_cf(db, roptions, handles[1]); |
||||
CheckCondition!(rocksdb_iter_valid(iter) == 0); |
||||
rocksdb_iter_seek_to_first(iter); |
||||
CheckCondition!(rocksdb_iter_valid(iter) != 0); |
||||
|
||||
let mut i: u32 = 0; |
||||
while rocksdb_iter_valid(iter) != 0 { |
||||
rocksdb_iter_next(iter); |
||||
i += 1; |
||||
} |
||||
CheckCondition!(i == 1); |
||||
rocksdb_iter_get_error(iter, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_iter_destroy(iter); |
||||
|
||||
let mut iters_cf_handles: [*mut rocksdb_column_family_handle_t; 2] = [handles[0], handles[1]]; |
||||
let mut iters_handles: [*mut rocksdb_iterator_t; 2] = [ptr::null_mut(), ptr::null_mut()]; |
||||
rocksdb_create_iterators(db, roptions, iters_cf_handles.as_mut_ptr(), iters_handles.as_mut_ptr(), 2, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
iter = iters_handles[0]; |
||||
CheckCondition!(rocksdb_iter_valid(iter) == 0); |
||||
rocksdb_iter_seek_to_first(iter); |
||||
CheckCondition!(rocksdb_iter_valid(iter) == 0); |
||||
rocksdb_iter_destroy(iter); |
||||
|
||||
iter = iters_handles[1]; |
||||
CheckCondition!(rocksdb_iter_valid(iter) == 0); |
||||
rocksdb_iter_seek_to_first(iter); |
||||
CheckCondition!(rocksdb_iter_valid(iter) != 0); |
||||
|
||||
let mut i: u32 = 0; |
||||
while rocksdb_iter_valid(iter) != 0 { |
||||
rocksdb_iter_next(iter); |
||||
i += 1; |
||||
} |
||||
CheckCondition!(i == 1); |
||||
rocksdb_iter_get_error(iter, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_iter_destroy(iter); |
||||
|
||||
rocksdb_drop_column_family(db, handles[1], &mut err); |
||||
CheckNoError!(err); |
||||
for i in 0..2 { |
||||
rocksdb_column_family_handle_destroy(handles[i]); |
||||
} |
||||
rocksdb_close(db); |
||||
rocksdb_destroy_db(options, dbname, &mut err); |
||||
rocksdb_options_destroy(db_options); |
||||
rocksdb_options_destroy(cf_options); |
||||
} |
||||
|
||||
StartPhase("prefix"); |
||||
{ |
||||
// Create new database
|
||||
rocksdb_options_set_allow_mmap_reads(options, 1); |
||||
rocksdb_options_set_prefix_extractor(options, rocksdb_slicetransform_create_fixed_prefix(3)); |
||||
rocksdb_options_set_hash_skip_list_rep(options, 5000, 4, 4); |
||||
rocksdb_options_set_plain_table_factory(options, 4, 10, 0.75, 16); |
||||
|
||||
db = rocksdb_open(options, dbname, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
rocksdb_put(db, woptions, cstrp!("foo1"), 4, cstrp!("foo"), 3, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_put(db, woptions, cstrp!("foo2"), 4, cstrp!("foo"), 3, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_put(db, woptions, cstrp!("foo3"), 4, cstrp!("foo"), 3, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_put(db, woptions, cstrp!("bar1"), 4, cstrp!("bar"), 3, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_put(db, woptions, cstrp!("bar2"), 4, cstrp!("bar"), 3, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_put(db, woptions, cstrp!("bar3"), 4, cstrp!("bar"), 3, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
let mut iter = rocksdb_create_iterator(db, roptions); |
||||
CheckCondition!(rocksdb_iter_valid(iter) == 0); |
||||
|
||||
rocksdb_iter_seek(iter, cstrp!("bar"), 3); |
||||
rocksdb_iter_get_error(iter, &mut err); |
||||
CheckNoError!(err); |
||||
CheckCondition!(rocksdb_iter_valid(iter) != 0); |
||||
|
||||
CheckIter(iter, cstrp!("bar1"), cstrp!("bar")); |
||||
rocksdb_iter_next(iter); |
||||
CheckIter(iter, cstrp!("bar2"), cstrp!("bar")); |
||||
rocksdb_iter_next(iter); |
||||
CheckIter(iter, cstrp!("bar3"), cstrp!("bar")); |
||||
rocksdb_iter_get_error(iter, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_iter_destroy(iter); |
||||
|
||||
rocksdb_close(db); |
||||
rocksdb_destroy_db(options, dbname, &mut err); |
||||
} |
||||
|
||||
StartPhase("cuckoo_options"); |
||||
{ |
||||
let mut cuckoo_options = rocksdb_cuckoo_options_create(); |
||||
rocksdb_cuckoo_options_set_hash_ratio(cuckoo_options, 0.5); |
||||
rocksdb_cuckoo_options_set_max_search_depth(cuckoo_options, 200); |
||||
rocksdb_cuckoo_options_set_cuckoo_block_size(cuckoo_options, 10); |
||||
rocksdb_cuckoo_options_set_identity_as_first_hash(cuckoo_options, 1); |
||||
rocksdb_cuckoo_options_set_use_module_hash(cuckoo_options, 0); |
||||
rocksdb_options_set_cuckoo_table_factory(options, cuckoo_options); |
||||
|
||||
db = rocksdb_open(options, dbname, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
rocksdb_cuckoo_options_destroy(cuckoo_options); |
||||
} |
||||
|
||||
StartPhase("iterate_upper_bound"); |
||||
{ |
||||
// Create new empty database
|
||||
rocksdb_close(db); |
||||
rocksdb_destroy_db(options, dbname, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
rocksdb_options_set_prefix_extractor(options, ptr::null_mut()); |
||||
db = rocksdb_open(options, dbname, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
rocksdb_put(db, woptions, cstrp!("a"), 1, cstrp!("0"), 1, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_put(db, woptions, cstrp!("foo"), 3, cstrp!("bar"), 3, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_put(db, woptions, cstrp!("foo1"), 4, cstrp!("bar1"), 4, &mut err); |
||||
CheckNoError!(err); |
||||
rocksdb_put(db, woptions, cstrp!("g1"), 2, cstrp!("0"), 1, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
// testing basic case with no iterate_upper_bound and no prefix_extractor
|
||||
{ |
||||
rocksdb_readoptions_set_iterate_upper_bound(roptions, ptr::null(), 0); |
||||
let mut iter = rocksdb_create_iterator(db, roptions); |
||||
|
||||
rocksdb_iter_seek(iter, cstrp!("foo"), 3); |
||||
CheckCondition!(rocksdb_iter_valid(iter) != 0); |
||||
CheckIter(iter, cstrp!("foo"), cstrp!("bar")); |
||||
|
||||
rocksdb_iter_next(iter); |
||||
CheckCondition!(rocksdb_iter_valid(iter) != 0); |
||||
CheckIter(iter, cstrp!("foo1"), cstrp!("bar1")); |
||||
|
||||
rocksdb_iter_next(iter); |
||||
CheckCondition!(rocksdb_iter_valid(iter) != 0); |
||||
CheckIter(iter, cstrp!("g1"), cstrp!("0")); |
||||
|
||||
rocksdb_iter_destroy(iter); |
||||
} |
||||
|
||||
// testing iterate_upper_bound and forward iterator
|
||||
// to make sure it stops at bound
|
||||
{ |
||||
// iterate_upper_bound points beyond the last expected entry
|
||||
rocksdb_readoptions_set_iterate_upper_bound(roptions, cstrp!("foo2"), 4); |
||||
|
||||
let mut iter = rocksdb_create_iterator(db, roptions); |
||||
|
||||
rocksdb_iter_seek(iter, cstrp!("foo"), 3); |
||||
CheckCondition!(rocksdb_iter_valid(iter) != 0); |
||||
CheckIter(iter, cstrp!("foo"), cstrp!("bar")); |
||||
|
||||
rocksdb_iter_next(iter); |
||||
CheckCondition!(rocksdb_iter_valid(iter) != 0); |
||||
CheckIter(iter, cstrp!("foo1"), cstrp!("bar1")); |
||||
|
||||
rocksdb_iter_next(iter); |
||||
// should stop here...
|
||||
CheckCondition!(rocksdb_iter_valid(iter) == 0); |
||||
|
||||
rocksdb_iter_destroy(iter); |
||||
} |
||||
} |
||||
|
||||
// Simple sanity check that setting memtable rep works.
|
||||
StartPhase("memtable_reps"); |
||||
{ |
||||
// Create database with vector memtable.
|
||||
rocksdb_close(db); |
||||
rocksdb_destroy_db(options, dbname, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
rocksdb_options_set_memtable_vector_rep(options); |
||||
db = rocksdb_open(options, dbname, &mut err); |
||||
CheckNoError!(err); |
||||
|
||||
// // Create database with hash skiplist memtable.
|
||||
// rocksdb_close(db);
|
||||
// rocksdb_destroy_db(options, dbname, &mut err);
|
||||
// CheckNoError!(err);
|
||||
//
|
||||
// rocksdb_options_set_hash_skip_list_rep(options, 5000, 4, 4);
|
||||
// db = rocksdb_open(options, dbname, &mut err);
|
||||
// CheckNoError!(err);
|
||||
} |
||||
|
||||
StartPhase("cleanup"); |
||||
rocksdb_close(db); |
||||
rocksdb_options_destroy(options); |
||||
rocksdb_block_based_options_destroy(table_options); |
||||
rocksdb_readoptions_destroy(roptions); |
||||
rocksdb_writeoptions_destroy(woptions); |
||||
rocksdb_cache_destroy(cache); |
||||
rocksdb_comparator_destroy(cmp); |
||||
rocksdb_env_destroy(env); |
||||
|
||||
err_println!("PASS"); |
||||
} |
||||
} |
Loading…
Reference in new issue