From 7517b13d92b0b9c746f163e6f79b2eaf6a25fe2c Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 11 Jul 2016 17:39:39 -0700 Subject: [PATCH 01/32] Expose lmdb::Iter publicly (#8) I'm trying to make a newtype wrapper around it, and can't because it's in `lmdb::cursor`, which isn't public. --- src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 6e89c0d..114989e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,8 @@ extern crate lmdb_sys as ffi; pub use cursor::{ Cursor, RoCursor, - RwCursor + RwCursor, + Iter }; pub use database::Database; pub use environment::{Environment, EnvironmentBuilder}; From 9b5d48c89aed611bd233c2c415793d6dc77b94d9 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Mon, 11 Jul 2016 22:10:25 -0700 Subject: [PATCH 02/32] make IterDup public --- src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 114989e..60533f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,7 +15,8 @@ pub use cursor::{ Cursor, RoCursor, RwCursor, - Iter + Iter, + IterDup, }; pub use database::Database; pub use environment::{Environment, EnvironmentBuilder}; From 0d20eb4b595c8713c0ee69aa9472220d46bf2129 Mon Sep 17 00:00:00 2001 From: Chip Collier Date: Sun, 17 Jul 2016 21:52:34 +0200 Subject: [PATCH 03/32] tweaks to enable windows builds with msvc (#9) --- lmdb-sys/src/ffi.rs | 2 +- lmdb-sys/src/lib.rs | 7 +++++++ src/environment.rs | 19 +++++++++++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/lmdb-sys/src/ffi.rs b/lmdb-sys/src/ffi.rs index 44d71cf..a998ea2 100644 --- a/lmdb-sys/src/ffi.rs +++ b/lmdb-sys/src/ffi.rs @@ -62,7 +62,7 @@ extern "C" { pub fn mdb_version(major: *mut ::libc::c_int, minor: *mut ::libc::c_int, patch: *mut ::libc::c_int) -> *mut ::libc::c_char; pub fn mdb_strerror(err: ::libc::c_int) -> *mut ::libc::c_char; pub fn mdb_env_create(env: *mut *mut MDB_env) -> ::libc::c_int; - pub fn mdb_env_open(env: *mut MDB_env, path: *const ::libc::c_char, flags: ::libc::c_uint, mode: ::libc::mode_t) -> ::libc::c_int; + pub fn mdb_env_open(env: *mut MDB_env, path: *const ::libc::c_char, flags: ::libc::c_uint, mode: super::mode_t) -> ::libc::c_int; pub fn mdb_env_copy(env: *mut MDB_env, path: *const ::libc::c_char) -> ::libc::c_int; pub fn mdb_env_copyfd(env: *mut MDB_env, fd: ::libc::c_int) -> ::libc::c_int; pub fn mdb_env_copy2(env: *mut MDB_env, path: *const ::libc::c_char, flags: ::libc::c_uint) -> ::libc::c_int; diff --git a/lmdb-sys/src/lib.rs b/lmdb-sys/src/lib.rs index 217fd92..92e681a 100644 --- a/lmdb-sys/src/lib.rs +++ b/lmdb-sys/src/lib.rs @@ -2,6 +2,13 @@ extern crate libc; +#[cfg(unix)] +#[allow(non_camel_case_types)] +pub type mode_t = ::libc::mode_t; +#[cfg(windows)] +#[allow(non_camel_case_types)] +pub type mode_t = ::libc::c_int; + pub use constants::*; pub use ffi::*; diff --git a/src/environment.rs b/src/environment.rs index 8d48654..a2ebdcc 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -1,6 +1,9 @@ -use libc::{c_uint, size_t, mode_t}; +use libc::{c_uint, size_t}; use std::ffi::CString; +#[cfg(unix)] use std::os::unix::ffi::OsStrExt; +#[cfg(windows)] +use std::ffi::OsStr; use std::path::Path; use std::ptr; use std::sync::Mutex; @@ -12,6 +15,18 @@ use database::Database; use transaction::{RoTransaction, RwTransaction, Transaction}; use flags::{DatabaseFlags, EnvironmentFlags}; +#[cfg(windows)] +/// Adding a 'missing' trait from windows OsStrExt +trait OsStrExtLmdb { + fn as_bytes(&self) -> &[u8]; +} +#[cfg(windows)] +impl OsStrExtLmdb for OsStr { + fn as_bytes(&self) -> &[u8] { + &self.to_str().unwrap().as_bytes() + } +} + /// An LMDB environment. /// /// An environment supports multiple databases, all residing in the same shared-memory map. @@ -176,7 +191,7 @@ impl EnvironmentBuilder { /// On Windows, the permissions will be ignored. /// /// The path may not contain the null character. - pub fn open_with_permissions(&self, path: &Path, mode: mode_t) -> Result { + pub fn open_with_permissions(&self, path: &Path, mode: ffi::mode_t) -> Result { let mut env: *mut ffi::MDB_env = ptr::null_mut(); unsafe { lmdb_try!(ffi::mdb_env_create(&mut env)); From c43a2ee7933964b524eee1151fa91121ac3b7561 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sun, 17 Jul 2016 13:03:07 -0700 Subject: [PATCH 04/32] appveyor --- .appveyor.yml | 21 +++++++++++++++++++++ README.md | 1 + 2 files changed, 22 insertions(+) create mode 100644 .appveyor.yml diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 0000000..7af942b --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,21 @@ +environment: + matrix: + - TARGET: x86_64-pc-windows-msvc + - TARGET: i686-pc-windows-msvc + #- TARGET: x86_64-pc-windows-gnu + #- TARGET: i686-pc-windows-gnu + +install: + - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" -FileName "rust-install.exe" + - ps: .\rust-install.exe /VERYSILENT /NORESTART /DIR="C:\rust" | Out-Null + - ps: $env:PATH="$env:PATH;C:\rust\bin" + - rustc -vV + - cargo -vV + +build_script: + - git submodule -q update --init + - cargo build -v + +test_script: + - SET RUST_BACKTRACE=1 + - cargo test -v diff --git a/README.md b/README.md index 43f91a1..0f47882 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ [![Build Status](https://travis-ci.org/danburkert/lmdb-rs.svg?branch=master)](https://travis-ci.org/danburkert/lmdb-rs) +[![Windows Build Status](https://ci.appveyor.com/api/projects/status/0bw21yfqsrsv3soh/branch/master?svg=true)](https://ci.appveyor.com/project/danburkert/lmdb-rs/branch/master) [Documentation](http://danburkert.github.io/lmdb-rs/lmdb/index.html) From 473173d14a6cae12bf8363814ae59281b614a16a Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sun, 17 Jul 2016 13:33:03 -0700 Subject: [PATCH 05/32] bump bitflags version --- .travis.yml | 2 +- Cargo.toml | 2 +- src/flags.rs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 64d9a5c..d19b2fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: rust sudo: false rust: -- 1.2.0 +- 1.8.0 - nightly os: diff --git a/Cargo.toml b/Cargo.toml index 8c32d77..359e7b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ path = "lmdb-sys" version = "0.5.0" [dependencies] -bitflags = "0.4" +bitflags = "0.7" libc = "0.2" [dev-dependencies] diff --git a/src/flags.rs b/src/flags.rs index 01f277e..adcd913 100644 --- a/src/flags.rs +++ b/src/flags.rs @@ -4,7 +4,7 @@ use ffi::*; bitflags! { #[doc="Environment Options"] - flags EnvironmentFlags: c_uint { + pub flags EnvironmentFlags: c_uint { #[doc="Use a fixed address for the mmap region. This flag must be specified"] #[doc="when creating the environment, and is stored persistently in the environment."] @@ -104,7 +104,7 @@ bitflags! { bitflags! { #[doc="Database Options"] - flags DatabaseFlags: c_uint { + pub flags DatabaseFlags: c_uint { #[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"] @@ -139,7 +139,7 @@ bitflags! { bitflags! { #[doc="Write Options"] - flags WriteFlags: c_uint { + pub flags WriteFlags: c_uint { #[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"] From 83b1d33fde128991f4ad95854ac7d172e90db987 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sun, 17 Jul 2016 13:33:41 -0700 Subject: [PATCH 06/32] 0.6.0 --- Cargo.toml | 4 ++-- lmdb-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 359e7b0..1c08a41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lmdb" -version = "0.5.0" +version = "0.6.0" authors = ["Dan Burkert "] license = "Apache-2.0" @@ -13,7 +13,7 @@ documentation = "http://danburkert.github.io/lmdb-rs/lmdb/index.html" [dependencies.lmdb-sys] path = "lmdb-sys" -version = "0.5.0" +version = "0.6.0" [dependencies] bitflags = "0.7" diff --git a/lmdb-sys/Cargo.toml b/lmdb-sys/Cargo.toml index cf6d02d..47dfe6d 100644 --- a/lmdb-sys/Cargo.toml +++ b/lmdb-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lmdb-sys" -version = "0.5.0" +version = "0.6.0" authors = ["Dan Burkert "] license = "Apache-2.0" description = "Rust bindings for liblmdb." From 2e36a93c615e752264cc8e93f522243ee9b6d0de Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Thu, 21 Jul 2016 00:12:32 +0700 Subject: [PATCH 07/32] Fix typo. (#10) --- src/flags.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flags.rs b/src/flags.rs index adcd913..23d417d 100644 --- a/src/flags.rs +++ b/src/flags.rs @@ -61,7 +61,7 @@ bitflags! { 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"] + #[doc="instead of to threads. I.e. `RoTransaction::reset` keeps the slot reserved for the"] #[doc="transaction object. A thread may use parallel read-only transactions. A read-only"] #[doc="transaction may span threads if the user synchronizes its use. Applications that"] #[doc="multiplex many the user synchronizes its use. Applications that multiplex many user"] From 14a5332e966c8357403ba481d1696e144dcc6d88 Mon Sep 17 00:00:00 2001 From: "Craig M. Brandenburg" Date: Sun, 25 Jun 2017 10:21:26 -0700 Subject: [PATCH 08/32] Disable rustfmt by default (#14) This effects issue #11. --- .rustfmt.toml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .rustfmt.toml diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..c7ad93b --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1 @@ +disable_all_formatting = true From de8bdbd8900933a1bf92dd8da0fda67de7414a44 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sun, 25 Jun 2017 11:46:16 -0700 Subject: [PATCH 09/32] Bump LMDB to 0.9.21 --- lmdb-sys/lmdb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lmdb-sys/lmdb b/lmdb-sys/lmdb index ad8488c..60d5002 160000 --- a/lmdb-sys/lmdb +++ b/lmdb-sys/lmdb @@ -1 +1 @@ -Subproject commit ad8488cfac644d7a289e428ab3c403c859d844cb +Subproject commit 60d500206a108b2c64ca7e36b0113b2cd3711b98 From 2c43e693e65ca16476780bdd8442c5e1cb933022 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sun, 25 Jun 2017 12:04:45 -0700 Subject: [PATCH 10/32] Fix potential use-after-free Clippy pointed out this potential use-after-free of a CString buffer. I don't think in this case it caused an issue because the temporary CString _should_ outlive the function call (at least, that's how C++ works...), however it's refactor-brittle, so best to fix. https://github.com/Manishearth/rust-clippy/wiki#temporary_cstring_as_ptr --- src/cursor.rs | 1 - src/environment.rs | 11 ++++++----- src/error.rs | 1 - 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/cursor.rs b/src/cursor.rs index 7bc8ce4..aa26746 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -290,7 +290,6 @@ mod test { use flags::*; use super::*; use test_utils::*; - use transaction::*; #[test] fn test_get() { diff --git a/src/environment.rs b/src/environment.rs index a2ebdcc..5962f3a 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -1,5 +1,5 @@ use libc::{c_uint, size_t}; -use std::ffi::CString; +use std::ffi::{CString, NulError}; #[cfg(unix)] use std::os::unix::ffi::OsStrExt; #[cfg(windows)] @@ -207,10 +207,11 @@ impl EnvironmentBuilder { lmdb_try_with_cleanup!(ffi::mdb_env_set_mapsize(env, map_size), ffi::mdb_env_close(env)) } - lmdb_try_with_cleanup!(ffi::mdb_env_open(env, - CString::new(path.as_os_str().as_bytes()).unwrap().as_ptr(), - self.flags.bits(), - mode), + let path = match CString::new(path.as_os_str().as_bytes()) { + Ok(path) => path, + Err(NulError { .. }) => 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)); } Ok(Environment { env: env, dbi_open_mutex: Mutex::new(()) }) diff --git a/src/error.rs b/src/error.rs index 5f73391..7907c40 100644 --- a/src/error.rs +++ b/src/error.rs @@ -145,5 +145,4 @@ mod test { assert_eq!("MDB_NOTFOUND: No matching key/data pair found", Error::NotFound.description()); } - } From 76f000df0746be0fd4bf9416a16c9ed711359bc2 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sun, 25 Jun 2017 12:16:19 -0700 Subject: [PATCH 11/32] Remove NulError For whatever reason, the 1.8.0 toolchain isn't happy with NulError. It wasn't necessary anyway. --- src/environment.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/environment.rs b/src/environment.rs index 5962f3a..80251d1 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -1,5 +1,5 @@ use libc::{c_uint, size_t}; -use std::ffi::{CString, NulError}; +use std::ffi::CString; #[cfg(unix)] use std::os::unix::ffi::OsStrExt; #[cfg(windows)] @@ -209,7 +209,7 @@ impl EnvironmentBuilder { } let path = match CString::new(path.as_os_str().as_bytes()) { Ok(path) => path, - Err(NulError { .. }) => return Err(::Error::Invalid), + 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)); From f6343a283a07dc3cc701e58329005c986dc437af Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sun, 25 Jun 2017 12:35:47 -0700 Subject: [PATCH 12/32] Update crate metadata and CI --- .appveyor.yml | 21 ++++++++++++--------- .travis.yml | 30 ++++++++++-------------------- Cargo.toml | 10 ++++++---- README.md | 8 +++----- lmdb-sys/Cargo.toml | 5 ++++- 5 files changed, 35 insertions(+), 39 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 7af942b..cad9135 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -2,20 +2,23 @@ environment: matrix: - TARGET: x86_64-pc-windows-msvc - TARGET: i686-pc-windows-msvc - #- TARGET: x86_64-pc-windows-gnu - #- TARGET: i686-pc-windows-gnu + - TARGET: x86_64-pc-windows-gnu + MSYS_BITS: 64 + - TARGET: i686-pc-windows-gnu + MSYS_BITS: 32 install: - - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" -FileName "rust-install.exe" - - ps: .\rust-install.exe /VERYSILENT /NORESTART /DIR="C:\rust" | Out-Null - - ps: $env:PATH="$env:PATH;C:\rust\bin" - - rustc -vV - - cargo -vV + - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" + - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" + - set PATH=%PATH%;C:\Program Files (x86)\Rust\bin + - if defined MSYS_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS_BITS%\bin + - rustc -V + - cargo -V build_script: - git submodule -q update --init - - cargo build -v + - cargo build --target %TARGET% --all -v test_script: - SET RUST_BACKTRACE=1 - - cargo test -v + - cargo test --target %TARGET% --all -v diff --git a/.travis.yml b/.travis.yml index d19b2fc..2526a2c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,30 +1,20 @@ language: rust +dist: trusty sudo: false -rust: -- 1.8.0 -- nightly +cache: cargo os: - linux - osx -before_script: - - pip install 'travis-cargo<0.2' --user - - export PATH=$HOME/.local/bin:$PATH # Linux - - export PATH=$HOME/Library/Python/2.7/bin:$PATH # OS X +rust: +- 1.8.0 +- stable +- nightly script: - - | - travis-cargo build && - travis-cargo --only nightly test && - travis-cargo bench && - travis-cargo --only nightly doc - -after_success: - - travis-cargo --only nightly doc-upload - -env: - global: - - TRAVIS_CARGO_NIGHTLY_FEATURE="" - - secure: "BCsYNBS56hCKCMBZFLYDxKk3+UbFkAt+JRpPG9aiQyTVGkVqXNm4jPhiNSc4/JMuxoBVne+EzUrKVgdv3D7jTOx0sPsWEiE/oFK1K+6xusvsA87ZdDBC0hTRMiEHaufgtaGFJNwWW2tLzwlcdzvGUPVGYogao2MAxl1xlpppvso=" + - cargo build --verbose + - if [[ $TRAVIS_RUST_VERSION = nightly* ]]; then + env RUST_BACKTRACE=1 cargo test --all -v; + fi diff --git a/Cargo.toml b/Cargo.toml index 1c08a41..7302c98 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,16 +8,18 @@ license = "Apache-2.0" description = "Idiomatic and safe LMDB wrapper." repository = "https://github.com/danburkert/lmdb-rs.git" readme = "README.md" +documentation = "https://docs.rs/lmdb" keywords = ["LMDB", "database", "storage-engine", "bindings", "library"] -documentation = "http://danburkert.github.io/lmdb-rs/lmdb/index.html" +categories = ["database"] -[dependencies.lmdb-sys] -path = "lmdb-sys" -version = "0.6.0" +[badges] +travis-ci = { repository = "danburkert/lmdb-rs" } +appveyor = { repository = "danburkert/lmdb-rs" } [dependencies] bitflags = "0.7" libc = "0.2" +lmdb-sys = { path = "lmdb-sys" } [dev-dependencies] rand = "0.3" diff --git a/README.md b/README.md index 0f47882..fbe6a0a 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,7 @@ [![Build Status](https://travis-ci.org/danburkert/lmdb-rs.svg?branch=master)](https://travis-ci.org/danburkert/lmdb-rs) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/0bw21yfqsrsv3soh/branch/master?svg=true)](https://ci.appveyor.com/project/danburkert/lmdb-rs/branch/master) - -[Documentation](http://danburkert.github.io/lmdb-rs/lmdb/index.html) - -[Cargo](https://crates.io/crates/lmdb) +[![Documentation](https://docs.rs/lmdb/badge.svg)](https://docs.rs/lmdb/) +[![Crate](https://img.shields.io/crates/v/lmdb.svg)](https://crates.io/crates/lmdb) # lmdb-rs @@ -23,5 +21,5 @@ cargo build * [x] lmdb-sys. * [x] Cursors. * [x] Zero-copy put API. -* [ ] Nested transactions. +* [x] Nested transactions. * [ ] Database statistics. diff --git a/lmdb-sys/Cargo.toml b/lmdb-sys/Cargo.toml index 47dfe6d..6f625f1 100644 --- a/lmdb-sys/Cargo.toml +++ b/lmdb-sys/Cargo.toml @@ -4,10 +4,13 @@ name = "lmdb-sys" version = "0.6.0" authors = ["Dan Burkert "] license = "Apache-2.0" + description = "Rust bindings for liblmdb." repository = "https://github.com/danburkert/lmdb-rs.git" readme = "../README.md" -documentation = "http://danburkert.github.io/lmdb-rs/lmdb_sys/index.html" +documentation = "https://docs.rs/lmdb-sys" +keywords = ["LMDB", "database", "storage-engine", "bindings", "library"] +categories = ["database", "external-ffi-bindings"] build = "build.rs" From 8d23b1acca3d449b1871025ee04289ad517cd340 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sun, 25 Jun 2017 14:17:29 -0700 Subject: [PATCH 13/32] Bump bitflags to 0.9 --- Cargo.toml | 2 +- src/flags.rs | 50 +++++++++++++++++++++++++------------------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7302c98..e8412c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ travis-ci = { repository = "danburkert/lmdb-rs" } appveyor = { repository = "danburkert/lmdb-rs" } [dependencies] -bitflags = "0.7" +bitflags = "0.9" libc = "0.2" lmdb-sys = { path = "lmdb-sys" } diff --git a/src/flags.rs b/src/flags.rs index 23d417d..13d52f0 100644 --- a/src/flags.rs +++ b/src/flags.rs @@ -4,7 +4,7 @@ use ffi::*; bitflags! { #[doc="Environment Options"] - pub flags EnvironmentFlags: c_uint { + pub struct EnvironmentFlags: c_uint { #[doc="Use a fixed address for the mmap region. This flag must be specified"] #[doc="when creating the environment, and is stored persistently in the environment."] @@ -13,25 +13,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 = MDB_FIXEDMAP, + 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 = MDB_NOSUBDIR, + 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 `WRITE_MAP` on the same environment do not cooperate"] #[doc="well."] - const WRITE_MAP = MDB_WRITEMAP, + 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 = MDB_RDONLY, + 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"] @@ -39,7 +39,7 @@ 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 = MDB_NOMETASYNC, + 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"] @@ -52,13 +52,13 @@ bitflags! { #[doc="system with no hint for when to write transactions to disk, unless"] #[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 = MDB_NOSYNC, + const NO_SYNC = MDB_NOSYNC; #[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 = MDB_MAPASYNC, + 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 reserved for the"] @@ -68,20 +68,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 = MDB_NOTLS, + 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 = MDB_NOLOCK, + 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 = MDB_NORDAHEAD, + 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."] @@ -98,73 +98,73 @@ bitflags! { #[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 = MDB_NOMEMINIT, + const NO_MEM_INIT = MDB_NOMEMINIT; } } bitflags! { #[doc="Database Options"] - pub flags DatabaseFlags: c_uint { + pub struct DatabaseFlags: c_uint { #[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 = MDB_REVERSEKEY, + 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 = MDB_DUPSORT, + 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 = MDB_INTEGERKEY, + 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 = MDB_DUPFIXED, + 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 = MDB_INTEGERDUP, + 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 = MDB_REVERSEDUP, + const REVERSE_DUP = MDB_REVERSEDUP; } } bitflags! { #[doc="Write Options"] - pub flags WriteFlags: c_uint { + pub struct WriteFlags: c_uint { #[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 = MDB_NOOVERWRITE, + 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 = MDB_NODUPDATA, + 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 = MDB_CURRENT, + 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 = MDB_APPEND, + const APPEND = MDB_APPEND; #[doc="Same as `APPEND`, but for sorted dup data."] - const APPEND_DUP = MDB_APPENDDUP, + const APPEND_DUP = MDB_APPENDDUP; } } From fc92971dcac24d4e88b5b9c612c70889e8b3ffbc Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sun, 25 Jun 2017 14:28:50 -0700 Subject: [PATCH 14/32] Add crate doc root https://github.com/brson/rust-api-guidelines#c-html-root --- Cargo.toml | 1 + lmdb-sys/Cargo.toml | 1 + lmdb-sys/src/lib.rs | 2 ++ src/lib.rs | 2 ++ 4 files changed, 6 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index e8412c9..d9fb76a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "lmdb" +# NB: When modifying, also modify html_root_url in lib.rs version = "0.6.0" authors = ["Dan Burkert "] license = "Apache-2.0" diff --git a/lmdb-sys/Cargo.toml b/lmdb-sys/Cargo.toml index 6f625f1..67b12f3 100644 --- a/lmdb-sys/Cargo.toml +++ b/lmdb-sys/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "lmdb-sys" +# NB: When modifying, also modify html_root_url in lib.rs version = "0.6.0" authors = ["Dan Burkert "] license = "Apache-2.0" diff --git a/lmdb-sys/src/lib.rs b/lmdb-sys/src/lib.rs index 92e681a..55d1a2c 100644 --- a/lmdb-sys/src/lib.rs +++ b/lmdb-sys/src/lib.rs @@ -1,4 +1,6 @@ #![allow(non_camel_case_types)] +#![deny(warnings)] +#![doc(html_root_url = "https://docs.rs/lmdb-sys/0.6.0")] extern crate libc; diff --git a/src/lib.rs b/src/lib.rs index 60533f3..442b558 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,8 @@ //! [Symas Lightning Memory-Mapped Database (LMDB)](http://symas.com/mdb/). #![cfg_attr(test, feature(test))] +#![deny(warnings)] +#![doc(html_root_url = "https://docs.rs/lmdb/0.6.0")] extern crate libc; extern crate lmdb_sys as ffi; From 15fe40a8e3372c1df6bbdce9ce56fee09209a5f7 Mon Sep 17 00:00:00 2001 From: "Craig M. Brandenburg" Date: Sun, 2 Jul 2017 18:02:59 -0700 Subject: [PATCH 15/32] Implement Debug for public types (#16) --- src/cursor.rs | 26 +++++++++++++++++++++++++- src/environment.rs | 8 +++++++- src/transaction.rs | 20 +++++++++++++++++++- 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/cursor.rs b/src/cursor.rs index aa26746..b3f59a2 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -1,5 +1,5 @@ use libc::{c_void, size_t, c_uint}; -use std::{ptr, slice}; +use std::{fmt, ptr, result, slice}; use std::marker::PhantomData; use database::Database; @@ -108,6 +108,12 @@ impl <'txn> Cursor<'txn> 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> { fn drop(&mut self) { unsafe { ffi::mdb_cursor_close(self.cursor) } @@ -141,6 +147,12 @@ impl <'txn> Cursor<'txn> 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> { fn drop(&mut self) { unsafe { ffi::mdb_cursor_close(self.cursor) } @@ -217,6 +229,12 @@ impl <'txn> 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> { type Item = (&'txn [u8], &'txn [u8]); @@ -257,6 +275,12 @@ impl <'txn> 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> { type Item = Iter<'txn>; diff --git a/src/environment.rs b/src/environment.rs index 80251d1..c800bd5 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -1,11 +1,11 @@ use libc::{c_uint, size_t}; +use std::{fmt, ptr, result}; use std::ffi::CString; #[cfg(unix)] use std::os::unix::ffi::OsStrExt; #[cfg(windows)] use std::ffi::OsStr; use std::path::Path; -use std::ptr; use std::sync::Mutex; use ffi; @@ -156,6 +156,12 @@ impl Environment { unsafe impl Send for Environment {} unsafe impl Sync for Environment {} +impl fmt::Debug for Environment { + fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { + f.debug_struct("Environment").finish() + } +} + impl Drop for Environment { fn drop(&mut self) { unsafe { ffi::mdb_env_close(self.env) } diff --git a/src/transaction.rs b/src/transaction.rs index ab481a4..b5278d8 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -1,5 +1,5 @@ use libc::{c_uint, c_void, size_t}; -use std::{mem, ptr, slice}; +use std::{fmt, mem, ptr, result, slice}; use std::marker::PhantomData ; use ffi; @@ -110,6 +110,12 @@ pub struct RoTransaction<'env> { _marker: PhantomData<&'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> { fn drop(&mut self) { unsafe { ffi::mdb_txn_abort(self.txn) } @@ -166,6 +172,12 @@ pub struct InactiveTransaction<'env> { _marker: PhantomData<&'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> { fn drop(&mut self) { unsafe { ffi::mdb_txn_abort(self.txn) } @@ -195,6 +207,12 @@ pub struct RwTransaction<'env> { _marker: PhantomData<&'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> { fn drop(&mut self) { unsafe { ffi::mdb_txn_abort(self.txn) } From 64ae95ba163a3fa2542aefecc348ddcf9711643c Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sun, 2 Jul 2017 18:11:56 -0700 Subject: [PATCH 16/32] 0.7.0 --- Cargo.toml | 4 ++-- lmdb-sys/Cargo.toml | 2 +- lmdb-sys/src/lib.rs | 2 +- src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d9fb76a..109103f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "lmdb" # NB: When modifying, also modify html_root_url in lib.rs -version = "0.6.0" +version = "0.7.0" authors = ["Dan Burkert "] license = "Apache-2.0" @@ -20,7 +20,7 @@ appveyor = { repository = "danburkert/lmdb-rs" } [dependencies] bitflags = "0.9" libc = "0.2" -lmdb-sys = { path = "lmdb-sys" } +lmdb-sys = "0.7" [dev-dependencies] rand = "0.3" diff --git a/lmdb-sys/Cargo.toml b/lmdb-sys/Cargo.toml index 67b12f3..b153047 100644 --- a/lmdb-sys/Cargo.toml +++ b/lmdb-sys/Cargo.toml @@ -2,7 +2,7 @@ name = "lmdb-sys" # NB: When modifying, also modify html_root_url in lib.rs -version = "0.6.0" +version = "0.7.0" authors = ["Dan Burkert "] license = "Apache-2.0" diff --git a/lmdb-sys/src/lib.rs b/lmdb-sys/src/lib.rs index 55d1a2c..1e853b4 100644 --- a/lmdb-sys/src/lib.rs +++ b/lmdb-sys/src/lib.rs @@ -1,6 +1,6 @@ #![allow(non_camel_case_types)] #![deny(warnings)] -#![doc(html_root_url = "https://docs.rs/lmdb-sys/0.6.0")] +#![doc(html_root_url = "https://docs.rs/lmdb-sys/0.7.0")] extern crate libc; diff --git a/src/lib.rs b/src/lib.rs index 442b558..5f78ca7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ #![cfg_attr(test, feature(test))] #![deny(warnings)] -#![doc(html_root_url = "https://docs.rs/lmdb/0.6.0")] +#![doc(html_root_url = "https://docs.rs/lmdb/0.7.0")] extern crate libc; extern crate lmdb_sys as ffi; From 37b241c7b6d659a9a85d00f05bea757cbc3641ff Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sun, 2 Jul 2017 18:26:00 -0700 Subject: [PATCH 17/32] reset lmdb-sys path-dep for next cycle --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 109103f..54a62ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ appveyor = { repository = "danburkert/lmdb-rs" } [dependencies] bitflags = "0.9" libc = "0.2" -lmdb-sys = "0.7" +lmdb-sys = { path = "lmdb-sys" } [dev-dependencies] rand = "0.3" From 4b9327818283b20d18207d9d56fa76f5346ff267 Mon Sep 17 00:00:00 2001 From: Sam Rijs Date: Sun, 16 Jul 2017 00:48:52 +0200 Subject: [PATCH 18/32] case mdb_strerror output to *const c_char (#19) --- src/error.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/error.rs b/src/error.rs index 7907c40..12fc2bb 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,6 +1,7 @@ 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 ffi; @@ -115,7 +116,7 @@ impl StdError for Error { fn description(&self) -> &str { unsafe { // This is safe since the error messages returned from mdb_strerror are static. - let err: *const i8 = ffi::mdb_strerror(self.to_err_code()) as *const i8; + let err: *const c_char = ffi::mdb_strerror(self.to_err_code()) as *const c_char; str::from_utf8_unchecked(CStr::from_ptr(err).to_bytes()) } } From b2efebf54a1bb2411a63f2f1831d79c9e82db955 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sat, 15 Jul 2017 15:55:35 -0700 Subject: [PATCH 19/32] 0.7.1 --- Cargo.toml | 4 ++-- lmdb-sys/Cargo.toml | 2 +- lmdb-sys/src/lib.rs | 2 +- src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 54a62ed..66d4d3a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "lmdb" # NB: When modifying, also modify html_root_url in lib.rs -version = "0.7.0" +version = "0.7.1" authors = ["Dan Burkert "] license = "Apache-2.0" @@ -20,7 +20,7 @@ appveyor = { repository = "danburkert/lmdb-rs" } [dependencies] bitflags = "0.9" libc = "0.2" -lmdb-sys = { path = "lmdb-sys" } +lmdb-sys = "0.7.1" [dev-dependencies] rand = "0.3" diff --git a/lmdb-sys/Cargo.toml b/lmdb-sys/Cargo.toml index b153047..79300a1 100644 --- a/lmdb-sys/Cargo.toml +++ b/lmdb-sys/Cargo.toml @@ -2,7 +2,7 @@ name = "lmdb-sys" # NB: When modifying, also modify html_root_url in lib.rs -version = "0.7.0" +version = "0.7.1" authors = ["Dan Burkert "] license = "Apache-2.0" diff --git a/lmdb-sys/src/lib.rs b/lmdb-sys/src/lib.rs index 1e853b4..4092a53 100644 --- a/lmdb-sys/src/lib.rs +++ b/lmdb-sys/src/lib.rs @@ -1,6 +1,6 @@ #![allow(non_camel_case_types)] #![deny(warnings)] -#![doc(html_root_url = "https://docs.rs/lmdb-sys/0.7.0")] +#![doc(html_root_url = "https://docs.rs/lmdb-sys/0.7.1")] extern crate libc; diff --git a/src/lib.rs b/src/lib.rs index 5f78ca7..3fe40b4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ #![cfg_attr(test, feature(test))] #![deny(warnings)] -#![doc(html_root_url = "https://docs.rs/lmdb/0.7.0")] +#![doc(html_root_url = "https://docs.rs/lmdb/0.7.1")] extern crate libc; extern crate lmdb_sys as ffi; From ee5968dd2538bcb616a4f6994db40899a476da91 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sun, 2 Jul 2017 18:26:00 -0700 Subject: [PATCH 20/32] reset lmdb-sys path-dep for next cycle --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 66d4d3a..6d802aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ appveyor = { repository = "danburkert/lmdb-rs" } [dependencies] bitflags = "0.9" libc = "0.2" -lmdb-sys = "0.7.1" +lmdb-sys = { path = "lmdb-sys" } [dev-dependencies] rand = "0.3" From 547841a3e287c96e734532114bf5d7cfb7d4a29c Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sat, 9 Sep 2017 10:52:17 -0700 Subject: [PATCH 21/32] Compile lmdb with opt level O2 LMDB segfaults reliably with newer GCC versions when compiled with O3. Regression test included. fixes #21 --- .travis.yml | 1 + Cargo.toml | 1 + lmdb-sys/Cargo.toml | 3 ++- lmdb-sys/build.rs | 16 ++++++---------- src/lib.rs | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 42 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2526a2c..d9212d5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,4 +17,5 @@ script: - cargo build --verbose - if [[ $TRAVIS_RUST_VERSION = nightly* ]]; then env RUST_BACKTRACE=1 cargo test --all -v; + env RUST_BACKTRACE=1 cargo test --all -v --release; fi diff --git a/Cargo.toml b/Cargo.toml index 6d802aa..df3d8fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,3 +25,4 @@ lmdb-sys = { path = "lmdb-sys" } [dev-dependencies] rand = "0.3" tempdir = "0.3" +byteorder = "1.0" diff --git a/lmdb-sys/Cargo.toml b/lmdb-sys/Cargo.toml index 79300a1..5a8dd4e 100644 --- a/lmdb-sys/Cargo.toml +++ b/lmdb-sys/Cargo.toml @@ -20,4 +20,5 @@ libc = "0.2" [build-dependencies] pkg-config = "0.3" -gcc = "0.3" +# https://github.com/alexcrichton/gcc-rs/issues/240 +gcc = "=0.3.51" diff --git a/lmdb-sys/build.rs b/lmdb-sys/build.rs index 36332d5..fd9e98e 100644 --- a/lmdb-sys/build.rs +++ b/lmdb-sys/build.rs @@ -5,21 +5,17 @@ use std::env; use std::path::PathBuf; fn main() { - let mut lmdb: PathBuf = PathBuf::from(&env::var("CARGO_MANIFEST_DIR").unwrap()); lmdb.push("lmdb"); lmdb.push("libraries"); lmdb.push("liblmdb"); - let mut mdb: PathBuf = lmdb.clone(); - let mut midl: PathBuf = lmdb.clone(); - - mdb.push("mdb.c"); - midl.push("midl.c"); - if !pkg_config::find_library("liblmdb").is_ok() { - gcc::compile_library("liblmdb.a", - &[(*mdb).to_str().unwrap(), - (*midl).to_str().unwrap()]); + gcc::Config::new() + .file(lmdb.join("mdb.c")) + .file(lmdb.join("midl.c")) + // https://github.com/LMDB/lmdb/blob/LMDB_0.9.21/libraries/liblmdb/Makefile#L25 + .opt_level(2) + .compile("liblmdb.a") } } diff --git a/src/lib.rs b/src/lib.rs index 3fe40b4..e54d2dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,6 +62,9 @@ mod transaction; #[cfg(test)] mod test_utils { + extern crate byteorder; + + use self::byteorder::{ByteOrder, LittleEndian}; use tempdir::TempDir; use super::*; @@ -88,4 +91,33 @@ mod test_utils { } (dir, env) } + + /// Regression test for https://github.com/danburkert/lmdb-rs/issues/21. + /// This test reliably segfaults when run against lmbdb compiled with opt level -O3 and newer + /// GCC compilers. + #[test] + fn issue_21_regression() { + const HEIGHT_KEY: [u8; 1] = [0]; + + let dir = TempDir::new("test").unwrap(); + + let env = { + let mut builder = Environment::new(); + builder.set_max_dbs(2); + builder.set_map_size(1_000_000); + builder.open(dir.path()).expect("open lmdb env") + }; + let index = env.create_db(None, DUP_SORT).expect("open index db"); + + for height in 0..1000 { + 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.commit().expect("ts.commit") + } + } } From 4d85f7390fa78823b61a5053f9cded89f5691d94 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sat, 9 Sep 2017 13:01:02 -0700 Subject: [PATCH 22/32] Convert to Cargo workspace project --- Cargo.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index df3d8fc..14ebf06 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,11 @@ categories = ["database"] travis-ci = { repository = "danburkert/lmdb-rs" } appveyor = { repository = "danburkert/lmdb-rs" } +[workspace] +members = [ + "lmdb-sys", +] + [dependencies] bitflags = "0.9" libc = "0.2" From 6539d449f0bc669e5b1e2357ecae07d1d1c37f6c Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sat, 9 Sep 2017 12:59:07 -0700 Subject: [PATCH 23/32] 0.7.2 --- Cargo.toml | 4 ++-- lmdb-sys/Cargo.toml | 2 +- lmdb-sys/src/lib.rs | 2 +- src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 14ebf06..1ed8696 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "lmdb" # NB: When modifying, also modify html_root_url in lib.rs -version = "0.7.1" +version = "0.7.2" authors = ["Dan Burkert "] license = "Apache-2.0" @@ -25,7 +25,7 @@ members = [ [dependencies] bitflags = "0.9" libc = "0.2" -lmdb-sys = { path = "lmdb-sys" } +lmdb-sys = { version = "0.7.2", path = "lmdb-sys" } [dev-dependencies] rand = "0.3" diff --git a/lmdb-sys/Cargo.toml b/lmdb-sys/Cargo.toml index 5a8dd4e..749f9fe 100644 --- a/lmdb-sys/Cargo.toml +++ b/lmdb-sys/Cargo.toml @@ -2,7 +2,7 @@ name = "lmdb-sys" # NB: When modifying, also modify html_root_url in lib.rs -version = "0.7.1" +version = "0.7.2" authors = ["Dan Burkert "] license = "Apache-2.0" diff --git a/lmdb-sys/src/lib.rs b/lmdb-sys/src/lib.rs index 4092a53..cfc69e3 100644 --- a/lmdb-sys/src/lib.rs +++ b/lmdb-sys/src/lib.rs @@ -1,6 +1,6 @@ #![allow(non_camel_case_types)] #![deny(warnings)] -#![doc(html_root_url = "https://docs.rs/lmdb-sys/0.7.1")] +#![doc(html_root_url = "https://docs.rs/lmdb-sys/0.7.2")] extern crate libc; diff --git a/src/lib.rs b/src/lib.rs index e54d2dc..fefb2fb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ #![cfg_attr(test, feature(test))] #![deny(warnings)] -#![doc(html_root_url = "https://docs.rs/lmdb/0.7.1")] +#![doc(html_root_url = "https://docs.rs/lmdb/0.7.2")] extern crate libc; extern crate lmdb_sys as ffi; From 0f613773c1a73516992d42a0f900c1627c115b53 Mon Sep 17 00:00:00 2001 From: zach Date: Sat, 3 Mar 2018 09:21:57 -0800 Subject: [PATCH 24/32] Update dependencies and add database statistics (#23) Add database statistics in a new `Stats` type Also bundles a few other changes: - Switch from `gcc` crate to `cc` for building lmdb - Bump `bitflags` crate to 1.0 - Bump minimum required `rustc` from `1.8` to `1.20` This is a breaking change. --- .travis.yml | 2 +- Cargo.toml | 4 +-- README.md | 2 +- lmdb-sys/Cargo.toml | 3 +-- lmdb-sys/build.rs | 4 +-- src/cursor.rs | 6 ++--- src/environment.rs | 62 +++++++++++++++++++++++++++++++++++++++++---- src/lib.rs | 4 +-- 8 files changed, 69 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index d9212d5..d7bf1e7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ os: - osx rust: -- 1.8.0 +- 1.20.0 - stable - nightly diff --git a/Cargo.toml b/Cargo.toml index 1ed8696..052cceb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,11 +23,11 @@ members = [ ] [dependencies] -bitflags = "0.9" +bitflags = "1" libc = "0.2" lmdb-sys = { version = "0.7.2", path = "lmdb-sys" } [dev-dependencies] -rand = "0.3" +rand = "0.4" tempdir = "0.3" byteorder = "1.0" diff --git a/README.md b/README.md index fbe6a0a..e2f7910 100644 --- a/README.md +++ b/README.md @@ -22,4 +22,4 @@ cargo build * [x] Cursors. * [x] Zero-copy put API. * [x] Nested transactions. -* [ ] Database statistics. +* [x] Database statistics. diff --git a/lmdb-sys/Cargo.toml b/lmdb-sys/Cargo.toml index 749f9fe..bc31441 100644 --- a/lmdb-sys/Cargo.toml +++ b/lmdb-sys/Cargo.toml @@ -20,5 +20,4 @@ libc = "0.2" [build-dependencies] pkg-config = "0.3" -# https://github.com/alexcrichton/gcc-rs/issues/240 -gcc = "=0.3.51" +cc = "1" diff --git a/lmdb-sys/build.rs b/lmdb-sys/build.rs index fd9e98e..8ae769a 100644 --- a/lmdb-sys/build.rs +++ b/lmdb-sys/build.rs @@ -1,5 +1,5 @@ extern crate pkg_config; -extern crate gcc; +extern crate cc; use std::env; use std::path::PathBuf; @@ -11,7 +11,7 @@ fn main() { lmdb.push("liblmdb"); if !pkg_config::find_library("liblmdb").is_ok() { - gcc::Config::new() + cc::Build::new() .file(lmdb.join("mdb.c")) .file(lmdb.join("midl.c")) // https://github.com/LMDB/lmdb/blob/LMDB_0.9.21/libraries/liblmdb/Makefile#L25 diff --git a/src/cursor.rs b/src/cursor.rs index b3f59a2..2fa7153 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -349,7 +349,7 @@ mod test { fn test_get_dup() { let dir = TempDir::new("test").unwrap(); let env = Environment::new().open(dir.path()).unwrap(); - let db = env.create_db(None, DUP_SORT).unwrap(); + let db = env.create_db(None, DatabaseFlags::DUP_SORT).unwrap(); let mut txn = env.begin_rw_txn().unwrap(); txn.put(db, b"key1", b"val1", WriteFlags::empty()).unwrap(); @@ -395,7 +395,7 @@ mod test { fn test_get_dupfixed() { let dir = TempDir::new("test").unwrap(); let env = Environment::new().open(dir.path()).unwrap(); - let db = env.create_db(None, DUP_SORT | DUP_FIXED).unwrap(); + let db = env.create_db(None, DatabaseFlags::DUP_SORT | DatabaseFlags::DUP_FIXED).unwrap(); let mut txn = env.begin_rw_txn().unwrap(); txn.put(db, b"key1", b"val1", WriteFlags::empty()).unwrap(); @@ -449,7 +449,7 @@ mod test { fn test_iter_dup() { let dir = TempDir::new("test").unwrap(); let env = Environment::new().open(dir.path()).unwrap(); - let db = env.create_db(None, DUP_SORT).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"), diff --git a/src/environment.rs b/src/environment.rs index c800bd5..26bcbdd 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -1,5 +1,5 @@ use libc::{c_uint, size_t}; -use std::{fmt, ptr, result}; +use std::{fmt, ptr, result, mem}; use std::ffi::CString; #[cfg(unix)] use std::os::unix::ffi::OsStrExt; @@ -35,6 +35,11 @@ pub struct Environment { dbi_open_mutex: Mutex<()>, } +/// Database statistics +/// +/// Contains information about the size and layout of an LMDB database +pub struct Stat(ffi::MDB_stat); + impl Environment { /// Creates a new builder for specifying options for opening an LMDB environment. @@ -151,6 +156,53 @@ impl Environment { pub unsafe fn close_db(&mut self, db: Database) { ffi::mdb_dbi_close(self.env, db.dbi()); } + + /// Get database statistics. + pub fn stat(&self) -> Result { + unsafe { + let mut stat = Stat(mem::zeroed()); + lmdb_try!(ffi::mdb_env_stat(self.env(), &mut stat.0)); + Ok(stat) + } + } +} + +impl Stat { + /// Size of database in bytes. + #[inline] + pub fn size(&self) -> u32 { + self.0.ms_psize + } + + /// Height of B-tree. + #[inline] + pub fn depth(&self) -> u32 { + self.0.ms_depth + } + + /// Number of internal (non-leaf) pages. + #[inline] + pub fn branch_pages(&self) -> usize { + self.0.ms_branch_pages + } + + /// Number of lead pages. + #[inline] + pub fn leaf_pages(&self) -> usize { + self.0.ms_leaf_pages + } + + /// Number of overflow pages. + #[inline] + pub fn overflow_pages(&self) -> usize { + self.0.ms_overflow_pages + } + + /// Number of data items. + #[inline] + pub fn entries(&self) -> usize { + self.0.ms_entries + } } unsafe impl Send for Environment {} @@ -285,7 +337,7 @@ mod test { let dir = TempDir::new("test").unwrap(); // opening non-existent env with read-only should fail - assert!(Environment::new().set_flags(READ_ONLY) + assert!(Environment::new().set_flags(EnvironmentFlags::READ_ONLY) .open(dir.path()) .is_err()); @@ -293,7 +345,7 @@ mod test { assert!(Environment::new().open(dir.path()).is_ok()); // opening env with read-only should succeed - assert!(Environment::new().set_flags(READ_ONLY) + assert!(Environment::new().set_flags(EnvironmentFlags::READ_ONLY) .open(dir.path()) .is_ok()); } @@ -310,7 +362,7 @@ mod test { } { // read-only environment - let env = Environment::new().set_flags(READ_ONLY) + let env = Environment::new().set_flags(EnvironmentFlags::READ_ONLY) .open(dir.path()) .unwrap(); @@ -360,7 +412,7 @@ mod test { let env = Environment::new().open(dir.path()).unwrap(); assert!(env.sync(true).is_ok()); } { - let env = Environment::new().set_flags(READ_ONLY) + let env = Environment::new().set_flags(EnvironmentFlags::READ_ONLY) .open(dir.path()) .unwrap(); assert!(env.sync(true).is_err()); diff --git a/src/lib.rs b/src/lib.rs index fefb2fb..44ee69a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,7 +21,7 @@ pub use cursor::{ IterDup, }; pub use database::Database; -pub use environment::{Environment, EnvironmentBuilder}; +pub use environment::{Environment, Stat, EnvironmentBuilder}; pub use error::{Error, Result}; pub use flags::*; pub use transaction::{ @@ -107,7 +107,7 @@ mod test_utils { builder.set_map_size(1_000_000); builder.open(dir.path()).expect("open lmdb env") }; - let index = env.create_db(None, DUP_SORT).expect("open index db"); + let index = env.create_db(None, DatabaseFlags::DUP_SORT).expect("open index db"); for height in 0..1000 { let mut value = [0u8; 8]; From c15f22c88427c4b4b90a23fbcbd6630489b283c2 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Sat, 3 Mar 2018 17:45:05 +0000 Subject: [PATCH 25/32] Typo in documentation (#22) --- src/cursor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cursor.rs b/src/cursor.rs index 2fa7153..88aa8cf 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -135,7 +135,7 @@ impl <'txn> RoCursor<'txn> { } } -/// A read-only cursor for navigating items within a database. +/// A read-write cursor for navigating items within a database. pub struct RwCursor<'txn> { cursor: *mut ffi::MDB_cursor, _marker: PhantomData &'txn ()>, From d0fda113ca880a1bc21fc215c74ee0251295ab28 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sat, 3 Mar 2018 09:44:09 -0800 Subject: [PATCH 26/32] try! -> ? --- src/cursor.rs | 8 ++++---- src/database.rs | 2 +- src/environment.rs | 16 ++++++++-------- src/transaction.rs | 27 ++++++++++++--------------- 4 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/cursor.rs b/src/cursor.rs index 88aa8cf..2395116 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -28,7 +28,7 @@ pub trait Cursor<'txn> { let mut key_val = slice_to_val(key); let mut data_val = slice_to_val(data); let key_ptr = key_val.mv_data; - try!(lmdb_result(ffi::mdb_cursor_get(self.cursor(), &mut key_val, &mut data_val, op))); + 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 data_out = val_to_slice(data_val); Ok((key_out, data_out)) @@ -91,7 +91,7 @@ pub trait Cursor<'txn> { /// key. fn iter_dup_of(&mut self, key: &K) -> Result> where K: AsRef<[u8]> { - try!(self.get(Some(key.as_ref()), None, ffi::MDB_SET)); + self.get(Some(key.as_ref()), None, ffi::MDB_SET)?; Ok(Iter::new(self.cursor(), ffi::MDB_GET_CURRENT, ffi::MDB_NEXT_DUP)) } } @@ -127,7 +127,7 @@ impl <'txn> RoCursor<'txn> { #[doc(hidden)] pub fn new(txn: &'txn T, db: Database) -> Result> where T: Transaction { 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 { lmdb_result(ffi::mdb_cursor_open(txn.txn(), db.dbi(), &mut cursor))?; } Ok(RoCursor { cursor: cursor, _marker: PhantomData, @@ -166,7 +166,7 @@ impl <'txn> RwCursor<'txn> { #[doc(hidden)] pub fn new(txn: &'txn T, db: Database) -> Result> where T: Transaction { 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 { lmdb_result(ffi::mdb_cursor_open(txn.txn(), db.dbi(), &mut cursor))?; } Ok(RwCursor { cursor: cursor, _marker: PhantomData }) } diff --git a/src/database.rs b/src/database.rs index 8a92ad1..71ed4ca 100644 --- a/src/database.rs +++ b/src/database.rs @@ -28,7 +28,7 @@ impl Database { 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 mut dbi: ffi::MDB_dbi = 0; - try!(lmdb_result(ffi::mdb_dbi_open(txn, name_ptr, flags, &mut dbi))); + lmdb_result(ffi::mdb_dbi_open(txn, name_ptr, flags, &mut dbi))?; Ok(Database { dbi: dbi }) } diff --git a/src/environment.rs b/src/environment.rs index 26bcbdd..c664e3a 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -76,9 +76,9 @@ impl Environment { /// The database name may not contain the null character. pub fn open_db<'env>(&'env self, name: Option<&str>) -> Result { let mutex = self.dbi_open_mutex.lock(); - let txn = try!(self.begin_ro_txn()); - let db = unsafe { try!(txn.open_db(name)) }; - try!(txn.commit()); + let txn = self.begin_ro_txn()?; + let db = unsafe { txn.open_db(name)? }; + txn.commit()?; drop(mutex); Ok(db) } @@ -102,18 +102,18 @@ impl Environment { flags: DatabaseFlags) -> Result { let mutex = self.dbi_open_mutex.lock(); - let txn = try!(self.begin_rw_txn()); - let db = unsafe { try!(txn.create_db(name, flags)) }; - try!(txn.commit()); + let txn = self.begin_rw_txn()?; + let db = unsafe { txn.create_db(name, flags)? }; + txn.commit()?; drop(mutex); Ok(db) } pub fn get_db_flags<'env>(&'env self, db: Database) -> Result { - let txn = try!(self.begin_ro_txn()); + let txn = self.begin_ro_txn()?; let mut flags: c_uint = 0; unsafe { - try!(lmdb_result(ffi::mdb_dbi_flags(txn.txn(), db.dbi(), &mut flags))); + lmdb_result(ffi::mdb_dbi_flags(txn.txn(), db.dbi(), &mut flags))?; } Ok(DatabaseFlags::from_bits(flags).unwrap()) } diff --git a/src/transaction.rs b/src/transaction.rs index b5278d8..1d9e49f 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -98,7 +98,7 @@ pub trait Transaction : Sized { fn db_flags(&self, db: Database) -> Result { let mut flags: c_uint = 0; unsafe { - try!(lmdb_result(ffi::mdb_dbi_flags(self.txn(), db.dbi(), &mut flags))); + lmdb_result(ffi::mdb_dbi_flags(self.txn(), db.dbi(), &mut flags))?; } Ok(DatabaseFlags::from_bits_truncate(flags)) } @@ -130,10 +130,7 @@ impl <'env> RoTransaction<'env> { pub fn new(env: &'env Environment) -> Result> { let mut txn: *mut ffi::MDB_txn = ptr::null_mut(); unsafe { - try!(lmdb_result(ffi::mdb_txn_begin(env.env(), - ptr::null_mut(), - ffi::MDB_RDONLY, - &mut txn))); + lmdb_result(ffi::mdb_txn_begin(env.env(), ptr::null_mut(), ffi::MDB_RDONLY, &mut txn))?; Ok(RoTransaction { txn: txn, _marker: PhantomData }) } } @@ -195,7 +192,7 @@ impl <'env> InactiveTransaction<'env> { let txn = self.txn; unsafe { mem::forget(self); - try!(lmdb_result(ffi::mdb_txn_renew(txn))) + lmdb_result(ffi::mdb_txn_renew(txn))? }; Ok(RoTransaction { txn: txn, _marker: PhantomData }) } @@ -227,10 +224,10 @@ impl <'env> RwTransaction<'env> { pub fn new(env: &'env Environment) -> Result> { let mut txn: *mut ffi::MDB_txn = ptr::null_mut(); unsafe { - try!(lmdb_result(ffi::mdb_txn_begin(env.env(), - ptr::null_mut(), - EnvironmentFlags::empty().bits(), - &mut txn))); + lmdb_result(ffi::mdb_txn_begin(env.env(), + ptr::null_mut(), + EnvironmentFlags::empty().bits(), + &mut txn))?; Ok(RwTransaction { txn: txn, _marker: PhantomData }) } } @@ -305,11 +302,11 @@ impl <'env> RwTransaction<'env> { let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: len, mv_data: ptr::null_mut::() }; unsafe { - try!(lmdb_result(ffi::mdb_put(self.txn(), - database.dbi(), - &mut key_val, - &mut data_val, - flags.bits() | ffi::MDB_RESERVE))); + 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)) } From 8e0bdab382203ab2097b2c8d03bc72d1bac11cd4 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sat, 3 Mar 2018 09:50:36 -0800 Subject: [PATCH 27/32] doc(hidden) -> pub(crate) fixes #17 --- src/cursor.rs | 6 ++---- src/database.rs | 9 ++++----- src/transaction.rs | 8 +++----- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/cursor.rs b/src/cursor.rs index 2395116..f59bada 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -124,8 +124,7 @@ impl <'txn> RoCursor<'txn> { /// Creates a new read-only cursor in the given database and transaction. /// Prefer using `Transaction::open_cursor`. - #[doc(hidden)] - pub 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(RoCursor { @@ -163,8 +162,7 @@ impl <'txn> RwCursor<'txn> { /// Creates a new read-only cursor in the given database and transaction. /// Prefer using `RwTransaction::open_rw_cursor`. - #[doc(hidden)] - pub 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 }) diff --git a/src/database.rs b/src/database.rs index 71ed4ca..61656dc 100644 --- a/src/database.rs +++ b/src/database.rs @@ -20,11 +20,10 @@ impl Database { /// /// Prefer using `Environment::open_db`, `Environment::create_db`, `TransactionExt::open_db`, /// or `RwTransaction::create_db`. - #[doc(hidden)] - pub 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 mut dbi: ffi::MDB_dbi = 0; diff --git a/src/transaction.rs b/src/transaction.rs index 1d9e49f..590fd9f 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -126,8 +126,7 @@ impl <'env> RoTransaction<'env> { /// Creates a new read-only transaction in the given environment. Prefer /// using `Environment::begin_ro_txn`. - #[doc(hidden)] - pub fn new(env: &'env Environment) -> Result> { + 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))?; @@ -220,8 +219,7 @@ impl <'env> RwTransaction<'env> { /// Creates a new read-write transaction in the given environment. Prefer /// using `Environment::begin_ro_txn`. - #[doc(hidden)] - pub fn new(env: &'env Environment) -> Result> { + 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(), @@ -244,7 +242,7 @@ impl <'env> RwTransaction<'env> { /// /// ## Safety /// - /// * This function (as well as `Environment::open_db`, + /// This function (as well as `Environment::open_db`, /// `Environment::create_db`, and `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 From e5dbfc81bb795194d19de40fafa7f13a20d4ac41 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sat, 3 Mar 2018 09:53:11 -0800 Subject: [PATCH 28/32] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e2f7910..59d4198 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ cd lmdb-rs cargo build ``` -## TODO +## Features * [x] lmdb-sys. * [x] Cursors. From 09af4d92b70583de728054fe827d7a4f03522870 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sat, 3 Mar 2018 10:22:25 -0800 Subject: [PATCH 29/32] Update docs and small tweaks --- src/cursor.rs | 5 +++++ src/environment.rs | 24 ++++++++++++++---------- src/error.rs | 5 +++++ src/flags.rs | 9 ++++++--- src/lib.rs | 3 ++- 5 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/cursor.rs b/src/cursor.rs index f59bada..1ea2385 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -212,6 +212,7 @@ unsafe fn val_to_slice<'a>(val: ffi::MDB_val) -> &'a [u8] { slice::from_raw_parts(val.mv_data as *const u8, val.mv_size as usize) } +/// An iterator over the values in an LMDB database. pub struct Iter<'txn> { cursor: *mut ffi::MDB_cursor, op: c_uint, @@ -259,6 +260,10 @@ impl <'txn> Iterator for Iter<'txn> { } } +/// An iterator over the keys and duplicate values in an LMDB database. +/// +/// The yielded items of the iterator are themselves iterators over the duplicate values for a +/// specific key. pub struct IterDup<'txn> { cursor: *mut ffi::MDB_cursor, op: c_uint, diff --git a/src/environment.rs b/src/environment.rs index c664e3a..6321f38 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -35,11 +35,6 @@ pub struct Environment { dbi_open_mutex: Mutex<()>, } -/// Database statistics -/// -/// Contains information about the size and layout of an LMDB database -pub struct Stat(ffi::MDB_stat); - impl Environment { /// Creates a new builder for specifying options for opening an LMDB environment. @@ -109,6 +104,9 @@ impl Environment { Ok(db) } + /// Retrieves the set of flags which the database is opened with. + /// + /// The database must belong to to this environment. pub fn get_db_flags<'env>(&'env self, db: Database) -> Result { let txn = self.begin_ro_txn()?; let mut flags: c_uint = 0; @@ -157,7 +155,7 @@ impl Environment { ffi::mdb_dbi_close(self.env, db.dbi()); } - /// Get database statistics. + /// Retrieves statistics about this environment. pub fn stat(&self) -> Result { unsafe { let mut stat = Stat(mem::zeroed()); @@ -167,14 +165,19 @@ impl Environment { } } +/// Environment statistics. +/// +/// Contains information about the size and layout of an LMDB environment. +pub struct Stat(ffi::MDB_stat); + impl Stat { - /// Size of database in bytes. + /// Size of a database page. This is the same for all databases in the environment. #[inline] - pub fn size(&self) -> u32 { + pub fn page_size(&self) -> u32 { self.0.ms_psize } - /// Height of B-tree. + /// Depth (height) of the B-tree. #[inline] pub fn depth(&self) -> u32 { self.0.ms_depth @@ -186,7 +189,7 @@ impl Stat { self.0.ms_branch_pages } - /// Number of lead pages. + /// Number of leaf pages. #[inline] pub fn leaf_pages(&self) -> usize { self.0.ms_leaf_pages @@ -276,6 +279,7 @@ impl EnvironmentBuilder { } + /// Sets the provided options in the environment. pub fn set_flags(&mut self, flags: EnvironmentFlags) -> &mut EnvironmentBuilder { self.flags = flags; self diff --git a/src/error.rs b/src/error.rs index 12fc2bb..9225e85 100644 --- a/src/error.rs +++ b/src/error.rs @@ -6,6 +6,7 @@ use std::{fmt, result, str}; use ffi; +/// An LMDB error kind. #[derive(Debug, Eq, PartialEq, Copy, Clone)] pub enum Error { /// key/data pair already exists. @@ -53,6 +54,8 @@ 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, @@ -79,6 +82,7 @@ impl Error { } } + /// Converts an `Error` to the raw error code. pub fn to_err_code(&self) -> c_int { match *self { Error::KeyExist => ffi::MDB_KEYEXIST, @@ -122,6 +126,7 @@ impl StdError for Error { } } +/// An LMDB result. pub type Result = result::Result; pub fn lmdb_result(err_code: c_int) -> Result<()> { diff --git a/src/flags.rs b/src/flags.rs index 13d52f0..c467405 100644 --- a/src/flags.rs +++ b/src/flags.rs @@ -3,7 +3,8 @@ use libc::c_uint; use ffi::*; bitflags! { - #[doc="Environment Options"] + #[doc="Environment options."] + #[derive(Default)] pub struct EnvironmentFlags: c_uint { #[doc="Use a fixed address for the mmap region. This flag must be specified"] @@ -103,7 +104,8 @@ bitflags! { } bitflags! { - #[doc="Database Options"] + #[doc="Database options."] + #[derive(Default)] pub struct DatabaseFlags: c_uint { #[doc="Keys are strings to be compared in reverse order, from the end of the strings"] @@ -138,7 +140,8 @@ bitflags! { } bitflags! { - #[doc="Write Options"] + #[doc="Write options."] + #[derive(Default)] pub struct WriteFlags: c_uint { #[doc="Insert the new item only if the key does not already appear in the database."] diff --git a/src/lib.rs b/src/lib.rs index 44ee69a..18524b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,9 @@ //! Idiomatic and safe APIs for interacting with the -//! [Symas Lightning Memory-Mapped Database (LMDB)](http://symas.com/mdb/). +//! [Lightning Memory-mapped Database (LMDB)](https://symas.com/lmdb). #![cfg_attr(test, feature(test))] #![deny(warnings)] +#![deny(missing_docs)] #![doc(html_root_url = "https://docs.rs/lmdb/0.7.2")] extern crate libc; From e8e58fd04c6a1d3bcab71b488293e8ecd49a4dc2 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sat, 3 Mar 2018 10:33:48 -0800 Subject: [PATCH 30/32] Add test for Environment::stats --- src/environment.rs | 38 ++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 +- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/environment.rs b/src/environment.rs index 6321f38..db31f7a 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -330,7 +330,10 @@ impl EnvironmentBuilder { #[cfg(test)] mod test { + extern crate byteorder; + use tempdir::TempDir; + use self::byteorder::{ByteOrder, LittleEndian}; use flags::*; @@ -422,4 +425,39 @@ mod test { assert!(env.sync(true).is_err()); } } + + #[test] + fn test_stat() { + let dir = TempDir::new("test").unwrap(); + let env = Environment::new().open(dir.path()).unwrap(); + + // Stats should be empty initially. + let stat = env.stat().unwrap(); + assert_eq!(stat.page_size(), 4096); + assert_eq!(stat.depth(), 0); + assert_eq!(stat.branch_pages(), 0); + assert_eq!(stat.leaf_pages(), 0); + assert_eq!(stat.overflow_pages(), 0); + assert_eq!(stat.entries(), 0); + + let db = env.open_db(None).unwrap(); + + // Write a few small values. + for i in 0..64 { + let mut value = [0u8; 8]; + LittleEndian::write_u64(&mut value, i); + let mut tx = env.begin_rw_txn().expect("begin_rw_txn"); + tx.put(db, &value, &value, WriteFlags::default()).expect("tx.put"); + tx.commit().expect("tx.commit") + } + + // Stats should now reflect inserted values. + let stat = env.stat().unwrap(); + assert_eq!(stat.page_size(), 4096); + assert_eq!(stat.depth(), 1); + assert_eq!(stat.branch_pages(), 0); + assert_eq!(stat.leaf_pages(), 1); + assert_eq!(stat.overflow_pages(), 0); + assert_eq!(stat.entries(), 64); + } } diff --git a/src/lib.rs b/src/lib.rs index 18524b9..ef58f79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -118,7 +118,7 @@ mod test_utils { &HEIGHT_KEY, &value, WriteFlags::empty()).expect("tx.put"); - tx.commit().expect("ts.commit") + tx.commit().expect("tx.commit") } } } From 5a70b18c0a655036f39deb9162ff28f36c4f6fe3 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sat, 3 Mar 2018 10:36:23 -0800 Subject: [PATCH 31/32] Remove deny(warnings) --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index ef58f79..21f2e4b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,6 @@ //! [Lightning Memory-mapped Database (LMDB)](https://symas.com/lmdb). #![cfg_attr(test, feature(test))] -#![deny(warnings)] #![deny(missing_docs)] #![doc(html_root_url = "https://docs.rs/lmdb/0.7.2")] From 90e88809954459869953cfa595ecd1e644bbfc87 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sat, 3 Mar 2018 10:25:22 -0800 Subject: [PATCH 32/32] 0.8.0 --- Cargo.toml | 4 ++-- lmdb-sys/Cargo.toml | 2 +- lmdb-sys/src/lib.rs | 2 +- src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 052cceb..82ed4ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "lmdb" # NB: When modifying, also modify html_root_url in lib.rs -version = "0.7.2" +version = "0.8.0" authors = ["Dan Burkert "] license = "Apache-2.0" @@ -25,7 +25,7 @@ members = [ [dependencies] bitflags = "1" libc = "0.2" -lmdb-sys = { version = "0.7.2", path = "lmdb-sys" } +lmdb-sys = { version = "0.8.0", path = "lmdb-sys" } [dev-dependencies] rand = "0.4" diff --git a/lmdb-sys/Cargo.toml b/lmdb-sys/Cargo.toml index bc31441..5c8f433 100644 --- a/lmdb-sys/Cargo.toml +++ b/lmdb-sys/Cargo.toml @@ -2,7 +2,7 @@ name = "lmdb-sys" # NB: When modifying, also modify html_root_url in lib.rs -version = "0.7.2" +version = "0.8.0" authors = ["Dan Burkert "] license = "Apache-2.0" diff --git a/lmdb-sys/src/lib.rs b/lmdb-sys/src/lib.rs index cfc69e3..601ef69 100644 --- a/lmdb-sys/src/lib.rs +++ b/lmdb-sys/src/lib.rs @@ -1,6 +1,6 @@ #![allow(non_camel_case_types)] #![deny(warnings)] -#![doc(html_root_url = "https://docs.rs/lmdb-sys/0.7.2")] +#![doc(html_root_url = "https://docs.rs/lmdb-sys/0.8.0")] extern crate libc; diff --git a/src/lib.rs b/src/lib.rs index 21f2e4b..bee6bfe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ #![cfg_attr(test, feature(test))] #![deny(missing_docs)] -#![doc(html_root_url = "https://docs.rs/lmdb/0.7.2")] +#![doc(html_root_url = "https://docs.rs/lmdb/0.8.0")] extern crate libc; extern crate lmdb_sys as ffi;