|
|
@ -16,6 +16,7 @@ mod util; |
|
|
|
|
|
|
|
|
|
|
|
use pretty_assertions::assert_eq; |
|
|
|
use pretty_assertions::assert_eq; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use rocksdb::merge_operator::MergeFn; |
|
|
|
use rocksdb::{DBCompactionStyle, MergeOperands, Options, DB}; |
|
|
|
use rocksdb::{DBCompactionStyle, MergeOperands, Options, DB}; |
|
|
|
use util::DBPath; |
|
|
|
use util::DBPath; |
|
|
|
|
|
|
|
|
|
|
@ -46,7 +47,7 @@ fn merge_test() { |
|
|
|
let db_path = DBPath::new("_rust_rocksdb_merge_test"); |
|
|
|
let db_path = DBPath::new("_rust_rocksdb_merge_test"); |
|
|
|
let mut opts = Options::default(); |
|
|
|
let mut opts = Options::default(); |
|
|
|
opts.create_if_missing(true); |
|
|
|
opts.create_if_missing(true); |
|
|
|
opts.set_merge_operator("test operator", test_provided_merge, None); |
|
|
|
opts.set_merge_operator_associative("test operator", test_provided_merge); |
|
|
|
|
|
|
|
|
|
|
|
let db = DB::open(&opts, &db_path).unwrap(); |
|
|
|
let db = DB::open(&opts, &db_path).unwrap(); |
|
|
|
let p = db.put(b"k1", b"a"); |
|
|
|
let p = db.put(b"k1", b"a"); |
|
|
@ -159,7 +160,7 @@ fn counting_merge_test() { |
|
|
|
opts.set_merge_operator( |
|
|
|
opts.set_merge_operator( |
|
|
|
"sort operator", |
|
|
|
"sort operator", |
|
|
|
test_counting_full_merge, |
|
|
|
test_counting_full_merge, |
|
|
|
Some(test_counting_partial_merge), |
|
|
|
test_counting_partial_merge, |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
let db = Arc::new(DB::open(&opts, &db_path).unwrap()); |
|
|
|
let db = Arc::new(DB::open(&opts, &db_path).unwrap()); |
|
|
@ -278,7 +279,7 @@ fn failed_merge_test() { |
|
|
|
let db_path = DBPath::new("_rust_rocksdb_failed_merge_test"); |
|
|
|
let db_path = DBPath::new("_rust_rocksdb_failed_merge_test"); |
|
|
|
let mut opts = Options::default(); |
|
|
|
let mut opts = Options::default(); |
|
|
|
opts.create_if_missing(true); |
|
|
|
opts.create_if_missing(true); |
|
|
|
opts.set_merge_operator("test operator", test_failing_merge, None); |
|
|
|
opts.set_merge_operator_associative("test operator", test_failing_merge); |
|
|
|
|
|
|
|
|
|
|
|
let db = DB::open(&opts, &db_path).expect("open with a merge operator"); |
|
|
|
let db = DB::open(&opts, &db_path).expect("open with a merge operator"); |
|
|
|
db.put(b"key", b"value").expect("put_ok"); |
|
|
|
db.put(b"key", b"value").expect("put_ok"); |
|
|
@ -290,3 +291,72 @@ fn failed_merge_test() { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn make_merge_max_with_limit(limit: u64) -> impl MergeFn + Clone { |
|
|
|
|
|
|
|
move |_key: &[u8], first: Option<&[u8]>, rest: &mut MergeOperands| { |
|
|
|
|
|
|
|
let max = first |
|
|
|
|
|
|
|
.into_iter() |
|
|
|
|
|
|
|
.chain(rest) |
|
|
|
|
|
|
|
.map(|slice| { |
|
|
|
|
|
|
|
let mut bytes: [u8; 8] = Default::default(); |
|
|
|
|
|
|
|
bytes.clone_from_slice(slice); |
|
|
|
|
|
|
|
u64::from_ne_bytes(bytes) |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
.fold(0, u64::max); |
|
|
|
|
|
|
|
let new_value = max.min(limit); |
|
|
|
|
|
|
|
Some(Vec::from(new_value.to_ne_bytes().as_ref())) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
|
|
|
|
fn test_merge_state() { |
|
|
|
|
|
|
|
use {Options, DB}; |
|
|
|
|
|
|
|
let path = "_rust_rocksdb_mergetest_state"; |
|
|
|
|
|
|
|
let mut opts = Options::default(); |
|
|
|
|
|
|
|
opts.create_if_missing(true); |
|
|
|
|
|
|
|
opts.set_merge_operator_associative("max-limit-12", make_merge_max_with_limit(12)); |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
let db = DB::open(&opts, path).unwrap(); |
|
|
|
|
|
|
|
let p = db.put(b"k1", 1u64.to_ne_bytes()); |
|
|
|
|
|
|
|
assert!(p.is_ok()); |
|
|
|
|
|
|
|
let _ = db.merge(b"k1", 7u64.to_ne_bytes()); |
|
|
|
|
|
|
|
let m = db.merge(b"k1", 64u64.to_ne_bytes()); |
|
|
|
|
|
|
|
assert!(m.is_ok()); |
|
|
|
|
|
|
|
match db.get(b"k1") { |
|
|
|
|
|
|
|
Ok(Some(value)) => { |
|
|
|
|
|
|
|
let mut bytes: [u8; 8] = Default::default(); |
|
|
|
|
|
|
|
bytes.copy_from_slice(&value); |
|
|
|
|
|
|
|
assert_eq!(u64::from_ne_bytes(bytes), 12); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Err(_) => println!("error reading value"), |
|
|
|
|
|
|
|
_ => panic!("value not present"), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert!(db.delete(b"k1").is_ok()); |
|
|
|
|
|
|
|
assert!(db.get(b"k1").unwrap().is_none()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
assert!(DB::destroy(&opts, path).is_ok()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
opts.set_merge_operator_associative("max-limit-128", make_merge_max_with_limit(128)); |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
let db = DB::open(&opts, path).unwrap(); |
|
|
|
|
|
|
|
let p = db.put(b"k1", 1u64.to_ne_bytes()); |
|
|
|
|
|
|
|
assert!(p.is_ok()); |
|
|
|
|
|
|
|
let _ = db.merge(b"k1", 7u64.to_ne_bytes()); |
|
|
|
|
|
|
|
let m = db.merge(b"k1", 64u64.to_ne_bytes()); |
|
|
|
|
|
|
|
assert!(m.is_ok()); |
|
|
|
|
|
|
|
match db.get(b"k1") { |
|
|
|
|
|
|
|
Ok(Some(value)) => { |
|
|
|
|
|
|
|
let mut bytes: [u8; 8] = Default::default(); |
|
|
|
|
|
|
|
bytes.copy_from_slice(&value); |
|
|
|
|
|
|
|
assert_eq!(u64::from_ne_bytes(bytes), 64); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Err(_) => println!("error reading value"), |
|
|
|
|
|
|
|
_ => panic!("value not present"), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert!(db.delete(b"k1").is_ok()); |
|
|
|
|
|
|
|
assert!(db.get(b"k1").unwrap().is_none()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
assert!(DB::destroy(&opts, path).is_ok()); |
|
|
|
|
|
|
|
} |
|
|
|