/* 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. */ #![feature(test)] #![feature(vec_push_all)] extern crate rocksdb; extern crate test; use rocksdb::{RocksDBOptions, RocksDB, MergeOperands, new_bloom_filter}; use rocksdb::RocksDBCompactionStyle::RocksDBUniversalCompaction; fn main() { let path = "/tmp/rust-rocksdb"; let db = RocksDB::open_default(path).unwrap(); assert!(db.put(b"my key", b"my value").is_ok()); db.get(b"my key").map( |value| { match value.to_utf8() { Some(v) => println!("retrieved utf8 value: {}", v), None => println!("did not read valid utf-8 out of the db"), } }) .on_absent( || { println!("value not found") }) .on_error( |e| { println!("error retrieving value: {}", e) }); assert!(db.delete(b"my key").is_ok()); db.close(); custom_merge(); } fn concat_merge(new_key: &[u8], existing_val: Option<&[u8]>, mut operands: &mut MergeOperands) -> Vec { let mut result: Vec = Vec::with_capacity(operands.size_hint().0); match existing_val { Some(v) => result.push_all(v), None => (), } for op in operands { result.push_all(op); } result } fn custom_merge() { let path = "_rust_rocksdb_mergetest"; let opts = RocksDBOptions::new(); opts.create_if_missing(true); opts.add_merge_operator("test operator", concat_merge); let db = RocksDB::open(opts, path).unwrap(); db.put(b"k1", b"a"); db.merge(b"k1", b"b"); db.merge(b"k1", b"c"); db.merge(b"k1", b"d"); db.merge(b"k1", b"efg"); db.merge(b"k1", b"h"); db.get(b"k1").map( |value| { match value.to_utf8() { Some(v) => println!("retrieved utf8 value: {}", v), None => println!("did not read valid utf-8 out of the db"), } }) .on_absent( || { println!("value not found") }) .on_error( |e| { println!("error retrieving value: {}", e) }); db.close(); RocksDB::destroy(opts, path).is_ok(); } #[cfg(test)] mod tests { use test::Bencher; use std::thread::sleep_ms; use rocksdb::{RocksDBOptions, RocksDB, MergeOperands, new_bloom_filter}; use rocksdb::RocksDBCompactionStyle::RocksDBUniversalCompaction; fn tuned_for_somebody_elses_disk() -> RocksDB { let path = "_rust_rocksdb_optimizetest"; let opts = RocksDBOptions::new(); opts.create_if_missing(true); opts.set_block_size(524288); opts.set_max_open_files(10000); opts.set_use_fsync(false); opts.set_bytes_per_sync(8388608); opts.set_disable_data_sync(false); opts.set_block_cache_size_mb(1024); opts.set_table_cache_num_shard_bits(6); opts.set_max_write_buffer_number(32); opts.set_write_buffer_size(536870912); opts.set_target_file_size_base(1073741824); opts.set_min_write_buffer_number_to_merge(4); opts.set_level_zero_stop_writes_trigger(2000); opts.set_level_zero_slowdown_writes_trigger(0); opts.set_compaction_style(RocksDBUniversalCompaction); opts.set_max_background_compactions(4); opts.set_max_background_flushes(4); opts.set_filter_deletes(false); opts.set_disable_auto_compactions(true); let filter = new_bloom_filter(10); opts.set_filter(filter); RocksDB::open(opts, path).unwrap() } #[bench] fn writes(b: &mut Bencher) { // dirty hack due to parallel tests causing contention. sleep_ms(1000); let db = tuned_for_somebody_elses_disk(); let mut i = 0 as u64; b.iter(|| { db.put(i.to_string().as_bytes(), b"v1111"); i += 1; }); db.close(); } #[bench] fn reads(b: &mut Bencher) { let db = tuned_for_somebody_elses_disk(); let mut i = 0 as u64; b.iter(|| { db.get(i.to_string().as_bytes()).on_error( |e| { println!("error: {}", e); e }); i += 1; }); db.close(); } }