From 0f613773c1a73516992d42a0f900c1627c115b53 Mon Sep 17 00:00:00 2001 From: zach Date: Sat, 3 Mar 2018 09:21:57 -0800 Subject: [PATCH] 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];