From 2acd21c52929725ab3093b93c835992682acaa69 Mon Sep 17 00:00:00 2001 From: Victor Porof Date: Wed, 11 Sep 2019 10:07:34 +0200 Subject: [PATCH] Rustfmt pass (cargo +nightly fmt --all) Signed-off-by: Victor Porof --- benches/cursor.rs | 24 ++- benches/transaction.rs | 36 +++- benches/utils.rs | 6 +- lmdb-sys/tests/lmdb.rs | 30 ++-- src/cursor.rs | 380 ++++++++++++++++++++++++----------------- src/database.rs | 21 ++- src/environment.rs | 136 ++++++++------- src/error.rs | 91 +++++----- src/lib.rs | 39 +++-- src/transaction.rs | 278 ++++++++++++++++-------------- 10 files changed, 594 insertions(+), 447 deletions(-) diff --git a/benches/cursor.rs b/benches/cursor.rs index 579d6ac..5f81e70 100644 --- a/benches/cursor.rs +++ b/benches/cursor.rs @@ -7,9 +7,17 @@ extern crate test; mod utils; use ffi::*; -use lmdb::{Cursor, Result, RoCursor, Transaction}; +use lmdb::{ + Cursor, + Result, + RoCursor, + Transaction, +}; use std::ptr; -use test::{Bencher, black_box}; +use test::{ + black_box, + Bencher, +}; use utils::*; /// Benchmark of iterator sequential read performance. @@ -85,8 +93,14 @@ fn bench_get_seq_raw(b: &mut Bencher) { let _txn = env.begin_ro_txn().unwrap(); let txn = _txn.txn(); - let mut key = MDB_val { mv_size: 0, mv_data: ptr::null_mut() }; - let mut data = MDB_val { mv_size: 0, mv_data: ptr::null_mut() }; + let mut key = MDB_val { + mv_size: 0, + mv_data: ptr::null_mut(), + }; + let mut data = MDB_val { + mv_size: 0, + mv_data: ptr::null_mut(), + }; let mut cursor: *mut MDB_cursor = ptr::null_mut(); b.iter(|| unsafe { @@ -97,7 +111,7 @@ fn bench_get_seq_raw(b: &mut Bencher) { while mdb_cursor_get(cursor, &mut key, &mut data, MDB_NEXT) == 0 { i += key.mv_size + data.mv_size; count += 1; - }; + } black_box(i); assert_eq!(count, n); diff --git a/benches/transaction.rs b/benches/transaction.rs index a0b4590..e6c86ee 100644 --- a/benches/transaction.rs +++ b/benches/transaction.rs @@ -10,10 +10,19 @@ mod utils; use ffi::*; use libc::size_t; -use lmdb::{Transaction, WriteFlags}; -use rand::{Rng, XorShiftRng}; +use lmdb::{ + Transaction, + WriteFlags, +}; +use rand::{ + Rng, + XorShiftRng, +}; use std::ptr; -use test::{Bencher, black_box}; +use test::{ + black_box, + Bencher, +}; use utils::*; #[bench] @@ -48,8 +57,14 @@ fn bench_get_rand_raw(b: &mut Bencher) { let dbi = db.dbi(); let txn = _txn.txn(); - let mut key_val: MDB_val = MDB_val { mv_size: 0, mv_data: ptr::null_mut() }; - let mut data_val: MDB_val = MDB_val { mv_size: 0, mv_data: ptr::null_mut() }; + let mut key_val: MDB_val = MDB_val { + mv_size: 0, + mv_data: ptr::null_mut(), + }; + let mut data_val: MDB_val = MDB_val { + mv_size: 0, + mv_data: ptr::null_mut(), + }; b.iter(|| unsafe { let mut i: size_t = 0; @@ -95,8 +110,14 @@ fn bench_put_rand_raw(b: &mut Bencher) { let dbi = db.dbi(); let env = _env.env(); - let mut key_val: MDB_val = MDB_val { mv_size: 0, mv_data: ptr::null_mut() }; - let mut data_val: MDB_val = MDB_val { mv_size: 0, mv_data: ptr::null_mut() }; + let mut key_val: MDB_val = MDB_val { + mv_size: 0, + mv_data: ptr::null_mut(), + }; + let mut data_val: MDB_val = MDB_val { + mv_size: 0, + mv_data: ptr::null_mut(), + }; b.iter(|| unsafe { let mut txn: *mut MDB_txn = ptr::null_mut(); @@ -104,7 +125,6 @@ fn bench_put_rand_raw(b: &mut Bencher) { let mut i: ::libc::c_int = 0; for &(ref key, ref data) in items.iter() { - key_val.mv_size = key.len() as size_t; key_val.mv_data = key.as_bytes().as_ptr() as *mut _; data_val.mv_size = data.len() as size_t; diff --git a/benches/utils.rs b/benches/utils.rs index bbe1e56..e01b061 100644 --- a/benches/utils.rs +++ b/benches/utils.rs @@ -1,8 +1,12 @@ extern crate lmdb; extern crate tempdir; -use lmdb::{Environment, Transaction, WriteFlags}; use self::tempdir::TempDir; +use lmdb::{ + Environment, + Transaction, + WriteFlags, +}; pub fn get_key(n: u32) -> String { format!("key{}", n) diff --git a/lmdb-sys/tests/lmdb.rs b/lmdb-sys/tests/lmdb.rs index 82ddb49..460f8b7 100644 --- a/lmdb-sys/tests/lmdb.rs +++ b/lmdb-sys/tests/lmdb.rs @@ -6,23 +6,23 @@ use std::process::Command; #[test] fn test_lmdb() { - let mut lmdb = PathBuf::from(&env::var("CARGO_MANIFEST_DIR").unwrap()); - lmdb.push("lmdb"); - lmdb.push("libraries"); - lmdb.push("liblmdb"); + let mut lmdb = PathBuf::from(&env::var("CARGO_MANIFEST_DIR").unwrap()); + lmdb.push("lmdb"); + lmdb.push("libraries"); + lmdb.push("liblmdb"); - let make_cmd = Command::new("make") - .current_dir(&lmdb) - .status() - .expect("failed to execute process"); + let make_cmd = Command::new("make") + .current_dir(&lmdb) + .status() + .expect("failed to execute process"); - assert_eq!(make_cmd.success(), true); + assert_eq!(make_cmd.success(), true); - let make_test_cmd = Command::new("make") - .arg("test") - .current_dir(&lmdb) - .status() - .expect("failed to execute process"); + let make_test_cmd = Command::new("make") + .arg("test") + .current_dir(&lmdb) + .status() + .expect("failed to execute process"); - assert_eq!(make_test_cmd.success(), true); + assert_eq!(make_test_cmd.success(), true); } diff --git a/src/cursor.rs b/src/cursor.rs index 9e332df..6c65fb5 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -1,17 +1,31 @@ use std::marker::PhantomData; -use std::{fmt, mem, ptr, result, slice}; - -use libc::{EINVAL, c_void, size_t, c_uint}; +use std::{ + fmt, + mem, + ptr, + result, + slice, +}; + +use libc::{ + c_uint, + c_void, + size_t, + EINVAL, +}; use database::Database; -use error::{Error, Result, lmdb_result}; +use error::{ + lmdb_result, + Error, + Result, +}; use ffi; use flags::WriteFlags; use transaction::Transaction; /// An LMDB cursor. pub trait Cursor<'txn> { - /// Returns a raw pointer to the underlying LMDB cursor. /// /// The caller **must** ensure that the pointer is not used after the @@ -26,7 +40,11 @@ pub trait Cursor<'txn> { let mut data_val = slice_to_val(data); let key_ptr = key_val.mv_data; lmdb_result(ffi::mdb_cursor_get(self.cursor(), &mut key_val, &mut data_val, op))?; - let key_out = if key_ptr != key_val.mv_data { Some(val_to_slice(key_val)) } else { None }; + let key_out = if key_ptr != key_val.mv_data { + Some(val_to_slice(key_val)) + } else { + None + }; let data_out = val_to_slice(data_val); Ok((key_out, data_out)) } @@ -57,7 +75,10 @@ pub trait Cursor<'txn> { /// For databases with duplicate data items (`DatabaseFlags::DUP_SORT`), the /// duplicate data items of each key will be returned before moving on to /// the next key. - fn iter_from(&mut self, key: K) -> Iter<'txn> where K: AsRef<[u8]> { + fn iter_from(&mut self, key: K) -> Iter<'txn> + where + K: AsRef<[u8]>, + { match self.get(Some(key.as_ref()), None, ffi::MDB_SET_RANGE) { Ok(_) | Err(Error::NotFound) => (), Err(error) => return Iter::Err(error), @@ -80,7 +101,10 @@ pub trait Cursor<'txn> { /// Iterate over duplicate items in the database starting from the given /// key. Each item will be returned as an iterator of its duplicates. - fn iter_dup_from(&mut self, key: K) -> IterDup<'txn> where K: AsRef<[u8]> { + fn iter_dup_from(&mut self, key: K) -> IterDup<'txn> + where + K: AsRef<[u8]>, + { match self.get(Some(key.as_ref()), None, ffi::MDB_SET_RANGE) { Ok(_) | Err(Error::NotFound) => (), Err(error) => return IterDup::Err(error), @@ -89,7 +113,10 @@ pub trait Cursor<'txn> { } /// Iterate over the duplicates of the item in the database with the given key. - fn iter_dup_of(&mut self, key: K) -> Iter<'txn> where K: AsRef<[u8]> { + fn iter_dup_of(&mut self, key: K) -> Iter<'txn> + where + K: AsRef<[u8]>, + { match self.get(Some(key.as_ref()), None, ffi::MDB_SET) { Ok(_) | Err(Error::NotFound) => (), Err(error) => return Iter::Err(error), @@ -104,31 +131,35 @@ pub struct RoCursor<'txn> { _marker: PhantomData &'txn ()>, } -impl <'txn> Cursor<'txn> for RoCursor<'txn> { +impl<'txn> Cursor<'txn> for RoCursor<'txn> { fn cursor(&self) -> *mut ffi::MDB_cursor { self.cursor } } -impl <'txn> fmt::Debug for RoCursor<'txn> { +impl<'txn> fmt::Debug for RoCursor<'txn> { fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { f.debug_struct("RoCursor").finish() } } -impl <'txn> Drop for RoCursor<'txn> { +impl<'txn> Drop for RoCursor<'txn> { fn drop(&mut self) { unsafe { ffi::mdb_cursor_close(self.cursor) } } } -impl <'txn> RoCursor<'txn> { - +impl<'txn> RoCursor<'txn> { /// Creates a new read-only cursor in the given database and transaction. /// Prefer using `Transaction::open_cursor`. - pub(crate) fn new(txn: &'txn T, db: Database) -> Result> where T: Transaction { + pub(crate) fn new(txn: &'txn T, db: Database) -> Result> + where + T: Transaction, + { let mut cursor: *mut ffi::MDB_cursor = ptr::null_mut(); - unsafe { lmdb_result(ffi::mdb_cursor_open(txn.txn(), db.dbi(), &mut cursor))?; } + unsafe { + lmdb_result(ffi::mdb_cursor_open(txn.txn(), db.dbi(), &mut cursor))?; + } Ok(RoCursor { cursor: cursor, _marker: PhantomData, @@ -142,50 +173,59 @@ pub struct RwCursor<'txn> { _marker: PhantomData &'txn ()>, } -impl <'txn> Cursor<'txn> for RwCursor<'txn> { +impl<'txn> Cursor<'txn> for RwCursor<'txn> { fn cursor(&self) -> *mut ffi::MDB_cursor { self.cursor } } -impl <'txn> fmt::Debug for RwCursor<'txn> { +impl<'txn> fmt::Debug for RwCursor<'txn> { fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { f.debug_struct("RwCursor").finish() } } -impl <'txn> Drop for RwCursor<'txn> { +impl<'txn> Drop for RwCursor<'txn> { fn drop(&mut self) { unsafe { ffi::mdb_cursor_close(self.cursor) } } } -impl <'txn> RwCursor<'txn> { - +impl<'txn> RwCursor<'txn> { /// Creates a new read-only cursor in the given database and transaction. /// Prefer using `RwTransaction::open_rw_cursor`. - pub(crate) fn new(txn: &'txn T, db: Database) -> Result> where T: Transaction { + pub(crate) fn new(txn: &'txn T, db: Database) -> Result> + where + T: Transaction, + { let mut cursor: *mut ffi::MDB_cursor = ptr::null_mut(); - unsafe { lmdb_result(ffi::mdb_cursor_open(txn.txn(), db.dbi(), &mut cursor))?; } - Ok(RwCursor { cursor: cursor, _marker: PhantomData }) + unsafe { + lmdb_result(ffi::mdb_cursor_open(txn.txn(), db.dbi(), &mut cursor))?; + } + Ok(RwCursor { + cursor: cursor, + _marker: PhantomData, + }) } /// Puts a key/data pair into the database. The cursor will be positioned at /// the new data item, or on failure usually near it. pub fn put(&mut self, key: &K, data: &D, flags: WriteFlags) -> Result<()> - where K: AsRef<[u8]>, D: AsRef<[u8]> { + where + K: AsRef<[u8]>, + D: AsRef<[u8]>, + { let key = key.as_ref(); let data = data.as_ref(); - let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t, - mv_data: key.as_ptr() as *mut c_void }; - let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: data.len() as size_t, - mv_data: data.as_ptr() as *mut c_void }; - unsafe { - lmdb_result(ffi::mdb_cursor_put(self.cursor(), - &mut key_val, - &mut data_val, - flags.bits())) - } + let mut key_val: ffi::MDB_val = ffi::MDB_val { + mv_size: key.len() as size_t, + mv_data: key.as_ptr() as *mut c_void, + }; + let mut data_val: ffi::MDB_val = ffi::MDB_val { + mv_size: data.len() as size_t, + mv_data: data.as_ptr() as *mut c_void, + }; + unsafe { lmdb_result(ffi::mdb_cursor_put(self.cursor(), &mut key_val, &mut data_val, flags.bits())) } } /// Deletes the current key/data pair. @@ -201,12 +241,14 @@ impl <'txn> RwCursor<'txn> { unsafe fn slice_to_val(slice: Option<&[u8]>) -> ffi::MDB_val { match slice { - Some(slice) => - ffi::MDB_val { mv_size: slice.len() as size_t, - mv_data: slice.as_ptr() as *mut c_void }, - None => - ffi::MDB_val { mv_size: 0, - mv_data: ptr::null_mut() }, + Some(slice) => ffi::MDB_val { + mv_size: slice.len() as size_t, + mv_data: slice.as_ptr() as *mut c_void, + }, + None => ffi::MDB_val { + mv_size: 0, + mv_data: ptr::null_mut(), + }, } } @@ -242,29 +284,43 @@ pub enum Iter<'txn> { }, } -impl <'txn> Iter<'txn> { - +impl<'txn> Iter<'txn> { /// Creates a new iterator backed by the given cursor. fn new<'t>(cursor: *mut ffi::MDB_cursor, op: c_uint, next_op: c_uint) -> Iter<'t> { - Iter::Ok { cursor: cursor, op: op, next_op: next_op, _marker: PhantomData } + Iter::Ok { + cursor: cursor, + op: op, + next_op: next_op, + _marker: PhantomData, + } } } -impl <'txn> fmt::Debug for Iter<'txn> { +impl<'txn> fmt::Debug for Iter<'txn> { fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { f.debug_struct("Iter").finish() } } -impl <'txn> Iterator for Iter<'txn> { - +impl<'txn> Iterator for Iter<'txn> { type Item = Result<(&'txn [u8], &'txn [u8])>; fn next(&mut self) -> Option> { match self { - &mut Iter::Ok { cursor, ref mut op, next_op, _marker } => { - let mut key = ffi::MDB_val { mv_size: 0, mv_data: ptr::null_mut() }; - let mut data = ffi::MDB_val { mv_size: 0, mv_data: ptr::null_mut() }; + &mut Iter::Ok { + cursor, + ref mut op, + next_op, + _marker, + } => { + let mut key = ffi::MDB_val { + mv_size: 0, + mv_data: ptr::null_mut(), + }; + let mut data = ffi::MDB_val { + mv_size: 0, + mv_data: ptr::null_mut(), + }; let op = mem::replace(op, next_op); unsafe { match ffi::mdb_cursor_get(cursor, &mut key, &mut data, op) { @@ -309,33 +365,43 @@ pub enum IterDup<'txn> { }, } -impl <'txn> IterDup<'txn> { - +impl<'txn> IterDup<'txn> { /// Creates a new iterator backed by the given cursor. fn new<'t>(cursor: *mut ffi::MDB_cursor, op: c_uint) -> IterDup<'t> { - IterDup::Ok { cursor: cursor, op: op, _marker: PhantomData } + IterDup::Ok { + cursor: cursor, + op: op, + _marker: PhantomData, + } } } -impl <'txn> fmt::Debug for IterDup<'txn> { +impl<'txn> fmt::Debug for IterDup<'txn> { fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { f.debug_struct("IterDup").finish() } } -impl <'txn> Iterator for IterDup<'txn> { - +impl<'txn> Iterator for IterDup<'txn> { type Item = Iter<'txn>; fn next(&mut self) -> Option> { match self { - &mut IterDup::Ok { cursor, ref mut op, _marker } => { - let mut key = ffi::MDB_val { mv_size: 0, mv_data: ptr::null_mut() }; - let mut data = ffi::MDB_val { mv_size: 0, mv_data: ptr::null_mut() }; - let op = mem::replace(op, ffi::MDB_NEXT_NODUP); - let err_code = unsafe { - ffi::mdb_cursor_get(cursor, &mut key, &mut data, op) + &mut IterDup::Ok { + cursor, + ref mut op, + _marker, + } => { + let mut key = ffi::MDB_val { + mv_size: 0, + mv_data: ptr::null_mut(), + }; + let mut data = ffi::MDB_val { + mv_size: 0, + mv_data: ptr::null_mut(), }; + let op = mem::replace(op, ffi::MDB_NEXT_NODUP); + let err_code = unsafe { ffi::mdb_cursor_get(cursor, &mut key, &mut data, op) }; if err_code == ffi::MDB_SUCCESS { Some(Iter::new(cursor, ffi::MDB_GET_CURRENT, ffi::MDB_NEXT_DUP)) @@ -352,10 +418,10 @@ impl <'txn> Iterator for IterDup<'txn> { mod test { use tempdir::TempDir; + use super::*; use environment::*; use ffi::*; use flags::*; - use super::*; #[test] fn test_get() { @@ -369,22 +435,14 @@ mod test { txn.put(db, b"key3", b"val3", WriteFlags::empty()).unwrap(); let cursor = txn.open_ro_cursor(db).unwrap(); - assert_eq!((Some(&b"key1"[..]), &b"val1"[..]), - cursor.get(None, None, MDB_FIRST).unwrap()); - assert_eq!((Some(&b"key1"[..]), &b"val1"[..]), - cursor.get(None, None, MDB_GET_CURRENT).unwrap()); - assert_eq!((Some(&b"key2"[..]), &b"val2"[..]), - cursor.get(None, None, MDB_NEXT).unwrap()); - assert_eq!((Some(&b"key1"[..]), &b"val1"[..]), - cursor.get(None, None, MDB_PREV).unwrap()); - assert_eq!((Some(&b"key3"[..]), &b"val3"[..]), - cursor.get(None, None, MDB_LAST).unwrap()); - assert_eq!((None, &b"val2"[..]), - cursor.get(Some(b"key2"), None, MDB_SET).unwrap()); - assert_eq!((Some(&b"key3"[..]), &b"val3"[..]), - cursor.get(Some(&b"key3"[..]), None, MDB_SET_KEY).unwrap()); - assert_eq!((Some(&b"key3"[..]), &b"val3"[..]), - cursor.get(Some(&b"key2\0"[..]), None, MDB_SET_RANGE).unwrap()); + assert_eq!((Some(&b"key1"[..]), &b"val1"[..]), cursor.get(None, None, MDB_FIRST).unwrap()); + assert_eq!((Some(&b"key1"[..]), &b"val1"[..]), cursor.get(None, None, MDB_GET_CURRENT).unwrap()); + assert_eq!((Some(&b"key2"[..]), &b"val2"[..]), cursor.get(None, None, MDB_NEXT).unwrap()); + assert_eq!((Some(&b"key1"[..]), &b"val1"[..]), cursor.get(None, None, MDB_PREV).unwrap()); + assert_eq!((Some(&b"key3"[..]), &b"val3"[..]), cursor.get(None, None, MDB_LAST).unwrap()); + assert_eq!((None, &b"val2"[..]), cursor.get(Some(b"key2"), None, MDB_SET).unwrap()); + assert_eq!((Some(&b"key3"[..]), &b"val3"[..]), cursor.get(Some(&b"key3"[..]), None, MDB_SET_KEY).unwrap()); + assert_eq!((Some(&b"key3"[..]), &b"val3"[..]), cursor.get(Some(&b"key2\0"[..]), None, MDB_SET_RANGE).unwrap()); } #[test] @@ -402,35 +460,24 @@ mod test { txn.put(db, b"key2", b"val3", WriteFlags::empty()).unwrap(); let cursor = txn.open_ro_cursor(db).unwrap(); - assert_eq!((Some(&b"key1"[..]), &b"val1"[..]), - cursor.get(None, None, MDB_FIRST).unwrap()); - assert_eq!((None, &b"val1"[..]), - cursor.get(None, None, MDB_FIRST_DUP).unwrap()); - assert_eq!((Some(&b"key1"[..]), &b"val1"[..]), - cursor.get(None, None, MDB_GET_CURRENT).unwrap()); - assert_eq!((Some(&b"key2"[..]), &b"val1"[..]), - cursor.get(None, None, MDB_NEXT_NODUP).unwrap()); - assert_eq!((Some(&b"key2"[..]), &b"val2"[..]), - cursor.get(None, None, MDB_NEXT_DUP).unwrap()); - assert_eq!((Some(&b"key2"[..]), &b"val3"[..]), - cursor.get(None, None, MDB_NEXT_DUP).unwrap()); + assert_eq!((Some(&b"key1"[..]), &b"val1"[..]), cursor.get(None, None, MDB_FIRST).unwrap()); + assert_eq!((None, &b"val1"[..]), cursor.get(None, None, MDB_FIRST_DUP).unwrap()); + assert_eq!((Some(&b"key1"[..]), &b"val1"[..]), cursor.get(None, None, MDB_GET_CURRENT).unwrap()); + assert_eq!((Some(&b"key2"[..]), &b"val1"[..]), cursor.get(None, None, MDB_NEXT_NODUP).unwrap()); + assert_eq!((Some(&b"key2"[..]), &b"val2"[..]), cursor.get(None, None, MDB_NEXT_DUP).unwrap()); + assert_eq!((Some(&b"key2"[..]), &b"val3"[..]), cursor.get(None, None, MDB_NEXT_DUP).unwrap()); assert!(cursor.get(None, None, MDB_NEXT_DUP).is_err()); - assert_eq!((Some(&b"key2"[..]), &b"val2"[..]), - cursor.get(None, None, MDB_PREV_DUP).unwrap()); - assert_eq!((None, &b"val3"[..]), - cursor.get(None, None, MDB_LAST_DUP).unwrap()); - assert_eq!((Some(&b"key1"[..]), &b"val3"[..]), - cursor.get(None, None, MDB_PREV_NODUP).unwrap()); - assert_eq!((None, &b"val1"[..]), - cursor.get(Some(&b"key1"[..]), None, MDB_SET).unwrap()); - assert_eq!((Some(&b"key2"[..]), &b"val1"[..]), - cursor.get(Some(&b"key2"[..]), None, MDB_SET_KEY).unwrap()); - assert_eq!((Some(&b"key2"[..]), &b"val1"[..]), - cursor.get(Some(&b"key1\0"[..]), None, MDB_SET_RANGE).unwrap()); - assert_eq!((None, &b"val3"[..]), - cursor.get(Some(&b"key1"[..]), Some(&b"val3"[..]), MDB_GET_BOTH).unwrap()); - assert_eq!((None, &b"val1"[..]), - cursor.get(Some(&b"key2"[..]), Some(&b"val"[..]), MDB_GET_BOTH_RANGE).unwrap()); + assert_eq!((Some(&b"key2"[..]), &b"val2"[..]), cursor.get(None, None, MDB_PREV_DUP).unwrap()); + assert_eq!((None, &b"val3"[..]), cursor.get(None, None, MDB_LAST_DUP).unwrap()); + assert_eq!((Some(&b"key1"[..]), &b"val3"[..]), cursor.get(None, None, MDB_PREV_NODUP).unwrap()); + assert_eq!((None, &b"val1"[..]), cursor.get(Some(&b"key1"[..]), None, MDB_SET).unwrap()); + assert_eq!((Some(&b"key2"[..]), &b"val1"[..]), cursor.get(Some(&b"key2"[..]), None, MDB_SET_KEY).unwrap()); + assert_eq!((Some(&b"key2"[..]), &b"val1"[..]), cursor.get(Some(&b"key1\0"[..]), None, MDB_SET_RANGE).unwrap()); + assert_eq!((None, &b"val3"[..]), cursor.get(Some(&b"key1"[..]), Some(&b"val3"[..]), MDB_GET_BOTH).unwrap()); + assert_eq!( + (None, &b"val1"[..]), + cursor.get(Some(&b"key2"[..]), Some(&b"val"[..]), MDB_GET_BOTH_RANGE).unwrap() + ); } #[test] @@ -448,10 +495,8 @@ mod test { txn.put(db, b"key2", b"val6", WriteFlags::empty()).unwrap(); let cursor = txn.open_ro_cursor(db).unwrap(); - assert_eq!((Some(&b"key1"[..]), &b"val1"[..]), - cursor.get(None, None, MDB_FIRST).unwrap()); - assert_eq!((None, &b"val1val2val3"[..]), - cursor.get(None, None, MDB_GET_MULTIPLE).unwrap()); + assert_eq!((Some(&b"key1"[..]), &b"val1"[..]), cursor.get(None, None, MDB_FIRST).unwrap()); + assert_eq!((None, &b"val1val2val3"[..]), cursor.get(None, None, MDB_GET_MULTIPLE).unwrap()); assert!(cursor.get(None, None, MDB_NEXT_MULTIPLE).is_err()); } @@ -461,10 +506,8 @@ mod test { let env = Environment::new().open(dir.path()).unwrap(); let db = env.open_db(None).unwrap(); - let items: Vec<(&[u8], &[u8])> = vec!((b"key1", b"val1"), - (b"key2", b"val2"), - (b"key3", b"val3"), - (b"key5", b"val5")); + let items: Vec<(&[u8], &[u8])> = + vec![(b"key1", b"val1"), (b"key2", b"val2"), (b"key3", b"val3"), (b"key5", b"val5")]; { let mut txn = env.begin_rw_txn().unwrap(); @@ -487,19 +530,27 @@ mod test { assert_eq!(items, retr.unwrap()); cursor.get(Some(b"key2"), None, MDB_SET).unwrap(); - assert_eq!(items.clone().into_iter().skip(2).collect::>(), - cursor.iter().collect::>>().unwrap()); + assert_eq!( + items.clone().into_iter().skip(2).collect::>(), + cursor.iter().collect::>>().unwrap() + ); assert_eq!(items, cursor.iter_start().collect::>>().unwrap()); - assert_eq!(items.clone().into_iter().skip(1).collect::>(), - cursor.iter_from(b"key2").collect::>>().unwrap()); + assert_eq!( + items.clone().into_iter().skip(1).collect::>(), + cursor.iter_from(b"key2").collect::>>().unwrap() + ); - assert_eq!(items.clone().into_iter().skip(3).collect::>(), - cursor.iter_from(b"key4").collect::>>().unwrap()); + assert_eq!( + items.clone().into_iter().skip(3).collect::>(), + cursor.iter_from(b"key4").collect::>>().unwrap() + ); - assert_eq!(vec!().into_iter().collect::>(), - cursor.iter_from(b"key6").collect::>>().unwrap()); + assert_eq!( + vec!().into_iter().collect::>(), + cursor.iter_from(b"key6").collect::>>().unwrap() + ); } #[test] @@ -538,18 +589,20 @@ mod test { let env = Environment::new().open(dir.path()).unwrap(); let db = env.create_db(None, DatabaseFlags::DUP_SORT).unwrap(); - let items: Vec<(&[u8], &[u8])> = vec!((b"a", b"1"), - (b"a", b"2"), - (b"a", b"3"), - (b"b", b"1"), - (b"b", b"2"), - (b"b", b"3"), - (b"c", b"1"), - (b"c", b"2"), - (b"c", b"3"), - (b"e", b"1"), - (b"e", b"2"), - (b"e", b"3")); + let items: Vec<(&[u8], &[u8])> = vec![ + (b"a", b"1"), + (b"a", b"2"), + (b"a", b"3"), + (b"b", b"1"), + (b"b", b"2"), + (b"b", b"3"), + (b"c", b"1"), + (b"c", b"2"), + (b"c", b"3"), + (b"e", b"1"), + (b"e", b"2"), + (b"e", b"3"), + ]; { let mut txn = env.begin_rw_txn().unwrap(); @@ -564,26 +617,37 @@ mod test { assert_eq!(items, cursor.iter_dup().flat_map(|x| x).collect::>>().unwrap()); cursor.get(Some(b"b"), None, MDB_SET).unwrap(); - assert_eq!(items.clone().into_iter().skip(4).collect::>(), - cursor.iter_dup().flat_map(|x| x).collect::>>().unwrap()); - - assert_eq!(items, - cursor.iter_dup_start().flat_map(|x| x).collect::>>().unwrap()); - - assert_eq!(items.clone().into_iter().skip(3).collect::>(), - cursor.iter_dup_from(b"b").flat_map(|x| x).collect::>>().unwrap()); - - assert_eq!(items.clone().into_iter().skip(3).collect::>(), - cursor.iter_dup_from(b"ab").flat_map(|x| x).collect::>>().unwrap()); - - assert_eq!(items.clone().into_iter().skip(9).collect::>(), - cursor.iter_dup_from(b"d").flat_map(|x| x).collect::>>().unwrap()); - - assert_eq!(vec!().into_iter().collect::>(), - cursor.iter_dup_from(b"f").flat_map(|x| x).collect::>>().unwrap()); - - assert_eq!(items.clone().into_iter().skip(3).take(3).collect::>(), - cursor.iter_dup_of(b"b").collect::>>().unwrap()); + assert_eq!( + items.clone().into_iter().skip(4).collect::>(), + cursor.iter_dup().flat_map(|x| x).collect::>>().unwrap() + ); + + assert_eq!(items, cursor.iter_dup_start().flat_map(|x| x).collect::>>().unwrap()); + + assert_eq!( + items.clone().into_iter().skip(3).collect::>(), + cursor.iter_dup_from(b"b").flat_map(|x| x).collect::>>().unwrap() + ); + + assert_eq!( + items.clone().into_iter().skip(3).collect::>(), + cursor.iter_dup_from(b"ab").flat_map(|x| x).collect::>>().unwrap() + ); + + assert_eq!( + items.clone().into_iter().skip(9).collect::>(), + cursor.iter_dup_from(b"d").flat_map(|x| x).collect::>>().unwrap() + ); + + assert_eq!( + vec!().into_iter().collect::>(), + cursor.iter_dup_from(b"f").flat_map(|x| x).collect::>>().unwrap() + ); + + assert_eq!( + items.clone().into_iter().skip(3).take(3).collect::>(), + cursor.iter_dup_of(b"b").collect::>>().unwrap() + ); assert_eq!(0, cursor.iter_dup_of(b"foo").count()); } @@ -601,11 +665,9 @@ mod test { cursor.put(b"key2", b"val2", WriteFlags::empty()).unwrap(); cursor.put(b"key3", b"val3", WriteFlags::empty()).unwrap(); - assert_eq!((Some(&b"key3"[..]), &b"val3"[..]), - cursor.get(None, None, MDB_GET_CURRENT).unwrap()); + assert_eq!((Some(&b"key3"[..]), &b"val3"[..]), cursor.get(None, None, MDB_GET_CURRENT).unwrap()); cursor.del(WriteFlags::empty()).unwrap(); - assert_eq!((Some(&b"key2"[..]), &b"val2"[..]), - cursor.get(None, None, MDB_LAST).unwrap()); + assert_eq!((Some(&b"key2"[..]), &b"val2"[..]), cursor.get(None, None, MDB_LAST).unwrap()); } } diff --git a/src/database.rs b/src/database.rs index e7973ba..e04a4db 100644 --- a/src/database.rs +++ b/src/database.rs @@ -4,7 +4,10 @@ use std::ptr; use ffi; -use error::{Result, lmdb_result}; +use error::{ + lmdb_result, + Result, +}; /// A handle to an individual database in an environment. /// @@ -15,20 +18,22 @@ pub struct Database { } impl Database { - /// Opens a new database handle in the given transaction. /// /// Prefer using `Environment::open_db`, `Environment::create_db`, `TransactionExt::open_db`, /// or `RwTransaction::create_db`. - pub(crate) unsafe fn new(txn: *mut ffi::MDB_txn, - name: Option<&str>, - flags: c_uint) - -> Result { + pub(crate) unsafe fn new(txn: *mut ffi::MDB_txn, name: Option<&str>, flags: c_uint) -> Result { let c_name = name.map(|n| CString::new(n).unwrap()); - let name_ptr = if let Some(ref c_name) = c_name { c_name.as_ptr() } else { ptr::null() }; + let name_ptr = if let Some(ref c_name) = c_name { + c_name.as_ptr() + } else { + ptr::null() + }; let mut dbi: ffi::MDB_dbi = 0; lmdb_result(ffi::mdb_dbi_open(txn, name_ptr, flags, &mut dbi))?; - Ok(Database { dbi: dbi }) + Ok(Database { + dbi: dbi, + }) } pub(crate) fn freelist_db() -> Database { diff --git a/src/environment.rs b/src/environment.rs index b5b85e0..8696927 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -1,22 +1,44 @@ -use libc::{c_uint, size_t}; -use std::{fmt, ptr, result, mem}; +use libc::{ + c_uint, + size_t, +}; use std::ffi::CString; -#[cfg(unix)] -use std::os::unix::ffi::OsStrExt; #[cfg(windows)] use std::ffi::OsStr; +#[cfg(unix)] +use std::os::unix::ffi::OsStrExt; use std::path::Path; use std::sync::Mutex; +use std::{ + fmt, + mem, + ptr, + result, +}; use ffi; -use byteorder::{ByteOrder, NativeEndian}; +use byteorder::{ + ByteOrder, + NativeEndian, +}; use cursor::Cursor; -use error::{Error, Result, lmdb_result}; use database::Database; -use transaction::{RoTransaction, RwTransaction, Transaction}; -use flags::{DatabaseFlags, EnvironmentFlags}; +use error::{ + lmdb_result, + Error, + Result, +}; +use flags::{ + DatabaseFlags, + EnvironmentFlags, +}; +use transaction::{ + RoTransaction, + RwTransaction, + Transaction, +}; #[cfg(windows)] /// Adding a 'missing' trait from windows OsStrExt @@ -39,14 +61,13 @@ pub struct Environment { } impl Environment { - /// Creates a new builder for specifying options for opening an LMDB environment. pub fn new() -> EnvironmentBuilder { EnvironmentBuilder { flags: EnvironmentFlags::empty(), max_readers: None, max_dbs: None, - map_size: None + map_size: None, } } @@ -95,10 +116,7 @@ impl Environment { /// /// This function will fail with `Error::BadRslot` if called by a thread with an open /// transaction. - pub fn create_db<'env>(&'env self, - name: Option<&str>, - flags: DatabaseFlags) - -> Result { + pub fn create_db<'env>(&'env self, name: Option<&str>, flags: DatabaseFlags) -> Result { let mutex = self.dbi_open_mutex.lock(); let txn = self.begin_rw_txn()?; let db = unsafe { txn.create_db(name, flags)? }; @@ -137,7 +155,14 @@ impl Environment { /// the environment was opened with `MDB_NOSYNC` or in part `MDB_NOMETASYNC`. pub fn sync(&self, force: bool) -> Result<()> { unsafe { - lmdb_result(ffi::mdb_env_sync(self.env(), if force { 1 } else { 0 })) + lmdb_result(ffi::mdb_env_sync( + self.env(), + if force { + 1 + } else { + 0 + }, + )) } } @@ -239,9 +264,7 @@ impl Environment { /// with size 0 to update the environment. Otherwise, new transaction creation /// will fail with `Error::MapResized`. pub fn set_map_size(&self, size: size_t) -> Result<()> { - unsafe { - lmdb_result(ffi::mdb_env_set_mapsize(self.env(), size)) - } + unsafe { lmdb_result(ffi::mdb_env_set_mapsize(self.env(), size)) } } } @@ -253,9 +276,7 @@ pub struct Stat(ffi::MDB_stat); impl Stat { /// Create a new Stat with zero'd inner struct `ffi::MDB_stat`. pub(crate) fn new() -> Stat { - unsafe { - Stat(mem::zeroed()) - } + unsafe { Stat(mem::zeroed()) } } /// Returns a mut pointer to `ffi::MDB_stat`. @@ -368,7 +389,6 @@ pub struct EnvironmentBuilder { } impl EnvironmentBuilder { - /// Open an environment. /// /// On UNIX, the database files will be opened with 644 permissions. @@ -390,26 +410,27 @@ impl EnvironmentBuilder { unsafe { lmdb_try!(ffi::mdb_env_create(&mut env)); if let Some(max_readers) = self.max_readers { - lmdb_try_with_cleanup!(ffi::mdb_env_set_maxreaders(env, max_readers), - ffi::mdb_env_close(env)) + lmdb_try_with_cleanup!(ffi::mdb_env_set_maxreaders(env, max_readers), ffi::mdb_env_close(env)) } if let Some(max_dbs) = self.max_dbs { - lmdb_try_with_cleanup!(ffi::mdb_env_set_maxdbs(env, max_dbs), - ffi::mdb_env_close(env)) + lmdb_try_with_cleanup!(ffi::mdb_env_set_maxdbs(env, max_dbs), ffi::mdb_env_close(env)) } if let Some(map_size) = self.map_size { - lmdb_try_with_cleanup!(ffi::mdb_env_set_mapsize(env, map_size), - ffi::mdb_env_close(env)) + lmdb_try_with_cleanup!(ffi::mdb_env_set_mapsize(env, map_size), ffi::mdb_env_close(env)) } let path = match CString::new(path.as_os_str().as_bytes()) { Ok(path) => path, Err(..) => return Err(::Error::Invalid), }; - lmdb_try_with_cleanup!(ffi::mdb_env_open(env, path.as_ptr(), self.flags.bits(), mode), - ffi::mdb_env_close(env)); + lmdb_try_with_cleanup!( + ffi::mdb_env_open(env, path.as_ptr(), self.flags.bits(), mode), + ffi::mdb_env_close(env) + ); } - Ok(Environment { env: env, dbi_open_mutex: Mutex::new(()) }) - + Ok(Environment { + env: env, + dbi_open_mutex: Mutex::new(()), + }) } /// Sets the provided options in the environment. @@ -465,8 +486,11 @@ mod test { extern crate byteorder; + use self::byteorder::{ + ByteOrder, + LittleEndian, + }; use tempdir::TempDir; - use self::byteorder::{ByteOrder, LittleEndian}; use flags::*; @@ -477,34 +501,30 @@ mod test { let dir = TempDir::new("test").unwrap(); // opening non-existent env with read-only should fail - assert!(Environment::new().set_flags(EnvironmentFlags::READ_ONLY) - .open(dir.path()) - .is_err()); + assert!(Environment::new().set_flags(EnvironmentFlags::READ_ONLY).open(dir.path()).is_err()); // opening non-existent env should succeed assert!(Environment::new().open(dir.path()).is_ok()); // opening env with read-only should succeed - assert!(Environment::new().set_flags(EnvironmentFlags::READ_ONLY) - .open(dir.path()) - .is_ok()); + assert!(Environment::new().set_flags(EnvironmentFlags::READ_ONLY).open(dir.path()).is_ok()); } #[test] fn test_begin_txn() { let dir = TempDir::new("test").unwrap(); - { // writable environment + { + // writable environment let env = Environment::new().open(dir.path()).unwrap(); assert!(env.begin_rw_txn().is_ok()); assert!(env.begin_ro_txn().is_ok()); } - { // read-only environment - let env = Environment::new().set_flags(EnvironmentFlags::READ_ONLY) - .open(dir.path()) - .unwrap(); + { + // read-only environment + let env = Environment::new().set_flags(EnvironmentFlags::READ_ONLY).open(dir.path()).unwrap(); assert!(env.begin_rw_txn().is_err()); assert!(env.begin_ro_txn().is_ok()); @@ -514,9 +534,7 @@ mod test { #[test] fn test_open_db() { let dir = TempDir::new("test").unwrap(); - let env = Environment::new().set_max_dbs(1) - .open(dir.path()) - .unwrap(); + let env = Environment::new().set_max_dbs(1).open(dir.path()).unwrap(); assert!(env.open_db(None).is_ok()); assert!(env.open_db(Some("testdb")).is_err()); @@ -525,9 +543,7 @@ mod test { #[test] fn test_create_db() { let dir = TempDir::new("test").unwrap(); - let env = Environment::new().set_max_dbs(11) - .open(dir.path()) - .unwrap(); + let env = Environment::new().set_max_dbs(11).open(dir.path()).unwrap(); assert!(env.open_db(Some("testdb")).is_err()); assert!(env.create_db(Some("testdb"), DatabaseFlags::empty()).is_ok()); assert!(env.open_db(Some("testdb")).is_ok()) @@ -536,12 +552,12 @@ mod test { #[test] fn test_close_database() { let dir = TempDir::new("test").unwrap(); - let mut env = Environment::new().set_max_dbs(10) - .open(dir.path()) - .unwrap(); + let mut env = Environment::new().set_max_dbs(10).open(dir.path()).unwrap(); let db = env.create_db(Some("db"), DatabaseFlags::empty()).unwrap(); - unsafe { env.close_db(db); } + unsafe { + env.close_db(db); + } assert!(env.open_db(Some("db")).is_ok()); } @@ -551,10 +567,9 @@ mod test { { let env = Environment::new().open(dir.path()).unwrap(); assert!(env.sync(true).is_ok()); - } { - let env = Environment::new().set_flags(EnvironmentFlags::READ_ONLY) - .open(dir.path()) - .unwrap(); + } + { + let env = Environment::new().set_flags(EnvironmentFlags::READ_ONLY).open(dir.path()).unwrap(); assert!(env.sync(true).is_err()); } } @@ -598,10 +613,7 @@ mod test { fn test_info() { let map_size = 1024 * 1024; let dir = TempDir::new("test").unwrap(); - let env = Environment::new() - .set_map_size(map_size) - .open(dir.path()) - .unwrap(); + let env = Environment::new().set_map_size(map_size).open(dir.path()).unwrap(); let info = env.info().unwrap(); assert_eq!(info.map_size(), map_size); diff --git a/src/error.rs b/src/error.rs index 9225e85..eb26d5d 100644 --- a/src/error.rs +++ b/src/error.rs @@ -2,7 +2,11 @@ use libc::c_int; use std::error::Error as StdError; use std::ffi::CStr; use std::os::raw::c_char; -use std::{fmt, result, str}; +use std::{ + fmt, + result, + str, +}; use ffi; @@ -54,57 +58,56 @@ pub enum Error { } impl Error { - /// Converts a raw error code to an `Error`. pub fn from_err_code(err_code: c_int) -> Error { match err_code { - ffi::MDB_KEYEXIST => Error::KeyExist, - ffi::MDB_NOTFOUND => Error::NotFound, - ffi::MDB_PAGE_NOTFOUND => Error::PageNotFound, - ffi::MDB_CORRUPTED => Error::Corrupted, - ffi::MDB_PANIC => Error::Panic, + ffi::MDB_KEYEXIST => Error::KeyExist, + ffi::MDB_NOTFOUND => Error::NotFound, + ffi::MDB_PAGE_NOTFOUND => Error::PageNotFound, + ffi::MDB_CORRUPTED => Error::Corrupted, + ffi::MDB_PANIC => Error::Panic, ffi::MDB_VERSION_MISMATCH => Error::VersionMismatch, - ffi::MDB_INVALID => Error::Invalid, - ffi::MDB_MAP_FULL => Error::MapFull, - ffi::MDB_DBS_FULL => Error::DbsFull, - ffi::MDB_READERS_FULL => Error::ReadersFull, - ffi::MDB_TLS_FULL => Error::TlsFull, - ffi::MDB_TXN_FULL => Error::TxnFull, - ffi::MDB_CURSOR_FULL => Error::CursorFull, - ffi::MDB_PAGE_FULL => Error::PageFull, - ffi::MDB_MAP_RESIZED => Error::MapResized, - ffi::MDB_INCOMPATIBLE => Error::Incompatible, - ffi::MDB_BAD_RSLOT => Error::BadRslot, - ffi::MDB_BAD_TXN => Error::BadTxn, - ffi::MDB_BAD_VALSIZE => Error::BadValSize, - ffi::MDB_BAD_DBI => Error::BadDbi, - other => Error::Other(other), + ffi::MDB_INVALID => Error::Invalid, + ffi::MDB_MAP_FULL => Error::MapFull, + ffi::MDB_DBS_FULL => Error::DbsFull, + ffi::MDB_READERS_FULL => Error::ReadersFull, + ffi::MDB_TLS_FULL => Error::TlsFull, + ffi::MDB_TXN_FULL => Error::TxnFull, + ffi::MDB_CURSOR_FULL => Error::CursorFull, + ffi::MDB_PAGE_FULL => Error::PageFull, + ffi::MDB_MAP_RESIZED => Error::MapResized, + ffi::MDB_INCOMPATIBLE => Error::Incompatible, + ffi::MDB_BAD_RSLOT => Error::BadRslot, + ffi::MDB_BAD_TXN => Error::BadTxn, + ffi::MDB_BAD_VALSIZE => Error::BadValSize, + ffi::MDB_BAD_DBI => Error::BadDbi, + other => Error::Other(other), } } /// Converts an `Error` to the raw error code. pub fn to_err_code(&self) -> c_int { match *self { - Error::KeyExist => ffi::MDB_KEYEXIST, - Error::NotFound => ffi::MDB_NOTFOUND, - Error::PageNotFound => ffi::MDB_PAGE_NOTFOUND, - Error::Corrupted => ffi::MDB_CORRUPTED, - Error::Panic => ffi::MDB_PANIC, + Error::KeyExist => ffi::MDB_KEYEXIST, + Error::NotFound => ffi::MDB_NOTFOUND, + Error::PageNotFound => ffi::MDB_PAGE_NOTFOUND, + Error::Corrupted => ffi::MDB_CORRUPTED, + Error::Panic => ffi::MDB_PANIC, Error::VersionMismatch => ffi::MDB_VERSION_MISMATCH, - Error::Invalid => ffi::MDB_INVALID, - Error::MapFull => ffi::MDB_MAP_FULL, - Error::DbsFull => ffi::MDB_DBS_FULL, - Error::ReadersFull => ffi::MDB_READERS_FULL, - Error::TlsFull => ffi::MDB_TLS_FULL, - Error::TxnFull => ffi::MDB_TXN_FULL, - Error::CursorFull => ffi::MDB_CURSOR_FULL, - Error::PageFull => ffi::MDB_PAGE_FULL, - Error::MapResized => ffi::MDB_MAP_RESIZED, - Error::Incompatible => ffi::MDB_INCOMPATIBLE, - Error::BadRslot => ffi::MDB_BAD_RSLOT, - Error::BadTxn => ffi::MDB_BAD_TXN, - Error::BadValSize => ffi::MDB_BAD_VALSIZE, - Error::BadDbi => ffi::MDB_BAD_DBI, + Error::Invalid => ffi::MDB_INVALID, + Error::MapFull => ffi::MDB_MAP_FULL, + Error::DbsFull => ffi::MDB_DBS_FULL, + Error::ReadersFull => ffi::MDB_READERS_FULL, + Error::TlsFull => ffi::MDB_TLS_FULL, + Error::TxnFull => ffi::MDB_TXN_FULL, + Error::CursorFull => ffi::MDB_CURSOR_FULL, + Error::PageFull => ffi::MDB_PAGE_FULL, + Error::MapResized => ffi::MDB_MAP_RESIZED, + Error::Incompatible => ffi::MDB_INCOMPATIBLE, + Error::BadRslot => ffi::MDB_BAD_RSLOT, + Error::BadTxn => ffi::MDB_BAD_TXN, + Error::BadValSize => ffi::MDB_BAD_VALSIZE, + Error::BadDbi => ffi::MDB_BAD_DBI, Error::Other(err_code) => err_code, } } @@ -146,9 +149,7 @@ mod test { #[test] fn test_description() { - assert_eq!("Permission denied", - Error::from_err_code(13).description()); - assert_eq!("MDB_NOTFOUND: No matching key/data pair found", - Error::NotFound.description()); + assert_eq!("Permission denied", Error::from_err_code(13).description()); + assert_eq!("MDB_NOTFOUND: No matching key/data pair found", Error::NotFound.description()); } } diff --git a/src/lib.rs b/src/lib.rs index 4664216..13deac8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,19 +4,21 @@ #![deny(missing_docs)] #![doc(html_root_url = "https://docs.rs/lmdb-rkv/0.12.0")] +extern crate byteorder; extern crate libc; extern crate lmdb_rkv_sys as ffi; -extern crate byteorder; -#[cfg(test)] extern crate tempdir; -#[macro_use] extern crate bitflags; +#[cfg(test)] +extern crate tempdir; +#[macro_use] +extern crate bitflags; pub use cursor::{ Cursor, - RoCursor, - RwCursor, Iter, IterDup, + RoCursor, + RwCursor, }; pub use database::Database; pub use environment::{ @@ -25,7 +27,10 @@ pub use environment::{ Info, Stat, }; -pub use error::{Error, Result}; +pub use error::{ + Error, + Result, +}; pub use flags::*; pub use transaction::{ InactiveTransaction, @@ -35,37 +40,40 @@ pub use transaction::{ }; macro_rules! lmdb_try { - ($expr:expr) => ({ + ($expr:expr) => {{ match $expr { ::ffi::MDB_SUCCESS => (), err_code => return Err(::Error::from_err_code(err_code)), } - }) + }}; } macro_rules! lmdb_try_with_cleanup { - ($expr:expr, $cleanup:expr) => ({ + ($expr:expr, $cleanup:expr) => {{ match $expr { ::ffi::MDB_SUCCESS => (), err_code => { let _ = $cleanup; - return Err(::Error::from_err_code(err_code)) + return Err(::Error::from_err_code(err_code)); }, } - }) + }}; } -mod flags; mod cursor; mod database; mod environment; mod error; +mod flags; mod transaction; #[cfg(test)] mod test_utils { - use byteorder::{ByteOrder, LittleEndian}; + use byteorder::{ + ByteOrder, + LittleEndian, + }; use tempdir::TempDir; use super::*; @@ -91,10 +99,7 @@ mod test_utils { let mut value = [0u8; 8]; LittleEndian::write_u64(&mut value, height); let mut tx = env.begin_rw_txn().expect("begin_rw_txn"); - tx.put(index, - &HEIGHT_KEY, - &value, - WriteFlags::empty()).expect("tx.put"); + tx.put(index, &HEIGHT_KEY, &value, WriteFlags::empty()).expect("tx.put"); tx.commit().expect("tx.commit") } } diff --git a/src/transaction.rs b/src/transaction.rs index e6a12c8..aa633b0 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -1,20 +1,43 @@ -use libc::{c_uint, c_void, size_t}; -use std::{fmt, mem, ptr, result, slice}; -use std::marker::PhantomData ; +use libc::{ + c_uint, + c_void, + size_t, +}; +use std::marker::PhantomData; +use std::{ + fmt, + mem, + ptr, + result, + slice, +}; use ffi; -use cursor::{RoCursor, RwCursor}; -use environment::{Environment, Stat}; +use cursor::{ + RoCursor, + RwCursor, +}; use database::Database; -use error::{Error, Result, lmdb_result}; -use flags::{DatabaseFlags, EnvironmentFlags, WriteFlags}; +use environment::{ + Environment, + Stat, +}; +use error::{ + lmdb_result, + Error, + Result, +}; +use flags::{ + DatabaseFlags, + EnvironmentFlags, + WriteFlags, +}; /// An LMDB transaction. /// /// All database operations require a transaction. -pub trait Transaction : Sized { - +pub trait Transaction: Sized { /// Returns a raw pointer to the underlying LMDB transaction. /// /// The caller **must** ensure that the pointer is not used after the @@ -68,22 +91,22 @@ pub trait Transaction : Sized { /// returned. Retrieval of other items requires the use of /// `Transaction::cursor_get`. If the item is not in the database, then /// `Error::NotFound` will be returned. - fn get<'txn, K>(&'txn self, - database: Database, - key: &K) - -> Result<&'txn [u8]> - where K: AsRef<[u8]> { + fn get<'txn, K>(&'txn self, database: Database, key: &K) -> Result<&'txn [u8]> + where + K: AsRef<[u8]>, + { let key = key.as_ref(); - let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t, - mv_data: key.as_ptr() as *mut c_void }; - let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: 0, - mv_data: ptr::null_mut() }; + let mut key_val: ffi::MDB_val = ffi::MDB_val { + mv_size: key.len() as size_t, + mv_data: key.as_ptr() as *mut c_void, + }; + let mut data_val: ffi::MDB_val = ffi::MDB_val { + mv_size: 0, + mv_data: ptr::null_mut(), + }; unsafe { match ffi::mdb_get(self.txn(), database.dbi(), &mut key_val, &mut data_val) { - ffi::MDB_SUCCESS => { - Ok(slice::from_raw_parts(data_val.mv_data as *const u8, - data_val.mv_size as usize)) - }, + ffi::MDB_SUCCESS => Ok(slice::from_raw_parts(data_val.mv_data as *const u8, data_val.mv_size as usize)), err_code => Err(Error::from_err_code(err_code)), } } @@ -119,27 +142,29 @@ pub struct RoTransaction<'env> { _marker: PhantomData<&'env ()>, } -impl <'env> fmt::Debug for RoTransaction<'env> { +impl<'env> fmt::Debug for RoTransaction<'env> { fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { f.debug_struct("RoTransaction").finish() } } -impl <'env> Drop for RoTransaction<'env> { +impl<'env> Drop for RoTransaction<'env> { fn drop(&mut self) { unsafe { ffi::mdb_txn_abort(self.txn) } } } -impl <'env> RoTransaction<'env> { - +impl<'env> RoTransaction<'env> { /// Creates a new read-only transaction in the given environment. Prefer /// using `Environment::begin_ro_txn`. pub(crate) fn new(env: &'env Environment) -> Result> { let mut txn: *mut ffi::MDB_txn = ptr::null_mut(); unsafe { lmdb_result(ffi::mdb_txn_begin(env.env(), ptr::null_mut(), ffi::MDB_RDONLY, &mut txn))?; - Ok(RoTransaction { txn: txn, _marker: PhantomData }) + Ok(RoTransaction { + txn: txn, + _marker: PhantomData, + }) } } @@ -161,11 +186,14 @@ impl <'env> RoTransaction<'env> { mem::forget(self); ffi::mdb_txn_reset(txn) }; - InactiveTransaction { txn: txn, _marker: PhantomData } + InactiveTransaction { + txn: txn, + _marker: PhantomData, + } } } -impl <'env> Transaction for RoTransaction<'env> { +impl<'env> Transaction for RoTransaction<'env> { fn txn(&self) -> *mut ffi::MDB_txn { self.txn } @@ -177,20 +205,19 @@ pub struct InactiveTransaction<'env> { _marker: PhantomData<&'env ()>, } -impl <'env> fmt::Debug for InactiveTransaction<'env> { +impl<'env> fmt::Debug for InactiveTransaction<'env> { fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { f.debug_struct("InactiveTransaction").finish() } } -impl <'env> Drop for InactiveTransaction<'env> { +impl<'env> Drop for InactiveTransaction<'env> { fn drop(&mut self) { unsafe { ffi::mdb_txn_abort(self.txn) } } } -impl <'env> InactiveTransaction<'env> { - +impl<'env> InactiveTransaction<'env> { /// Renews the inactive transaction, returning an active read-only /// transaction. /// @@ -202,7 +229,10 @@ impl <'env> InactiveTransaction<'env> { mem::forget(self); lmdb_result(ffi::mdb_txn_renew(txn))? }; - Ok(RoTransaction { txn: txn, _marker: PhantomData }) + Ok(RoTransaction { + txn: txn, + _marker: PhantomData, + }) } } @@ -212,30 +242,29 @@ pub struct RwTransaction<'env> { _marker: PhantomData<&'env ()>, } -impl <'env> fmt::Debug for RwTransaction<'env> { +impl<'env> fmt::Debug for RwTransaction<'env> { fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { f.debug_struct("RwTransaction").finish() } } -impl <'env> Drop for RwTransaction<'env> { +impl<'env> Drop for RwTransaction<'env> { fn drop(&mut self) { unsafe { ffi::mdb_txn_abort(self.txn) } } } -impl <'env> RwTransaction<'env> { - +impl<'env> RwTransaction<'env> { /// Creates a new read-write transaction in the given environment. Prefer /// using `Environment::begin_ro_txn`. pub(crate) fn new(env: &'env Environment) -> Result> { let mut txn: *mut ffi::MDB_txn = ptr::null_mut(); unsafe { - lmdb_result(ffi::mdb_txn_begin(env.env(), - ptr::null_mut(), - EnvironmentFlags::empty().bits(), - &mut txn))?; - Ok(RwTransaction { txn: txn, _marker: PhantomData }) + lmdb_result(ffi::mdb_txn_begin(env.env(), ptr::null_mut(), EnvironmentFlags::empty().bits(), &mut txn))?; + Ok(RwTransaction { + txn: txn, + _marker: PhantomData, + }) } } @@ -271,51 +300,55 @@ impl <'env> RwTransaction<'env> { /// behavior is to enter the new key/data pair, replacing any previously /// existing key if duplicates are disallowed, or adding a duplicate data /// item if duplicates are allowed (`DatabaseFlags::DUP_SORT`). - pub fn put(&mut self, - database: Database, - key: &K, - data: &D, - flags: WriteFlags) - -> Result<()> - where K: AsRef<[u8]>, D: AsRef<[u8]> { + pub fn put(&mut self, database: Database, key: &K, data: &D, flags: WriteFlags) -> Result<()> + where + K: AsRef<[u8]>, + D: AsRef<[u8]>, + { let key = key.as_ref(); let data = data.as_ref(); - let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t, - mv_data: key.as_ptr() as *mut c_void }; - let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: data.len() as size_t, - mv_data: data.as_ptr() as *mut c_void }; - unsafe { - lmdb_result(ffi::mdb_put(self.txn(), - database.dbi(), - &mut key_val, - &mut data_val, - flags.bits())) - } + let mut key_val: ffi::MDB_val = ffi::MDB_val { + mv_size: key.len() as size_t, + mv_data: key.as_ptr() as *mut c_void, + }; + let mut data_val: ffi::MDB_val = ffi::MDB_val { + mv_size: data.len() as size_t, + mv_data: data.as_ptr() as *mut c_void, + }; + unsafe { lmdb_result(ffi::mdb_put(self.txn(), database.dbi(), &mut key_val, &mut data_val, flags.bits())) } } /// Returns a buffer which can be used to write a value into the item at the /// given key and with the given length. The buffer must be completely /// filled by the caller. - pub fn reserve<'txn, K>(&'txn mut self, - database: Database, - key: &K, - len: size_t, - flags: WriteFlags) - -> Result<&'txn mut [u8]> - where K: AsRef<[u8]> { + pub fn reserve<'txn, K>( + &'txn mut self, + database: Database, + key: &K, + len: size_t, + flags: WriteFlags, + ) -> Result<&'txn mut [u8]> + where + K: AsRef<[u8]>, + { let key = key.as_ref(); - let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t, - mv_data: key.as_ptr() as *mut c_void }; - let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: len, - mv_data: ptr::null_mut::() }; + let mut key_val: ffi::MDB_val = ffi::MDB_val { + mv_size: key.len() as size_t, + mv_data: key.as_ptr() as *mut c_void, + }; + let mut data_val: ffi::MDB_val = ffi::MDB_val { + mv_size: len, + mv_data: ptr::null_mut::(), + }; unsafe { - lmdb_result(ffi::mdb_put(self.txn(), - database.dbi(), - &mut key_val, - &mut data_val, - flags.bits() | ffi::MDB_RESERVE))?; - Ok(slice::from_raw_parts_mut(data_val.mv_data as *mut u8, - data_val.mv_size as usize)) + lmdb_result(ffi::mdb_put( + self.txn(), + database.dbi(), + &mut key_val, + &mut data_val, + flags.bits() | ffi::MDB_RESERVE, + ))?; + Ok(slice::from_raw_parts_mut(data_val.mv_data as *mut u8, data_val.mv_size as usize)) } } @@ -329,34 +362,24 @@ impl <'env> RwTransaction<'env> { /// `Some` only the matching data item will be deleted. This function will /// return `Error::NotFound` if the specified key/data pair is not in the /// database. - pub fn del(&mut self, - database: Database, - key: &K, - data: Option<&[u8]>) - -> Result<()> - where K: AsRef<[u8]> { + pub fn del(&mut self, database: Database, key: &K, data: Option<&[u8]>) -> Result<()> + where + K: AsRef<[u8]>, + { let key = key.as_ref(); - let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t, - mv_data: key.as_ptr() as *mut c_void }; - let data_val: Option = - data.map(|data| ffi::MDB_val { mv_size: data.len() as size_t, - mv_data: data.as_ptr() as *mut c_void }); + let mut key_val: ffi::MDB_val = ffi::MDB_val { + mv_size: key.len() as size_t, + mv_data: key.as_ptr() as *mut c_void, + }; + let data_val: Option = data.map(|data| ffi::MDB_val { + mv_size: data.len() as size_t, + mv_data: data.as_ptr() as *mut c_void, + }); if let Some(mut d) = data_val { - unsafe { - lmdb_result(ffi::mdb_del(self.txn(), - database.dbi(), - &mut key_val, - &mut d)) - - } + unsafe { lmdb_result(ffi::mdb_del(self.txn(), database.dbi(), &mut key_val, &mut d)) } } else { - unsafe { - lmdb_result(ffi::mdb_del(self.txn(), - database.dbi(), - &mut key_val, - ptr::null_mut())) - } + unsafe { lmdb_result(ffi::mdb_del(self.txn(), database.dbi(), &mut key_val, ptr::null_mut())) } } } @@ -382,11 +405,14 @@ impl <'env> RwTransaction<'env> { let env: *mut ffi::MDB_env = ffi::mdb_txn_env(self.txn()); ffi::mdb_txn_begin(env, self.txn(), 0, &mut nested); } - Ok(RwTransaction { txn: nested, _marker: PhantomData }) + Ok(RwTransaction { + txn: nested, + _marker: PhantomData, + }) } } -impl <'env> Transaction for RwTransaction<'env> { +impl<'env> Transaction for RwTransaction<'env> { fn txn(&self) -> *mut ffi::MDB_txn { self.txn } @@ -396,16 +422,21 @@ impl <'env> Transaction for RwTransaction<'env> { mod test { use std::io::Write; - use std::sync::{Arc, Barrier}; - use std::thread::{self, JoinHandle}; + use std::sync::{ + Arc, + Barrier, + }; + use std::thread::{ + self, + JoinHandle, + }; use tempdir::TempDir; - use environment::*; - use error::*; - use flags::*; use super::*; use cursor::Cursor; + use error::*; + use flags::*; #[test] fn test_put_get_del() { @@ -451,9 +482,8 @@ mod test { { let mut cur = txn.open_ro_cursor(db).unwrap(); let iter = cur.iter_dup_of(b"key1"); - let vals = iter.map(|x| x.unwrap()).map(|(_,x)| x).collect::>(); + let vals = iter.map(|x| x.unwrap()).map(|(_, x)| x).collect::>(); assert_eq!(vals, vec![b"val1", b"val2", b"val3"]); - } txn.commit().unwrap(); @@ -466,7 +496,7 @@ mod test { { let mut cur = txn.open_ro_cursor(db).unwrap(); let iter = cur.iter_dup_of(b"key1"); - let vals = iter.map(|x| x.unwrap()).map(|(_,x)| x).collect::>(); + let vals = iter.map(|x| x.unwrap()).map(|(_, x)| x).collect::>(); assert_eq!(vals, vec![b"val1", b"val3"]); let iter = cur.iter_dup_of(b"key2"); @@ -475,7 +505,6 @@ mod test { txn.commit().unwrap(); } - #[test] fn test_reserve() { let dir = TempDir::new("test").unwrap(); @@ -557,12 +586,10 @@ mod test { assert_eq!(txn.get(db, b"key"), Err(Error::NotFound)); } - #[test] fn test_drop_db() { let dir = TempDir::new("test").unwrap(); - let env = Environment::new().set_max_dbs(2) - .open(dir.path()).unwrap(); + let env = Environment::new().set_max_dbs(2).open(dir.path()).unwrap(); let db = env.create_db(Some("test"), DatabaseFlags::empty()).unwrap(); { @@ -572,7 +599,9 @@ mod test { } { let mut txn = env.begin_rw_txn().unwrap(); - unsafe { txn.drop_db(db).unwrap(); } + unsafe { + txn.drop_db(db).unwrap(); + } txn.commit().unwrap(); } @@ -595,7 +624,7 @@ mod test { let reader_env = env.clone(); let reader_barrier = barrier.clone(); - threads.push(thread::spawn(move|| { + threads.push(thread::spawn(move || { let db = reader_env.open_db(None).unwrap(); { let txn = reader_env.begin_ro_txn().unwrap(); @@ -635,14 +664,10 @@ mod test { for i in 0..n { let writer_env = env.clone(); - threads.push(thread::spawn(move|| { + threads.push(thread::spawn(move || { let db = writer_env.open_db(None).unwrap(); let mut txn = writer_env.begin_rw_txn().unwrap(); - txn.put(db, - &format!("{}{}", key, i), - &format!("{}{}", val, i), - WriteFlags::empty()) - .unwrap(); + txn.put(db, &format!("{}{}", key, i), &format!("{}{}", val, i), WriteFlags::empty()).unwrap(); txn.commit().is_ok() })); } @@ -652,8 +677,7 @@ mod test { let txn = env.begin_ro_txn().unwrap(); for i in 0..n { - assert_eq!(format!("{}{}", val, i).as_bytes(), - txn.get(db, &format!("{}{}", key, i)).unwrap()); + assert_eq!(format!("{}{}", val, i).as_bytes(), txn.get(db, &format!("{}{}", key, i)).unwrap()); } }