Drop Lmdb prefix on Error and Result

without.crypto
Dan Burkert 10 years ago
parent 21df9369dc
commit 79f36662df
  1. 1
      .travis.yml
  2. 6
      README.md
  3. 20
      src/cursor.rs
  4. 4
      src/database.rs
  5. 22
      src/environment.rs
  6. 110
      src/error.rs
  7. 13
      src/lib.rs
  8. 59
      src/transaction.rs

@ -3,7 +3,6 @@ env:
global: global:
- secure: LhiHXBKaxsubX45eMukb39IDKaM0mdMzE8Ow4DCnq/yFTZn22ju/H3nMawk0X74gCMXsrADErcBke/7+mHV5GgToqtKjr8RaZDwAmZtzDgdrvJlqy+w59WbvJKuPXYGN0dPiVSkt/fFGf7qGFjLj0DiGZHw05XmBSq+90Qn3Iqw= - secure: LhiHXBKaxsubX45eMukb39IDKaM0mdMzE8Ow4DCnq/yFTZn22ju/H3nMawk0X74gCMXsrADErcBke/7+mHV5GgToqtKjr8RaZDwAmZtzDgdrvJlqy+w59WbvJKuPXYGN0dPiVSkt/fFGf7qGFjLj0DiGZHw05XmBSq+90Qn3Iqw=
script: script:
- export LD_PRELOAD=/usr/lib/llvm-${LLVM_VERSION}/lib/libclang.so
- cargo build -v - cargo build -v
- cargo test -v - cargo test -v
- cargo doc - cargo doc

@ -6,10 +6,8 @@
# lmdb-rs # lmdb-rs
Safe Rust bindings for the [Symas Lightning Memory-Mapped Database (LMDB)](http://symas.com/mdb/). Idiomatic and safe APIs for interacting with the
[Symas Lightning Memory-Mapped Database (LMDB)](http://symas.com/mdb/).
Provides the minimal amount of abstraction necessary to interact with LMDB safely in Rust. In
general, the API is very similar to the LMDB [C-API](http://symas.com/mdb/doc/).
## Building from Source ## Building from Source

@ -3,7 +3,7 @@ use std::{mem, ptr, raw};
use std::marker::{PhantomData, PhantomFn}; use std::marker::{PhantomData, PhantomFn};
use database::Database; use database::Database;
use error::{LmdbResult, lmdb_result, LmdbError}; use error::{Error, Result, lmdb_result};
use ffi; use ffi;
use flags::WriteFlags; use flags::WriteFlags;
use transaction::Transaction; use transaction::Transaction;
@ -25,7 +25,7 @@ pub trait CursorExt<'txn> : Cursor<'txn> + Sized {
key: Option<&[u8]>, key: Option<&[u8]>,
data: Option<&[u8]>, data: Option<&[u8]>,
op: c_uint) op: c_uint)
-> LmdbResult<(Option<&'txn [u8]>, &'txn [u8])> { -> Result<(Option<&'txn [u8]>, &'txn [u8])> {
unsafe { unsafe {
let mut key_val = slice_to_val(key); let mut key_val = slice_to_val(key);
let mut data_val = slice_to_val(data); let mut data_val = slice_to_val(data);
@ -90,7 +90,7 @@ pub trait CursorExt<'txn> : Cursor<'txn> + Sized {
} }
/// Iterate over the duplicates of the item in the database with the given key. /// Iterate over the duplicates of the item in the database with the given key.
fn iter_dup_of(&mut self, key: &[u8]) -> LmdbResult<Iter<'txn>> { fn iter_dup_of(&mut self, key: &[u8]) -> Result<Iter<'txn>> {
try!(self.get(Some(key), None, ffi::MDB_SET)); try!(self.get(Some(key), None, ffi::MDB_SET));
Ok(Iter::new(self.cursor(), ffi::MDB_GET_CURRENT, ffi::MDB_NEXT_DUP)) Ok(Iter::new(self.cursor(), ffi::MDB_GET_CURRENT, ffi::MDB_NEXT_DUP))
} }
@ -125,7 +125,7 @@ impl <'txn> RoCursor<'txn> {
/// Creates a new read-only cursor in the given database and transaction. Prefer using /// Creates a new read-only cursor in the given database and transaction. Prefer using
/// `Transaction::open_cursor`. /// `Transaction::open_cursor`.
#[doc(hidden)] #[doc(hidden)]
pub fn new(txn: &'txn Transaction, db: Database) -> LmdbResult<RoCursor<'txn>> { pub fn new(txn: &'txn Transaction, db: Database) -> Result<RoCursor<'txn>> {
let mut cursor: *mut ffi::MDB_cursor = ptr::null_mut(); let mut cursor: *mut ffi::MDB_cursor = ptr::null_mut();
unsafe { try!(lmdb_result(ffi::mdb_cursor_open(txn.txn(), db.dbi(), &mut cursor))); } unsafe { try!(lmdb_result(ffi::mdb_cursor_open(txn.txn(), db.dbi(), &mut cursor))); }
Ok(RoCursor { Ok(RoCursor {
@ -162,7 +162,7 @@ impl <'txn> RwCursor<'txn> {
/// Creates a new read-only cursor in the given database and transaction. Prefer using /// Creates a new read-only cursor in the given database and transaction. Prefer using
/// `RwTransaction::open_rw_cursor`. /// `RwTransaction::open_rw_cursor`.
#[doc(hidden)] #[doc(hidden)]
pub fn new(txn: &'txn Transaction, db: Database) -> LmdbResult<RwCursor<'txn>> { pub fn new(txn: &'txn Transaction, db: Database) -> Result<RwCursor<'txn>> {
let mut cursor: *mut ffi::MDB_cursor = ptr::null_mut(); let mut cursor: *mut ffi::MDB_cursor = ptr::null_mut();
unsafe { try!(lmdb_result(ffi::mdb_cursor_open(txn.txn(), db.dbi(), &mut cursor))); } unsafe { try!(lmdb_result(ffi::mdb_cursor_open(txn.txn(), db.dbi(), &mut cursor))); }
Ok(RwCursor { cursor: cursor, _marker: PhantomData }) Ok(RwCursor { cursor: cursor, _marker: PhantomData })
@ -170,11 +170,7 @@ impl <'txn> RwCursor<'txn> {
/// Puts a key/data pair into the database. The cursor will be positioned at the new data item, /// Puts a key/data pair into the database. The cursor will be positioned at the new data item,
/// or on failure usually near it. /// or on failure usually near it.
pub fn put(&mut self, pub fn put(&mut self, key: &[u8], data: &[u8], flags: WriteFlags) -> Result<()> {
key: &[u8],
data: &[u8],
flags: WriteFlags)
-> LmdbResult<()> {
let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t, 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 }; 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, let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: data.len() as size_t,
@ -193,7 +189,7 @@ impl <'txn> RwCursor<'txn> {
/// ///
/// `WriteFlags::NO_DUP_DATA` may be used to delete all data items for the current key, if the /// `WriteFlags::NO_DUP_DATA` may be used to delete all data items for the current key, if the
/// database was opened with `DatabaseFlags::DUP_SORT`. /// database was opened with `DatabaseFlags::DUP_SORT`.
pub fn del(&mut self, flags: WriteFlags) -> LmdbResult<()> { pub fn del(&mut self, flags: WriteFlags) -> Result<()> {
unsafe { lmdb_result(ffi::mdb_cursor_del(self.cursor(), flags.bits())) } unsafe { lmdb_result(ffi::mdb_cursor_del(self.cursor(), flags.bits())) }
} }
} }
@ -250,7 +246,7 @@ impl <'txn> Iterator for Iter<'txn> {
// and MDB_EINVAL (and we shouldn't be passing in invalid parameters). // and MDB_EINVAL (and we shouldn't be passing in invalid parameters).
// TODO: validate that these are the only failures possible. // TODO: validate that these are the only failures possible.
debug_assert!(err_code == ffi::MDB_NOTFOUND, debug_assert!(err_code == ffi::MDB_NOTFOUND,
"Unexpected LMDB error {:?}.", LmdbError::from_err_code(err_code)); "Unexpected LMDB error {:?}.", Error::from_err_code(err_code));
None None
} }
} }

@ -4,7 +4,7 @@ use std::ptr;
use ffi; use ffi;
use error::{LmdbResult, lmdb_result}; use error::{Result, lmdb_result};
/// A handle to an individual database in an environment. /// A handle to an individual database in an environment.
/// ///
@ -24,7 +24,7 @@ impl Database {
pub unsafe fn new(txn: *mut ffi::MDB_txn, pub unsafe fn new(txn: *mut ffi::MDB_txn,
name: Option<&str>, name: Option<&str>,
flags: c_uint) flags: c_uint)
-> LmdbResult<Database> { -> Result<Database> {
let c_name = name.map(|n| CString::new(n).unwrap()); 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; let mut dbi: ffi::MDB_dbi = 0;

@ -8,7 +8,7 @@ use std::sync::Mutex;
use ffi; use ffi;
use error::{LmdbResult, lmdb_result}; use error::{Result, lmdb_result};
use database::Database; use database::Database;
use transaction::{RoTransaction, RwTransaction, Transaction, TransactionExt}; use transaction::{RoTransaction, RwTransaction, Transaction, TransactionExt};
use flags::{DatabaseFlags, EnvironmentFlags}; use flags::{DatabaseFlags, EnvironmentFlags};
@ -51,11 +51,11 @@ impl Environment {
/// ///
/// The returned database handle may be shared among any transaction in the environment. /// The returned database handle may be shared among any transaction in the environment.
/// ///
/// This function will fail with `LmdbError::BadRslot` if called by a thread which has an ongoing /// This function will fail with `Error::BadRslot` if called by a thread which has an ongoing
/// transaction. /// transaction.
/// ///
/// The database name may not contain the null character. /// The database name may not contain the null character.
pub fn open_db<'env>(&'env self, name: Option<&str>) -> LmdbResult<Database> { pub fn open_db<'env>(&'env self, name: Option<&str>) -> Result<Database> {
let mutex = self.dbi_open_mutex.lock(); let mutex = self.dbi_open_mutex.lock();
let txn = try!(self.begin_ro_txn()); let txn = try!(self.begin_ro_txn());
let db = unsafe { try!(txn.open_db(name)) }; let db = unsafe { try!(txn.open_db(name)) };
@ -76,12 +76,12 @@ impl Environment {
/// ///
/// The returned database handle may be shared among any transaction in the environment. /// The returned database handle may be shared among any transaction in the environment.
/// ///
/// This function will fail with `LmdbError::BadRslot` if called by a thread with an open /// This function will fail with `Error::BadRslot` if called by a thread with an open
/// transaction. /// transaction.
pub fn create_db<'env>(&'env self, pub fn create_db<'env>(&'env self,
name: Option<&str>, name: Option<&str>,
flags: DatabaseFlags) flags: DatabaseFlags)
-> LmdbResult<Database> { -> Result<Database> {
let mutex = self.dbi_open_mutex.lock(); let mutex = self.dbi_open_mutex.lock();
let txn = try!(self.begin_rw_txn()); let txn = try!(self.begin_rw_txn());
let db = unsafe { try!(txn.create_db(name, flags)) }; let db = unsafe { try!(txn.create_db(name, flags)) };
@ -90,7 +90,7 @@ impl Environment {
Ok(db) Ok(db)
} }
pub fn get_db_flags<'env>(&'env self, db: Database) -> LmdbResult<DatabaseFlags> { pub fn get_db_flags<'env>(&'env self, db: Database) -> Result<DatabaseFlags> {
let txn = try!(self.begin_ro_txn()); let txn = try!(self.begin_ro_txn());
let mut flags: c_uint = 0; let mut flags: c_uint = 0;
unsafe { unsafe {
@ -100,13 +100,13 @@ impl Environment {
} }
/// Create a read-only transaction for use with the environment. /// Create a read-only transaction for use with the environment.
pub fn begin_ro_txn<'env>(&'env self) -> LmdbResult<RoTransaction<'env>> { pub fn begin_ro_txn<'env>(&'env self) -> Result<RoTransaction<'env>> {
RoTransaction::new(self) RoTransaction::new(self)
} }
/// Create a read-write transaction for use with the environment. This method will block while /// Create a read-write transaction for use with the environment. This method will block while
/// there are any other read-write transactions open on the environment. /// there are any other read-write transactions open on the environment.
pub fn begin_rw_txn<'env>(&'env self) -> LmdbResult<RwTransaction<'env>> { pub fn begin_rw_txn<'env>(&'env self) -> Result<RwTransaction<'env>> {
RwTransaction::new(self) RwTransaction::new(self)
} }
@ -115,7 +115,7 @@ impl Environment {
/// Data is always written to disk when `Transaction::commit` is called, but the operating /// Data is always written to disk when `Transaction::commit` is called, but the operating
/// system may keep it buffered. LMDB always flushes the OS buffers upon commit as well, unless /// system may keep it buffered. LMDB always flushes the OS buffers upon commit as well, unless
/// the environment was opened with `MDB_NOSYNC` or in part `MDB_NOMETASYNC`. /// the environment was opened with `MDB_NOSYNC` or in part `MDB_NOMETASYNC`.
pub fn sync(&self, force: bool) -> LmdbResult<()> { pub fn sync(&self, force: bool) -> Result<()> {
unsafe { 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 }))
} }
@ -133,7 +133,7 @@ impl Environment {
/// only if no other threads are going to reference the database handle or one of its cursors /// only if no other threads are going to reference the database handle or one of its cursors
/// any further. Do not close a handle if an existing transaction has modified its database. /// any further. Do not close a handle if an existing transaction has modified its database.
/// Doing so can cause misbehavior from database corruption to errors like /// Doing so can cause misbehavior from database corruption to errors like
/// `LmdbError::BadValSize` (since the DB name is gone). /// `Error::BadValSize` (since the DB name is gone).
pub unsafe fn close_db(&mut self, db: Database) { pub unsafe fn close_db(&mut self, db: Database) {
ffi::mdb_dbi_close(self.env, db.dbi()); ffi::mdb_dbi_close(self.env, db.dbi());
} }
@ -166,7 +166,7 @@ impl EnvironmentBuilder {
/// Open an environment. /// Open an environment.
/// ///
/// The path may not contain the null character. /// The path may not contain the null character.
pub fn open(&self, path: &Path, mode: FilePermission) -> LmdbResult<Environment> { pub fn open(&self, path: &Path, mode: FilePermission) -> Result<Environment> {
let mut env: *mut ffi::MDB_env = ptr::null_mut(); let mut env: *mut ffi::MDB_env = ptr::null_mut();
unsafe { unsafe {
lmdb_try!(ffi::mdb_env_create(&mut env)); lmdb_try!(ffi::mdb_env_create(&mut env));

@ -1,12 +1,12 @@
use libc::c_int; use libc::c_int;
use std::error::Error; use std::error::Error as StdError;
use std::ffi::CStr; use std::ffi::CStr;
use std::{fmt, str}; use std::{fmt, result, str};
use ffi; use ffi;
#[derive(Debug, Eq, PartialEq, Copy, Clone)] #[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum LmdbError { pub enum Error {
/// key/data pair already exists. /// key/data pair already exists.
KeyExist, KeyExist,
/// key/data pair not found (EOF). /// key/data pair not found (EOF).
@ -51,67 +51,67 @@ pub enum LmdbError {
Other(c_int), Other(c_int),
} }
impl LmdbError { impl Error {
pub fn from_err_code(err_code: c_int) -> LmdbError { pub fn from_err_code(err_code: c_int) -> Error {
match err_code { match err_code {
ffi::MDB_KEYEXIST => LmdbError::KeyExist, ffi::MDB_KEYEXIST => Error::KeyExist,
ffi::MDB_NOTFOUND => LmdbError::NotFound, ffi::MDB_NOTFOUND => Error::NotFound,
ffi::MDB_PAGE_NOTFOUND => LmdbError::PageNotFound, ffi::MDB_PAGE_NOTFOUND => Error::PageNotFound,
ffi::MDB_CORRUPTED => LmdbError::Corrupted, ffi::MDB_CORRUPTED => Error::Corrupted,
ffi::MDB_PANIC => LmdbError::Panic, ffi::MDB_PANIC => Error::Panic,
ffi::MDB_VERSION_MISMATCH => LmdbError::VersionMismatch, ffi::MDB_VERSION_MISMATCH => Error::VersionMismatch,
ffi::MDB_INVALID => LmdbError::Invalid, ffi::MDB_INVALID => Error::Invalid,
ffi::MDB_MAP_FULL => LmdbError::MapFull, ffi::MDB_MAP_FULL => Error::MapFull,
ffi::MDB_DBS_FULL => LmdbError::DbsFull, ffi::MDB_DBS_FULL => Error::DbsFull,
ffi::MDB_READERS_FULL => LmdbError::ReadersFull, ffi::MDB_READERS_FULL => Error::ReadersFull,
ffi::MDB_TLS_FULL => LmdbError::TlsFull, ffi::MDB_TLS_FULL => Error::TlsFull,
ffi::MDB_TXN_FULL => LmdbError::TxnFull, ffi::MDB_TXN_FULL => Error::TxnFull,
ffi::MDB_CURSOR_FULL => LmdbError::CursorFull, ffi::MDB_CURSOR_FULL => Error::CursorFull,
ffi::MDB_PAGE_FULL => LmdbError::PageFull, ffi::MDB_PAGE_FULL => Error::PageFull,
ffi::MDB_MAP_RESIZED => LmdbError::MapResized, ffi::MDB_MAP_RESIZED => Error::MapResized,
ffi::MDB_INCOMPATIBLE => LmdbError::Incompatible, ffi::MDB_INCOMPATIBLE => Error::Incompatible,
ffi::MDB_BAD_RSLOT => LmdbError::BadRslot, ffi::MDB_BAD_RSLOT => Error::BadRslot,
ffi::MDB_BAD_TXN => LmdbError::BadTxn, ffi::MDB_BAD_TXN => Error::BadTxn,
ffi::MDB_BAD_VALSIZE => LmdbError::BadValSize, ffi::MDB_BAD_VALSIZE => Error::BadValSize,
ffi::MDB_BAD_DBI => LmdbError::BadDbi, ffi::MDB_BAD_DBI => Error::BadDbi,
other => LmdbError::Other(other), other => Error::Other(other),
} }
} }
pub fn to_err_code(&self) -> c_int { pub fn to_err_code(&self) -> c_int {
match *self { match *self {
LmdbError::KeyExist => ffi::MDB_KEYEXIST, Error::KeyExist => ffi::MDB_KEYEXIST,
LmdbError::NotFound => ffi::MDB_NOTFOUND, Error::NotFound => ffi::MDB_NOTFOUND,
LmdbError::PageNotFound => ffi::MDB_PAGE_NOTFOUND, Error::PageNotFound => ffi::MDB_PAGE_NOTFOUND,
LmdbError::Corrupted => ffi::MDB_CORRUPTED, Error::Corrupted => ffi::MDB_CORRUPTED,
LmdbError::Panic => ffi::MDB_PANIC, Error::Panic => ffi::MDB_PANIC,
LmdbError::VersionMismatch => ffi::MDB_VERSION_MISMATCH, Error::VersionMismatch => ffi::MDB_VERSION_MISMATCH,
LmdbError::Invalid => ffi::MDB_INVALID, Error::Invalid => ffi::MDB_INVALID,
LmdbError::MapFull => ffi::MDB_MAP_FULL, Error::MapFull => ffi::MDB_MAP_FULL,
LmdbError::DbsFull => ffi::MDB_DBS_FULL, Error::DbsFull => ffi::MDB_DBS_FULL,
LmdbError::ReadersFull => ffi::MDB_READERS_FULL, Error::ReadersFull => ffi::MDB_READERS_FULL,
LmdbError::TlsFull => ffi::MDB_TLS_FULL, Error::TlsFull => ffi::MDB_TLS_FULL,
LmdbError::TxnFull => ffi::MDB_TXN_FULL, Error::TxnFull => ffi::MDB_TXN_FULL,
LmdbError::CursorFull => ffi::MDB_CURSOR_FULL, Error::CursorFull => ffi::MDB_CURSOR_FULL,
LmdbError::PageFull => ffi::MDB_PAGE_FULL, Error::PageFull => ffi::MDB_PAGE_FULL,
LmdbError::MapResized => ffi::MDB_MAP_RESIZED, Error::MapResized => ffi::MDB_MAP_RESIZED,
LmdbError::Incompatible => ffi::MDB_INCOMPATIBLE, Error::Incompatible => ffi::MDB_INCOMPATIBLE,
LmdbError::BadRslot => ffi::MDB_BAD_RSLOT, Error::BadRslot => ffi::MDB_BAD_RSLOT,
LmdbError::BadTxn => ffi::MDB_BAD_TXN, Error::BadTxn => ffi::MDB_BAD_TXN,
LmdbError::BadValSize => ffi::MDB_BAD_VALSIZE, Error::BadValSize => ffi::MDB_BAD_VALSIZE,
LmdbError::BadDbi => ffi::MDB_BAD_DBI, Error::BadDbi => ffi::MDB_BAD_DBI,
LmdbError::Other(err_code) => err_code, Error::Other(err_code) => err_code,
} }
} }
} }
impl fmt::Display for LmdbError { impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}", self.description()) write!(fmt, "{}", self.description())
} }
} }
impl Error for LmdbError { impl StdError for Error {
fn description(&self) -> &str { fn description(&self) -> &str {
unsafe { unsafe {
// This is safe since the error messages returned from mdb_strerror are static. // This is safe since the error messages returned from mdb_strerror are static.
@ -121,29 +121,29 @@ impl Error for LmdbError {
} }
} }
pub type LmdbResult<T> = Result<T, LmdbError>; pub type Result<T> = result::Result<T, Error>;
pub fn lmdb_result(err_code: c_int) -> LmdbResult<()> { pub fn lmdb_result(err_code: c_int) -> Result<()> {
if err_code == ffi::MDB_SUCCESS { if err_code == ffi::MDB_SUCCESS {
Ok(()) Ok(())
} else { } else {
Err(LmdbError::from_err_code(err_code)) Err(Error::from_err_code(err_code))
} }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::error::Error; use std::error::Error as StdError;
use super::*; use super::*;
#[test] #[test]
fn test_description() { fn test_description() {
assert_eq!("Permission denied", assert_eq!("Permission denied",
LmdbError::from_err_code(13).description()); Error::from_err_code(13).description());
assert_eq!("MDB_NOTFOUND: No matching key/data pair found", assert_eq!("MDB_NOTFOUND: No matching key/data pair found",
LmdbError::NotFound.description()); Error::NotFound.description());
} }
} }

@ -1,8 +1,5 @@
//! Safe Rust bindings for the [Symas Lightning Memory-Mapped Database(LMDB)] //! Idiomatic and safe APIs for interacting with the
//! (http://symas.com/mdb/). //! [Symas Lightning Memory-Mapped Database (LMDB)](http://symas.com/mdb/).
//!
//! Provides the minimal amount of abstraction necessary to interact with LMDB safely in Rust. In
//! general, the API is very similar to the LMDB [C-API](http://symas.com/mdb/doc/).
#![feature(core, libc, old_io, optin_builtin_traits, path, std_misc, unsafe_destructor)] #![feature(core, libc, old_io, optin_builtin_traits, path, std_misc, unsafe_destructor)]
#![cfg_attr(test, feature(test))] #![cfg_attr(test, feature(test))]
@ -23,7 +20,7 @@ pub use cursor::{
}; };
pub use database::Database; pub use database::Database;
pub use environment::{Environment, EnvironmentBuilder}; pub use environment::{Environment, EnvironmentBuilder};
pub use error::{LmdbResult, LmdbError}; pub use error::{Error, Result};
pub use flags::*; pub use flags::*;
pub use transaction::{ pub use transaction::{
InactiveTransaction, InactiveTransaction,
@ -37,7 +34,7 @@ macro_rules! lmdb_try {
($expr:expr) => ({ ($expr:expr) => ({
match $expr { match $expr {
::ffi::MDB_SUCCESS => (), ::ffi::MDB_SUCCESS => (),
err_code => return Err(::std::error::FromError::from_error(::LmdbError::from_err_code(err_code))), err_code => return Err(::std::error::FromError::from_error(::Error::from_err_code(err_code))),
} }
}) })
} }
@ -48,7 +45,7 @@ macro_rules! lmdb_try_with_cleanup {
::ffi::MDB_SUCCESS => (), ::ffi::MDB_SUCCESS => (),
err_code => { err_code => {
let _ = $cleanup; let _ = $cleanup;
return Err(::std::error::FromError::from_error(::LmdbError::from_err_code(err_code))) return Err(::std::error::FromError::from_error(::Error::from_err_code(err_code)))
}, },
} }
}) })

@ -8,7 +8,7 @@ use ffi;
use cursor::{RoCursor, RwCursor}; use cursor::{RoCursor, RwCursor};
use environment::Environment; use environment::Environment;
use database::Database; use database::Database;
use error::{LmdbError, LmdbResult, lmdb_result}; use error::{Error, Result, lmdb_result};
use flags::{DatabaseFlags, EnvironmentFlags, WriteFlags}; use flags::{DatabaseFlags, EnvironmentFlags, WriteFlags};
/// An LMDB transaction. /// An LMDB transaction.
@ -29,7 +29,7 @@ pub trait TransactionExt<'env> : Transaction<'env> + Sized {
/// Commits the transaction. /// Commits the transaction.
/// ///
/// Any pending operations will be saved. /// Any pending operations will be saved.
fn commit(self) -> LmdbResult<()> { fn commit(self) -> Result<()> {
unsafe { unsafe {
let result = lmdb_result(ffi::mdb_txn_commit(self.txn())); let result = lmdb_result(ffi::mdb_txn_commit(self.txn()));
mem::forget(self); mem::forget(self);
@ -59,7 +59,7 @@ pub trait TransactionExt<'env> : Transaction<'env> + Sized {
/// `Database::create`) **must not** be called from multiple concurrent transactions in the same /// `Database::create`) **must not** be called from multiple concurrent transactions in the same
/// environment. A transaction which uses this function must finish (either commit or abort) /// environment. A transaction which uses this function must finish (either commit or abort)
/// before any other transaction may use this function. /// before any other transaction may use this function.
unsafe fn open_db(&self, name: Option<&str>) -> LmdbResult<Database> { unsafe fn open_db(&self, name: Option<&str>) -> Result<Database> {
Database::new(self.txn(), name, 0) Database::new(self.txn(), name, 0)
} }
@ -68,9 +68,9 @@ pub trait TransactionExt<'env> : Transaction<'env> + Sized {
/// This function retrieves the data associated with the given key in the database. If the /// This function retrieves the data associated with the given key in the database. If the
/// database supports duplicate keys (`DatabaseFlags::DUP_SORT`) then the first data item for /// database supports duplicate keys (`DatabaseFlags::DUP_SORT`) then the first data item for
/// the key will be returned. Retrieval of other items requires the use of /// the key will be returned. Retrieval of other items requires the use of
/// `Transaction::cursor_get`. If the item is not in the database, then `LmdbError::NotFound` /// `Transaction::cursor_get`. If the item is not in the database, then `Error::NotFound`
/// will be returned. /// will be returned.
fn get<'txn>(&'txn self, database: Database, key: &[u8]) -> LmdbResult<&'txn [u8]> { fn get<'txn>(&'txn self, database: Database, key: &[u8]) -> Result<&'txn [u8]> {
let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t, 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 }; mv_data: key.as_ptr() as *mut c_void };
let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: 0, let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: 0,
@ -83,18 +83,18 @@ pub trait TransactionExt<'env> : Transaction<'env> + Sized {
len: data_val.mv_size as usize len: data_val.mv_size as usize
})) }))
}, },
err_code => Err(LmdbError::from_err_code(err_code)), err_code => Err(Error::from_err_code(err_code)),
} }
} }
} }
/// Open a new read-only cursor on the given database. /// Open a new read-only cursor on the given database.
fn open_ro_cursor<'txn>(&'txn self, db: Database) -> LmdbResult<RoCursor<'txn>> { fn open_ro_cursor<'txn>(&'txn self, db: Database) -> Result<RoCursor<'txn>> {
RoCursor::new(self, db) RoCursor::new(self, db)
} }
/// Gets the option flags for the given database in the transaction. /// Gets the option flags for the given database in the transaction.
fn db_flags(&self, db: Database) -> LmdbResult<DatabaseFlags> { fn db_flags(&self, db: Database) -> Result<DatabaseFlags> {
let mut flags: c_uint = 0; let mut flags: c_uint = 0;
unsafe { unsafe {
try!(lmdb_result(ffi::mdb_dbi_flags(self.txn(), db.dbi(), &mut flags))); try!(lmdb_result(ffi::mdb_dbi_flags(self.txn(), db.dbi(), &mut flags)));
@ -126,7 +126,7 @@ impl <'env> RoTransaction<'env> {
/// Creates a new read-only transaction in the given environment. Prefer using /// Creates a new read-only transaction in the given environment. Prefer using
/// `Environment::begin_ro_txn`. /// `Environment::begin_ro_txn`.
#[doc(hidden)] #[doc(hidden)]
pub fn new(env: &'env Environment) -> LmdbResult<RoTransaction<'env>> { pub fn new(env: &'env Environment) -> Result<RoTransaction<'env>> {
let mut txn: *mut ffi::MDB_txn = ptr::null_mut(); let mut txn: *mut ffi::MDB_txn = ptr::null_mut();
unsafe { unsafe {
try!(lmdb_result(ffi::mdb_txn_begin(env.env(), try!(lmdb_result(ffi::mdb_txn_begin(env.env(),
@ -182,7 +182,7 @@ impl <'env> InactiveTransaction<'env> {
/// ///
/// This acquires a new reader lock for a transaction handle that had been released by /// This acquires a new reader lock for a transaction handle that had been released by
/// `RoTransaction::reset`. /// `RoTransaction::reset`.
pub fn renew(self) -> LmdbResult<RoTransaction<'env>> { pub fn renew(self) -> Result<RoTransaction<'env>> {
let txn = self.txn; let txn = self.txn;
unsafe { unsafe {
mem::forget(self); mem::forget(self);
@ -213,7 +213,7 @@ impl <'env> RwTransaction<'env> {
/// Creates a new read-write transaction in the given environment. Prefer using /// Creates a new read-write transaction in the given environment. Prefer using
/// `Environment::begin_ro_txn`. /// `Environment::begin_ro_txn`.
#[doc(hidden)] #[doc(hidden)]
pub fn new(env: &'env Environment) -> LmdbResult<RwTransaction<'env>> { pub fn new(env: &'env Environment) -> Result<RwTransaction<'env>> {
let mut txn: *mut ffi::MDB_txn = ptr::null_mut(); let mut txn: *mut ffi::MDB_txn = ptr::null_mut();
unsafe { unsafe {
try!(lmdb_result(ffi::mdb_txn_begin(env.env(), try!(lmdb_result(ffi::mdb_txn_begin(env.env(),
@ -239,16 +239,13 @@ impl <'env> RwTransaction<'env> {
/// `Database::open`) **must not** be called from multiple concurrent transactions in the same /// `Database::open`) **must not** be called from multiple concurrent transactions in the same
/// environment. A transaction which uses this function must finish (either commit or abort) /// environment. A transaction which uses this function must finish (either commit or abort)
/// before any other transaction may use this function. /// before any other transaction may use this function.
pub unsafe fn create_db(&self, pub unsafe fn create_db(&self, name: Option<&str>, flags: DatabaseFlags) -> Result<Database> {
name: Option<&str>,
flags: DatabaseFlags)
-> LmdbResult<Database> {
Database::new(self.txn(), name, flags.bits() | ffi::MDB_CREATE) Database::new(self.txn(), name, flags.bits() | ffi::MDB_CREATE)
} }
/// Opens a new read-write cursor on the given database and transaction. /// Opens a new read-write cursor on the given database and transaction.
pub fn open_rw_cursor<'txn>(&'txn mut self, db: Database) -> LmdbResult<RwCursor<'txn>> { pub fn open_rw_cursor<'txn>(&'txn mut self, db: Database) -> Result<RwCursor<'txn>> {
RwCursor::new(self, db) RwCursor::new(self, db)
} }
@ -262,7 +259,7 @@ impl <'env> RwTransaction<'env> {
key: &[u8], key: &[u8],
data: &[u8], data: &[u8],
flags: WriteFlags) flags: WriteFlags)
-> LmdbResult<()> { -> Result<()> {
let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t, 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 }; 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, let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: data.len() as size_t,
@ -283,7 +280,7 @@ impl <'env> RwTransaction<'env> {
key: &[u8], key: &[u8],
len: size_t, len: size_t,
flags: WriteFlags) flags: WriteFlags)
-> LmdbResult<BufWriter<'txn>> { -> Result<BufWriter<'txn>> {
let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t, 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 }; mv_data: key.as_ptr() as *mut c_void };
let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: len, let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: len,
@ -310,12 +307,12 @@ impl <'env> RwTransaction<'env> {
/// If the database supports sorted duplicates and the data parameter is `None`, all of the /// If the database supports sorted duplicates and the data parameter is `None`, all of the
/// duplicate data items for the key will be deleted. Otherwise, if the data parameter is /// duplicate data items for the key will be deleted. Otherwise, if the data parameter is
/// `Some` only the matching data item will be deleted. This function will return /// `Some` only the matching data item will be deleted. This function will return
/// `LmdbError::NotFound` if the specified key/data pair is not in the database. /// `Error::NotFound` if the specified key/data pair is not in the database.
pub fn del(&mut self, pub fn del(&mut self,
database: Database, database: Database,
key: &[u8], key: &[u8],
data: Option<&[u8]>) data: Option<&[u8]>)
-> LmdbResult<()> { -> Result<()> {
let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t, 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 }; mv_data: key.as_ptr() as *mut c_void };
let data_val: Option<ffi::MDB_val> = let data_val: Option<ffi::MDB_val> =
@ -331,7 +328,7 @@ impl <'env> RwTransaction<'env> {
} }
/// Empties the given database. All items will be removed. /// Empties the given database. All items will be removed.
pub fn clear_db(&mut self, db: Database) -> LmdbResult<()> { pub fn clear_db(&mut self, db: Database) -> Result<()> {
unsafe { lmdb_result(ffi::mdb_drop(self.txn(), db.dbi(), 0)) } unsafe { lmdb_result(ffi::mdb_drop(self.txn(), db.dbi(), 0)) }
} }
@ -341,12 +338,12 @@ impl <'env> RwTransaction<'env> {
/// ///
/// This method is unsafe in the same ways as `Environment::close_db`, and should be used /// This method is unsafe in the same ways as `Environment::close_db`, and should be used
/// accordingly. /// accordingly.
pub unsafe fn drop_db(&mut self, db: Database) -> LmdbResult<()> { pub unsafe fn drop_db(&mut self, db: Database) -> Result<()> {
lmdb_result(ffi::mdb_drop(self.txn, db.dbi(), 1)) lmdb_result(ffi::mdb_drop(self.txn, db.dbi(), 1))
} }
/// Begins a new nested transaction inside of this transaction. /// Begins a new nested transaction inside of this transaction.
pub fn begin_nested_txn<'txn>(&'txn mut self) -> LmdbResult<RwTransaction<'txn>> { pub fn begin_nested_txn<'txn>(&'txn mut self) -> Result<RwTransaction<'txn>> {
let mut nested: *mut ffi::MDB_txn = ptr::null_mut(); let mut nested: *mut ffi::MDB_txn = ptr::null_mut();
unsafe { unsafe {
let env: *mut ffi::MDB_env = ffi::mdb_txn_env(self.txn()); let env: *mut ffi::MDB_env = ffi::mdb_txn_env(self.txn());
@ -396,10 +393,10 @@ mod test {
assert_eq!(b"val1", txn.get(db, b"key1").unwrap()); assert_eq!(b"val1", txn.get(db, b"key1").unwrap());
assert_eq!(b"val2", txn.get(db, b"key2").unwrap()); assert_eq!(b"val2", txn.get(db, b"key2").unwrap());
assert_eq!(b"val3", txn.get(db, b"key3").unwrap()); assert_eq!(b"val3", txn.get(db, b"key3").unwrap());
assert_eq!(txn.get(db, b"key"), Err(LmdbError::NotFound)); assert_eq!(txn.get(db, b"key"), Err(Error::NotFound));
txn.del(db, b"key1", None).unwrap(); txn.del(db, b"key1", None).unwrap();
assert_eq!(txn.get(db, b"key1"), Err(LmdbError::NotFound)); assert_eq!(txn.get(db, b"key1"), Err(Error::NotFound));
} }
#[test] #[test]
@ -417,10 +414,10 @@ mod test {
let mut txn = env.begin_rw_txn().unwrap(); let mut txn = env.begin_rw_txn().unwrap();
assert_eq!(b"val1", txn.get(db, b"key1").unwrap()); assert_eq!(b"val1", txn.get(db, b"key1").unwrap());
assert_eq!(txn.get(db, b"key"), Err(LmdbError::NotFound)); assert_eq!(txn.get(db, b"key"), Err(Error::NotFound));
txn.del(db, b"key1", None).unwrap(); txn.del(db, b"key1", None).unwrap();
assert_eq!(txn.get(db, b"key1"), Err(LmdbError::NotFound)); assert_eq!(txn.get(db, b"key1"), Err(Error::NotFound));
} }
#[test] #[test]
@ -458,7 +455,7 @@ mod test {
} }
assert_eq!(txn.get(db, b"key1").unwrap(), b"val1"); assert_eq!(txn.get(db, b"key1").unwrap(), b"val1");
assert_eq!(txn.get(db, b"key2"), Err(LmdbError::NotFound)); assert_eq!(txn.get(db, b"key2"), Err(Error::NotFound));
} }
#[test] #[test]
@ -480,7 +477,7 @@ mod test {
} }
let txn = env.begin_ro_txn().unwrap(); let txn = env.begin_ro_txn().unwrap();
assert_eq!(txn.get(db, b"key"), Err(LmdbError::NotFound)); assert_eq!(txn.get(db, b"key"), Err(Error::NotFound));
} }
@ -502,7 +499,7 @@ mod test {
txn.commit().unwrap(); txn.commit().unwrap();
} }
assert_eq!(env.open_db(Some("test")), Err(LmdbError::NotFound)); assert_eq!(env.open_db(Some("test")), Err(Error::NotFound));
} }
#[test] #[test]
@ -525,7 +522,7 @@ mod test {
let db = reader_env.open_db(None).unwrap(); let db = reader_env.open_db(None).unwrap();
{ {
let txn = reader_env.begin_ro_txn().unwrap(); let txn = reader_env.begin_ro_txn().unwrap();
assert_eq!(txn.get(db, key), Err(LmdbError::NotFound)); assert_eq!(txn.get(db, key), Err(Error::NotFound));
txn.abort(); txn.abort();
} }
reader_barrier.wait(); reader_barrier.wait();

Loading…
Cancel
Save