|
|
@ -1,4 +1,4 @@ |
|
|
|
// Copyright 2014 Tyler Neely
|
|
|
|
// Copyright 2020 Tyler Neely
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
@ -101,7 +101,7 @@ impl DB { |
|
|
|
.into_iter() |
|
|
|
.into_iter() |
|
|
|
.map(|name| ColumnFamilyDescriptor::new(name.as_ref(), Options::default())); |
|
|
|
.map(|name| ColumnFamilyDescriptor::new(name.as_ref(), Options::default())); |
|
|
|
|
|
|
|
|
|
|
|
DB::open_cf_descriptors_internal(opts, path, cfs, AccessType::ReadWrite) |
|
|
|
DB::open_cf_descriptors_internal(opts, path, cfs, &AccessType::ReadWrite) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Opens a database for read only with the given database options and column family names.
|
|
|
|
/// Opens a database for read only with the given database options and column family names.
|
|
|
@ -124,7 +124,7 @@ impl DB { |
|
|
|
opts, |
|
|
|
opts, |
|
|
|
path, |
|
|
|
path, |
|
|
|
cfs, |
|
|
|
cfs, |
|
|
|
AccessType::ReadOnly { |
|
|
|
&AccessType::ReadOnly { |
|
|
|
error_if_log_file_exist, |
|
|
|
error_if_log_file_exist, |
|
|
|
}, |
|
|
|
}, |
|
|
|
) |
|
|
|
) |
|
|
@ -150,7 +150,7 @@ impl DB { |
|
|
|
opts, |
|
|
|
opts, |
|
|
|
primary_path, |
|
|
|
primary_path, |
|
|
|
cfs, |
|
|
|
cfs, |
|
|
|
AccessType::Secondary { |
|
|
|
&AccessType::Secondary { |
|
|
|
secondary_path: secondary_path.as_ref(), |
|
|
|
secondary_path: secondary_path.as_ref(), |
|
|
|
}, |
|
|
|
}, |
|
|
|
) |
|
|
|
) |
|
|
@ -162,7 +162,7 @@ impl DB { |
|
|
|
P: AsRef<Path>, |
|
|
|
P: AsRef<Path>, |
|
|
|
I: IntoIterator<Item = ColumnFamilyDescriptor>, |
|
|
|
I: IntoIterator<Item = ColumnFamilyDescriptor>, |
|
|
|
{ |
|
|
|
{ |
|
|
|
DB::open_cf_descriptors_internal(opts, path, cfs, AccessType::ReadWrite) |
|
|
|
DB::open_cf_descriptors_internal(opts, path, cfs, &AccessType::ReadWrite) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Internal implementation for opening RocksDB.
|
|
|
|
/// Internal implementation for opening RocksDB.
|
|
|
@ -170,7 +170,7 @@ impl DB { |
|
|
|
opts: &Options, |
|
|
|
opts: &Options, |
|
|
|
path: P, |
|
|
|
path: P, |
|
|
|
cfs: I, |
|
|
|
cfs: I, |
|
|
|
access_type: AccessType, |
|
|
|
access_type: &AccessType, |
|
|
|
) -> Result<DB, Error> |
|
|
|
) -> Result<DB, Error> |
|
|
|
where |
|
|
|
where |
|
|
|
P: AsRef<Path>, |
|
|
|
P: AsRef<Path>, |
|
|
@ -191,7 +191,7 @@ impl DB { |
|
|
|
let mut cf_map = BTreeMap::new(); |
|
|
|
let mut cf_map = BTreeMap::new(); |
|
|
|
|
|
|
|
|
|
|
|
if cfs.is_empty() { |
|
|
|
if cfs.is_empty() { |
|
|
|
db = DB::open_raw(opts, cpath, access_type)?; |
|
|
|
db = DB::open_raw(opts, &cpath, access_type)?; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
let mut cfs_v = cfs; |
|
|
|
let mut cfs_v = cfs; |
|
|
|
// Always open the default column family.
|
|
|
|
// Always open the default column family.
|
|
|
@ -220,12 +220,12 @@ impl DB { |
|
|
|
|
|
|
|
|
|
|
|
db = DB::open_cf_raw( |
|
|
|
db = DB::open_cf_raw( |
|
|
|
opts, |
|
|
|
opts, |
|
|
|
cpath, |
|
|
|
&cpath, |
|
|
|
&cfs_v, |
|
|
|
&cfs_v, |
|
|
|
&cfnames, |
|
|
|
&cfnames, |
|
|
|
&cfopts, |
|
|
|
&cfopts, |
|
|
|
&mut cfhandles, |
|
|
|
&mut cfhandles, |
|
|
|
access_type, |
|
|
|
&access_type, |
|
|
|
)?; |
|
|
|
)?; |
|
|
|
for handle in &cfhandles { |
|
|
|
for handle in &cfhandles { |
|
|
|
if handle.is_null() { |
|
|
|
if handle.is_null() { |
|
|
@ -253,11 +253,11 @@ impl DB { |
|
|
|
|
|
|
|
|
|
|
|
fn open_raw( |
|
|
|
fn open_raw( |
|
|
|
opts: &Options, |
|
|
|
opts: &Options, |
|
|
|
cpath: CString, |
|
|
|
cpath: &CString, |
|
|
|
access_type: AccessType, |
|
|
|
access_type: &AccessType, |
|
|
|
) -> Result<*mut ffi::rocksdb_t, Error> { |
|
|
|
) -> Result<*mut ffi::rocksdb_t, Error> { |
|
|
|
let db = unsafe { |
|
|
|
let db = unsafe { |
|
|
|
match access_type { |
|
|
|
match *access_type { |
|
|
|
AccessType::ReadOnly { |
|
|
|
AccessType::ReadOnly { |
|
|
|
error_if_log_file_exist, |
|
|
|
error_if_log_file_exist, |
|
|
|
} => ffi_try!(ffi::rocksdb_open_for_read_only( |
|
|
|
} => ffi_try!(ffi::rocksdb_open_for_read_only( |
|
|
@ -282,15 +282,15 @@ impl DB { |
|
|
|
|
|
|
|
|
|
|
|
fn open_cf_raw( |
|
|
|
fn open_cf_raw( |
|
|
|
opts: &Options, |
|
|
|
opts: &Options, |
|
|
|
cpath: CString, |
|
|
|
cpath: &CString, |
|
|
|
cfs_v: &[ColumnFamilyDescriptor], |
|
|
|
cfs_v: &[ColumnFamilyDescriptor], |
|
|
|
cfnames: &[*const c_char], |
|
|
|
cfnames: &[*const c_char], |
|
|
|
cfopts: &[*const ffi::rocksdb_options_t], |
|
|
|
cfopts: &[*const ffi::rocksdb_options_t], |
|
|
|
cfhandles: &mut Vec<*mut ffi::rocksdb_column_family_handle_t>, |
|
|
|
cfhandles: &mut Vec<*mut ffi::rocksdb_column_family_handle_t>, |
|
|
|
access_type: AccessType, |
|
|
|
access_type: &AccessType, |
|
|
|
) -> Result<*mut ffi::rocksdb_t, Error> { |
|
|
|
) -> Result<*mut ffi::rocksdb_t, Error> { |
|
|
|
let db = unsafe { |
|
|
|
let db = unsafe { |
|
|
|
match access_type { |
|
|
|
match *access_type { |
|
|
|
AccessType::ReadOnly { |
|
|
|
AccessType::ReadOnly { |
|
|
|
error_if_log_file_exist, |
|
|
|
error_if_log_file_exist, |
|
|
|
} => ffi_try!(ffi::rocksdb_open_for_read_only_column_families( |
|
|
|
} => ffi_try!(ffi::rocksdb_open_for_read_only_column_families( |
|
|
@ -537,19 +537,18 @@ impl DB { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn create_cf<N: AsRef<str>>(&mut self, name: N, opts: &Options) -> Result<(), Error> { |
|
|
|
pub fn create_cf<N: AsRef<str>>(&mut self, name: N, opts: &Options) -> Result<(), Error> { |
|
|
|
let cname = match CString::new(name.as_ref().as_bytes()) { |
|
|
|
let cf_name = if let Ok(c) = CString::new(name.as_ref().as_bytes()) { |
|
|
|
Ok(c) => c, |
|
|
|
c |
|
|
|
Err(_) => { |
|
|
|
} else { |
|
|
|
return Err(Error::new( |
|
|
|
return Err(Error::new( |
|
|
|
"Failed to convert path to CString when creating cf".to_owned(), |
|
|
|
"Failed to convert path to CString when creating cf".to_owned(), |
|
|
|
)); |
|
|
|
)); |
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
unsafe { |
|
|
|
unsafe { |
|
|
|
let inner = ffi_try!(ffi::rocksdb_create_column_family( |
|
|
|
let inner = ffi_try!(ffi::rocksdb_create_column_family( |
|
|
|
self.inner, |
|
|
|
self.inner, |
|
|
|
opts.inner, |
|
|
|
opts.inner, |
|
|
|
cname.as_ptr(), |
|
|
|
cf_name.as_ptr(), |
|
|
|
)); |
|
|
|
)); |
|
|
|
|
|
|
|
|
|
|
|
self.cfs |
|
|
|
self.cfs |
|
|
@ -565,9 +564,7 @@ impl DB { |
|
|
|
} |
|
|
|
} |
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
Err(Error::new( |
|
|
|
Err(Error::new(format!("Invalid column family: {}", name))) |
|
|
|
format!("Invalid column family: {}", name).to_owned(), |
|
|
|
|
|
|
|
)) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -896,8 +893,8 @@ impl DB { |
|
|
|
|
|
|
|
|
|
|
|
pub fn compact_range<S: AsRef<[u8]>, E: AsRef<[u8]>>(&self, start: Option<S>, end: Option<E>) { |
|
|
|
pub fn compact_range<S: AsRef<[u8]>, E: AsRef<[u8]>>(&self, start: Option<S>, end: Option<E>) { |
|
|
|
unsafe { |
|
|
|
unsafe { |
|
|
|
let start = start.as_ref().map(|s| s.as_ref()); |
|
|
|
let start = start.as_ref().map(AsRef::as_ref); |
|
|
|
let end = end.as_ref().map(|e| e.as_ref()); |
|
|
|
let end = end.as_ref().map(AsRef::as_ref); |
|
|
|
|
|
|
|
|
|
|
|
ffi::rocksdb_compact_range( |
|
|
|
ffi::rocksdb_compact_range( |
|
|
|
self.inner, |
|
|
|
self.inner, |
|
|
@ -916,8 +913,8 @@ impl DB { |
|
|
|
end: Option<E>, |
|
|
|
end: Option<E>, |
|
|
|
) { |
|
|
|
) { |
|
|
|
unsafe { |
|
|
|
unsafe { |
|
|
|
let start = start.as_ref().map(|s| s.as_ref()); |
|
|
|
let start = start.as_ref().map(AsRef::as_ref); |
|
|
|
let end = end.as_ref().map(|e| e.as_ref()); |
|
|
|
let end = end.as_ref().map(AsRef::as_ref); |
|
|
|
|
|
|
|
|
|
|
|
ffi::rocksdb_compact_range_cf( |
|
|
|
ffi::rocksdb_compact_range_cf( |
|
|
|
self.inner, |
|
|
|
self.inner, |
|
|
@ -1220,9 +1217,9 @@ fn writebatch_works() { |
|
|
|
assert!(db.get(b"k1").unwrap().is_none()); |
|
|
|
assert!(db.get(b"k1").unwrap().is_none()); |
|
|
|
assert_eq!(batch.len(), 0); |
|
|
|
assert_eq!(batch.len(), 0); |
|
|
|
assert!(batch.is_empty()); |
|
|
|
assert!(batch.is_empty()); |
|
|
|
let _ = batch.put(b"k1", b"v1111"); |
|
|
|
batch.put(b"k1", b"v1111"); |
|
|
|
let _ = batch.put(b"k2", b"v2222"); |
|
|
|
batch.put(b"k2", b"v2222"); |
|
|
|
let _ = batch.put(b"k3", b"v3333"); |
|
|
|
batch.put(b"k3", b"v3333"); |
|
|
|
assert_eq!(batch.len(), 3); |
|
|
|
assert_eq!(batch.len(), 3); |
|
|
|
assert!(!batch.is_empty()); |
|
|
|
assert!(!batch.is_empty()); |
|
|
|
assert!(db.get(b"k1").unwrap().is_none()); |
|
|
|
assert!(db.get(b"k1").unwrap().is_none()); |
|
|
@ -1234,7 +1231,7 @@ fn writebatch_works() { |
|
|
|
{ |
|
|
|
{ |
|
|
|
// test delete
|
|
|
|
// test delete
|
|
|
|
let mut batch = WriteBatch::default(); |
|
|
|
let mut batch = WriteBatch::default(); |
|
|
|
let _ = batch.delete(b"k1"); |
|
|
|
batch.delete(b"k1"); |
|
|
|
assert_eq!(batch.len(), 1); |
|
|
|
assert_eq!(batch.len(), 1); |
|
|
|
assert!(!batch.is_empty()); |
|
|
|
assert!(!batch.is_empty()); |
|
|
|
let p = db.write(batch); |
|
|
|
let p = db.write(batch); |
|
|
@ -1244,7 +1241,7 @@ fn writebatch_works() { |
|
|
|
{ |
|
|
|
{ |
|
|
|
// test delete_range
|
|
|
|
// test delete_range
|
|
|
|
let mut batch = WriteBatch::default(); |
|
|
|
let mut batch = WriteBatch::default(); |
|
|
|
let _ = batch.delete_range(b"k2", b"k4"); |
|
|
|
batch.delete_range(b"k2", b"k4"); |
|
|
|
assert_eq!(batch.len(), 1); |
|
|
|
assert_eq!(batch.len(), 1); |
|
|
|
assert!(!batch.is_empty()); |
|
|
|
assert!(!batch.is_empty()); |
|
|
|
let p = db.write(batch); |
|
|
|
let p = db.write(batch); |
|
|
@ -1256,7 +1253,7 @@ fn writebatch_works() { |
|
|
|
// test size_in_bytes
|
|
|
|
// test size_in_bytes
|
|
|
|
let mut batch = WriteBatch::default(); |
|
|
|
let mut batch = WriteBatch::default(); |
|
|
|
let before = batch.size_in_bytes(); |
|
|
|
let before = batch.size_in_bytes(); |
|
|
|
let _ = batch.put(b"k1", b"v1234567890"); |
|
|
|
batch.put(b"k1", b"v1234567890"); |
|
|
|
let after = batch.size_in_bytes(); |
|
|
|
let after = batch.size_in_bytes(); |
|
|
|
assert!(before + 10 <= after); |
|
|
|
assert!(before + 10 <= after); |
|
|
|
} |
|
|
|
} |
|
|
@ -1355,7 +1352,7 @@ fn iterator_test_tailing() { |
|
|
|
(k.to_vec(), v.to_vec()), |
|
|
|
(k.to_vec(), v.to_vec()), |
|
|
|
(data[i].0.to_vec(), data[i].1.to_vec()) |
|
|
|
(data[i].0.to_vec(), data[i].1.to_vec()) |
|
|
|
); |
|
|
|
); |
|
|
|
tot = tot + 1; |
|
|
|
tot += 1; |
|
|
|
} |
|
|
|
} |
|
|
|
assert_eq!(tot, data.len()); |
|
|
|
assert_eq!(tot, data.len()); |
|
|
|
} |
|
|
|
} |
|
|
|