reintroduce LmdbError as enum

without.crypto
Dan Burkert 10 years ago
parent 1d220c2116
commit ae49ecef6b
  1. 23
      lmdb-sys/src/constants.rs
  2. 8
      src/cursor.rs
  3. 8
      src/environment.rs
  4. 108
      src/error.rs
  5. 58
      src/flags.rs

@ -81,66 +81,45 @@ pub const MDB_CP_COMPACT: c_uint = 0x01;
/// Successful result.
pub const MDB_SUCCESS: c_int = 0;
/// key/data pair already exists.
pub const MDB_KEYEXIST: c_int = -30799;
/// key/data pair not found (EOF).
pub const MDB_NOTFOUND: c_int = -30798;
/// Requested page not found - this usually indicates corruption.
pub const MDB_PAGE_NOTFOUND: c_int = -30797;
/// Located page was wrong type.
pub const MDB_CORRUPTED: c_int = -30796;
/// Update of meta page failed or environment had fatal error.
pub const MDB_PANIC : c_int = -30795;
pub const MDB_PANIC: c_int = -30795;
/// Environment version mismatch.
pub const MDB_VERSION_MISMATCH: c_int = -30794;
/// File is not a valid LMDB file.
pub const MDB_INVALID: c_int = -30793;
/// Environment mapsize reached.
pub const MDB_MAP_FULL: c_int = -30792;
/// Environment maxdbs reached.
pub const MDB_DBS_FULL: c_int = -30791;
/// Environment maxreaders reached.
pub const MDB_READERS_FULL: c_int = -30790;
/// Too many TLS keys in use - Windows only.
pub const MDB_TLS_FULL: c_int = -30789;
/// Txn has too many dirty pages.
pub const MDB_TXN_FULL: c_int = -30788;
/// Cursor stack too deep - internal error.
pub const MDB_CURSOR_FULL: c_int = -30787;
/// Page has not enough space - internal error.
pub const MDB_PAGE_FULL: c_int = -30786;
/// Database contents grew beyond environment mapsize.
pub const MDB_MAP_RESIZED: c_int = -30785;
/// MDB_INCOMPATIBLE: Operation and DB incompatible, or DB flags changed.
pub const MDB_INCOMPATIBLE: c_int = -30784;
/// Invalid reuse of reader locktable slot.
pub const MDB_BAD_RSLOT: c_int = -30783;
/// Transaction cannot recover - it must be aborted.
pub const MDB_BAD_TXN: c_int = -30782;
/// Unsupported size of key/DB name/data, or wrong DUPFIXED size.
pub const MDB_BAD_VALSIZE: c_int = -30781;
/// The specified DBI was changed unexpectedly.
pub const MDB_BAD_DBI: c_int = -30780;
/// The last defined error code.
pub const MDB_LAST_ERRCODE: c_int = MDB_BAD_DBI;

@ -147,8 +147,8 @@ impl <'txn> RwCursor<'txn> {
///
/// ### Flags
///
/// `MDB_NODUPDATA` may be used to delete all data items for the current key, if the database
/// was opened with `MDB_DUPSORT`.
/// `NO_DUP_DATA` may be used to delete all data items for the current key, if the database
/// was opened with `DUP_SORT`.
pub fn del(&self, flags: WriteFlags) -> LmdbResult<()> {
unsafe {
lmdb_result(ffi::mdb_cursor_del(self.cursor(), flags.bits()))
@ -283,7 +283,7 @@ mod test {
fn test_get_dup() {
let dir = io::TempDir::new("test").unwrap();
let env = Environment::new().open(dir.path(), io::USER_RWX).unwrap();
let db = env.create_db(None, MDB_DUPSORT).unwrap();
let db = env.create_db(None, DUP_SORT).unwrap();
let mut txn = env.begin_write_txn().unwrap();
txn.put(db, b"key1", b"val1", WriteFlags::empty()).unwrap();
@ -329,7 +329,7 @@ mod test {
fn test_get_dupfixed() {
let dir = io::TempDir::new("test").unwrap();
let env = Environment::new().open(dir.path(), io::USER_RWX).unwrap();
let db = env.create_db(None, MDB_DUPSORT | MDB_DUPFIXED).unwrap();
let db = env.create_db(None, DUP_SORT | DUP_FIXED).unwrap();
let mut txn = env.begin_write_txn().unwrap();
txn.put(db, b"key1", b"val1", WriteFlags::empty()).unwrap();

@ -242,7 +242,7 @@ mod test {
let dir = io::TempDir::new("test").unwrap();
// opening non-existent env with read-only should fail
assert!(Environment::new().set_flags(MDB_RDONLY)
assert!(Environment::new().set_flags(READ_ONLY)
.open(dir.path(), io::USER_RWX)
.is_err());
@ -250,7 +250,7 @@ mod test {
assert!(Environment::new().open(dir.path(), io::USER_RWX).is_ok());
// opening env with read-only should succeed
assert!(Environment::new().set_flags(MDB_RDONLY)
assert!(Environment::new().set_flags(READ_ONLY)
.open(dir.path(), io::USER_RWX)
.is_ok());
}
@ -267,7 +267,7 @@ mod test {
}
{ // read-only environment
let env = Environment::new().set_flags(MDB_RDONLY)
let env = Environment::new().set_flags(READ_ONLY)
.open(dir.path(), io::USER_RWX)
.unwrap();
@ -305,7 +305,7 @@ mod test {
let env = Environment::new().open(dir.path(), io::USER_RWX).unwrap();
assert!(env.sync(true).is_ok());
} {
let env = Environment::new().set_flags(MDB_RDONLY)
let env = Environment::new().set_flags(READ_ONLY)
.open(dir.path(), io::USER_RWX)
.unwrap();
assert!(env.sync(true).is_ok());

@ -5,19 +5,108 @@ use std::str;
use ffi;
#[deriving(Show, Eq, PartialEq, Copy, Clone)]
pub struct LmdbError {
err_code: c_int,
pub enum LmdbError {
/// key/data pair already exists.
KeyExist,
/// key/data pair not found (EOF).
NotFound,
/// Requested page not found - this usually indicates corruption.
PageNotFound,
/// Located page was wrong type.
Corrupted,
/// Update of meta page failed or environment had fatal error.
Panic,
/// Environment version mismatch.
VersionMismatch,
/// File is not a valid LMDB file.
Invalid,
/// Environment mapsize reached.
MapFull,
/// Environment maxdbs reached.
DbsFull,
/// Environment maxreaders reached.
ReadersFull,
/// Too many TLS keys in use - Windows only.
TlsFull,
/// Txn has too many dirty pages.
TxnFull,
/// Cursor stack too deep - internal error.
CursorFull,
/// Page has not enough space - internal error.
PageFull,
/// Database contents grew beyond environment mapsize.
MapResized,
/// MDB_Incompatible: Operation and DB incompatible, or DB flags changed.
Incompatible,
/// Invalid reuse of reader locktable slot.
BadRslot,
/// Transaction cannot recover - it must be aborted.
BadTxn,
/// Unsupported size of key/DB name/data, or wrong DUP_FIXED size.
BadValSize,
/// The specified DBI was changed unexpectedly.
BadDbi,
/// Other error.
Other(c_int),
}
impl Error for LmdbError {
fn description(&self) -> &str {
unsafe { str::from_c_str(ffi::mdb_strerror(self.err_code) as *const _) }
impl LmdbError {
pub fn from_err_code(err_code: c_int) -> LmdbError {
match err_code {
ffi::MDB_KEYEXIST => LmdbError::KeyExist,
ffi::MDB_NOTFOUND => LmdbError::NotFound,
ffi::MDB_PAGE_NOTFOUND => LmdbError::PageNotFound,
ffi::MDB_CORRUPTED => LmdbError::Corrupted,
ffi::MDB_PANIC => LmdbError::Panic,
ffi::MDB_VERSION_MISMATCH => LmdbError::VersionMismatch,
ffi::MDB_INVALID => LmdbError::Invalid,
ffi::MDB_MAP_FULL => LmdbError::MapFull,
ffi::MDB_DBS_FULL => LmdbError::DbsFull,
ffi::MDB_READERS_FULL => LmdbError::ReadersFull,
ffi::MDB_TLS_FULL => LmdbError::TlsFull,
ffi::MDB_TXN_FULL => LmdbError::TxnFull,
ffi::MDB_CURSOR_FULL => LmdbError::CursorFull,
ffi::MDB_PAGE_FULL => LmdbError::PageFull,
ffi::MDB_MAP_RESIZED => LmdbError::MapResized,
ffi::MDB_INCOMPATIBLE => LmdbError::Incompatible,
ffi::MDB_BAD_RSLOT => LmdbError::BadRslot,
ffi::MDB_BAD_TXN => LmdbError::BadTxn,
ffi::MDB_BAD_VALSIZE => LmdbError::BadValSize,
ffi::MDB_BAD_DBI => LmdbError::BadDbi,
other => LmdbError::Other(other),
}
}
pub fn to_err_code(&self) -> c_int {
match *self {
LmdbError::KeyExist => ffi::MDB_KEYEXIST,
LmdbError::NotFound => ffi::MDB_NOTFOUND,
LmdbError::PageNotFound => ffi::MDB_PAGE_NOTFOUND,
LmdbError::Corrupted => ffi::MDB_CORRUPTED,
LmdbError::Panic => ffi::MDB_PANIC,
LmdbError::VersionMismatch => ffi::MDB_VERSION_MISMATCH,
LmdbError::Invalid => ffi::MDB_INVALID,
LmdbError::MapFull => ffi::MDB_MAP_FULL,
LmdbError::DbsFull => ffi::MDB_DBS_FULL,
LmdbError::ReadersFull => ffi::MDB_READERS_FULL,
LmdbError::TlsFull => ffi::MDB_TLS_FULL,
LmdbError::TxnFull => ffi::MDB_TXN_FULL,
LmdbError::CursorFull => ffi::MDB_CURSOR_FULL,
LmdbError::PageFull => ffi::MDB_PAGE_FULL,
LmdbError::MapResized => ffi::MDB_MAP_RESIZED,
LmdbError::Incompatible => ffi::MDB_INCOMPATIBLE,
LmdbError::BadRslot => ffi::MDB_BAD_RSLOT,
LmdbError::BadTxn => ffi::MDB_BAD_TXN,
LmdbError::BadValSize => ffi::MDB_BAD_VALSIZE,
LmdbError::BadDbi => ffi::MDB_BAD_DBI,
LmdbError::Other(err_code) => err_code,
}
}
}
impl LmdbError {
pub fn from_err_code(err_code: c_int) -> LmdbError {
LmdbError { err_code: err_code}
impl Error for LmdbError {
fn description(&self) -> &str {
unsafe { str::from_c_str(ffi::mdb_strerror(self.to_err_code()) as *const _) }
}
}
@ -37,14 +126,13 @@ mod test {
use std::error::Error;
use super::*;
use ffi;
#[test]
fn test_description() {
assert_eq!("Permission denied",
LmdbError::from_err_code(13).description());
assert_eq!("MDB_NOTFOUND: No matching key/data pair found",
LmdbError::from_err_code(ffi::MDB_NOTFOUND).description());
LmdbError::NotFound.description());
}
}

@ -1,5 +1,7 @@
use libc::c_uint;
use ffi::*;
bitflags! {
#[doc="Environment Options"]
#[deriving(Show)]
@ -12,25 +14,25 @@ bitflags! {
#[doc="across multiple invocations. This option may not always work, depending on"]
#[doc="how the operating system has allocated memory to shared libraries and other uses."]
#[doc="The feature is highly experimental."]
const FIXED_MAP = 0x01,
const FIXED_MAP = MDB_FIXEDMAP,
#[doc="By default, LMDB creates its environment in a directory whose pathname is given in"]
#[doc="`path`, and creates its data and lock files under that directory. With this option,"]
#[doc="`path` is used as-is for the database main data file. The database lock file is the"]
#[doc="`path` with `-lock` appended."]
const NO_SUB_DIR = 0x4000,
const NO_SUB_DIR = MDB_NOSUBDIR,
#[doc="Use a writeable memory map unless `READ_ONLY` is set. This is faster and uses"]
#[doc="fewer mallocs, but loses protection from application bugs like wild pointer writes"]
#[doc="and other bad updates into the database. Incompatible with nested transactions."]
#[doc="Processes with and without `WRITEMAP` on the same environment do not cooperate"]
#[doc="Processes with and without `WRITE_MAP` on the same environment do not cooperate"]
#[doc="well."]
const WRITEMAP = 0x80000,
const WRITE_MAP = MDB_WRITEMAP,
#[doc="Open the environment in read-only mode. No write operations will be allowed."]
#[doc="When opening an environment, LMDB will still modify the lock file - except on"]
#[doc="read-only filesystems, where LMDB does not use locks."]
const READ_ONLY = 0x20000,
const READ_ONLY = MDB_RDONLY,
#[doc="Flush system buffers to disk only once per transaction, omit the metadata flush."]
#[doc="Defer that until the system flushes files to disk, or next non-`READ_ONLY` commit"]
@ -38,26 +40,26 @@ bitflags! {
#[doc="system crash may undo the last committed transaction. I.e. it preserves the ACI"]
#[doc="(atomicity, consistency, isolation) but not D (durability) database property."]
#[doc="\n\nThis flag may be changed at any time using `Environment::set_flags`."]
const NO_META_SYNC = 0x40000,
const NO_META_SYNC = MDB_NOMETASYNC,
#[doc="Don't flush system buffers to disk when committing a transaction. This optimization"]
#[doc="means a system crash can corrupt the database or lose the last transactions if"]
#[doc="buffers are not yet flushed to disk. The risk is governed by how often the system"]
#[doc="flushes dirty buffers to disk and how often `Environment::sync` is called. However,"]
#[doc="if the filesystem preserves write order and the `WRITEMAP` flag is not used,"]
#[doc="if the filesystem preserves write order and the `WRITE_MAP` flag is not used,"]
#[doc="transactions exhibit ACI (atomicity, consistency, isolation) properties and only"]
#[doc="lose D (durability). I.e. database integrity"] #[doc="is maintained, but a system"]
#[doc="crash may undo the final transactions. Note that (`NO_SYNC | WRITEMAP`) leaves the"]
#[doc="crash may undo the final transactions. Note that (`NO_SYNC | WRITE_MAP`) leaves the"]
#[doc="system with no hint for when to write transactions to disk, unless"]
#[doc="`Environment::sync` is called. (`MAP_ASYNC | WRITEMAP`) may be preferable."]
#[doc="`Environment::sync` is called. (`MAP_ASYNC | WRITE_MAP`) may be preferable."]
#[doc="\n\nThis flag may be changed at any time using `Environment::set_flags`."]
const NO_SYNC = 0x10000,
const NO_SYNC = MDB_NOSYNC,
#[doc="When using `WRITEMAP`, use asynchronous flushes to disk. As with `NO_SYNC`, a"]
#[doc="When using `WRITE_MAP`, use asynchronous flushes to disk. As with `NO_SYNC`, a"]
#[doc="system crash can then corrupt the database or lose the last transactions. Calling"]
#[doc="`Environment::sync` ensures on-disk database integrity until next commit."]
#[doc="\n\nThis flag may be changed at any time using `Environment::set_flags`."]
const MAP_ASYNC = 0x100000,
const MAP_ASYNC = MDB_MAPASYNC,
#[doc="Don't use thread-local storage. Tie reader locktable slots to transaction objects"]
#[doc="instead of to threads. I.e. `RoTransaction::reset` keeps the slot reseved for the"]
@ -67,20 +69,20 @@ bitflags! {
#[doc="threads over individual OS threads need this option. Such an application must also"]
#[doc="serialize the write transactions in an OS thread, since LMDB's write locking is"]
#[doc="unaware of the user threads."]
const NO_TLS = 0x200000,
const NO_TLS = MDB_NOTLS,
#[doc="Do not do any locking. If concurrent access is anticipated, the caller must manage"]
#[doc="all concurrency themself. For proper operation the caller must enforce"]
#[doc="single-writer semantics, and must ensure that no readers are using old"]
#[doc="transactions while a writer is active. The simplest approach is to use an exclusive"]
#[doc="lock so that no readers may be active at all when a writer begins."]
const NO_LOCK = 0x400000,
const NO_LOCK = MDB_NOLOCK,
#[doc="Turn off readahead. Most operating systems perform readahead on read requests by"]
#[doc="default. This option turns it off if the OS supports it. Turning it off may help"]
#[doc="random read performance when the DB is larger than RAM and system RAM is full."]
#[doc="The option is not implemented on Windows."]
const NO_READAHEAD = 0x800000,
const NO_READAHEAD = MDB_NORDAHEAD,
#[doc="Do not initialize malloc'd memory before writing to unused spaces in the data file."]
#[doc="By default, memory for pages written to the data file is obtained using malloc."]
@ -92,12 +94,12 @@ bitflags! {
#[doc="initialization step has a modest performance cost so some applications may want to"]
#[doc="disable it using this flag. This option can be a problem for applications which"]
#[doc="handle sensitive data like passwords, and it makes memory checkers like Valgrind"]
#[doc="noisy. This flag is not needed with `WRITEMAP`, which writes directly to the mmap"]
#[doc="noisy. This flag is not needed with `WRITE_MAP`, which writes directly to the mmap"]
#[doc="instead of using malloc for pages. The initialization is also skipped if writing"]
#[doc="with reserve; the caller is expected to overwrite all of the memory that was"]
#[doc="reserved in that case."]
#[doc="\n\nThis flag may be changed at any time using `Environment::set_flags`."]
const NO_MEM_INIT = 0x1000000,
const NO_MEM_INIT = MDB_NOMEMINIT,
}
}
@ -109,31 +111,31 @@ bitflags! {
#[doc="Keys are strings to be compared in reverse order, from the end of the strings"]
#[doc="to the beginning. By default, Keys are treated as strings and compared from"]
#[doc="beginning to end."]
const REVERSE_KEY = 0x02,
const REVERSE_KEY = MDB_REVERSEKEY,
#[doc="Duplicate keys may be used in the database. (Or, from another perspective,"]
#[doc="keys may have multiple data items, stored in sorted order.) By default"]
#[doc="keys must be unique and may have only a single data item."]
const DUP_SORT = 0x04,
const DUP_SORT = MDB_DUPSORT,
#[doc="Keys are binary integers in native byte order. Setting this option requires all"]
#[doc="keys to be the same size, typically 32 or 64 bits."]
const INTEGER_KEY = 0x08,
const INTEGER_KEY = MDB_INTEGERKEY,
#[doc="This flag may only be used in combination with `DUP_SORT`. This option tells"]
#[doc="the library that the data items for this database are all the same size, which"]
#[doc="allows further optimizations in storage and retrieval. When all data items are"]
#[doc="the same size, the `GET_MULTIPLE` and `NEXT_MULTIPLE` cursor operations may be"]
#[doc="used to retrieve multiple items at once."]
const DUP_FIXED = 0x10,
const DUP_FIXED = MDB_DUPFIXED,
#[doc="This option specifies that duplicate data items are also integers, and"]
#[doc="should be sorted as such."]
const INTEGER_DUP = 0x20,
const INTEGER_DUP = MDB_INTEGERDUP,
#[doc="This option specifies that duplicate data items should be compared as strings"]
#[doc="in reverse order."]
const REVERSE_DUP = 0x40,
const REVERSE_DUP = MDB_REVERSEDUP,
}
}
@ -145,27 +147,27 @@ bitflags! {
#[doc="Insert the new item only if the key does not already appear in the database."]
#[doc="The function will return `LmdbError::KeyExist` if the key already appears in the"]
#[doc="database, even if the database supports duplicates (`DUP_SORT`)."]
const NO_OVERWRITE = 0x10,
const NO_OVERWRITE = MDB_NOOVERWRITE,
#[doc="Insert the new item only if it does not already appear in the database."]
#[doc="This flag may only be specified if the database was opened with `DUP_SORT`."]
#[doc="The function will return `LmdbError::KeyExist` if the item already appears in the"]
#[doc="database."]
const NO_DUP_DATA = 0x20,
const NO_DUP_DATA = MDB_NODUPDATA,
#[doc="For `Cursor::put`. Replace the item at the current cursor position. The key"]
#[doc="parameter must match the current position. If using sorted duplicates (`DUP_SORT`)"]
#[doc="the data item must still sort into the same position. This is intended to be used"]
#[doc="when the new data is the same size as the old. Otherwise it will simply perform a"]
#[doc="delete of the old record followed by an insert."]
const CURRENT = 0x40,
const CURRENT = MDB_CURRENT,
#[doc="Append the given item to the end of the database. No key comparisons are performed."]
#[doc="This option allows fast bulk loading when keys are already known to be in the"]
#[doc="correct order. Loading unsorted keys with this flag will cause data corruption."]
const APPEND = 0x20000,
const APPEND = MDB_APPEND,
#[doc="Same as `APPEND`, but for sorted dup data."]
const APPEND_DUP = 0x40000,
const APPEND_DUP = MDB_APPENDDUP,
}
}

Loading…
Cancel
Save