diff --git a/src/environment.rs b/src/environment.rs index dc0f96a..74fb882 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -161,7 +161,7 @@ impl Environment { /// Retrieves statistics about this environment. pub fn stat(&self) -> Result { unsafe { - let mut stat = Stat(mem::zeroed()); + let mut stat = Stat::new(); lmdb_try!(ffi::mdb_env_stat(self.env(), &mut stat.0)); Ok(stat) } @@ -248,7 +248,16 @@ impl Environment { /// Environment statistics. /// /// Contains information about the size and layout of an LMDB environment. -pub struct Stat(ffi::MDB_stat); +pub struct Stat(pub(crate) ffi::MDB_stat); + +impl Stat { + /// Create a new Stat with zero'd inner struct `ffi::MDB_stat`. + pub fn new() -> Stat { + unsafe { + Stat(mem::zeroed()) + } + } +} impl Stat { /// Size of a database page. This is the same for all databases in the environment. diff --git a/src/transaction.rs b/src/transaction.rs index 16804d3..97eecc1 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -5,7 +5,7 @@ use std::marker::PhantomData ; use ffi; use cursor::{RoCursor, RwCursor}; -use environment::Environment; +use environment::{Environment, Stat}; use database::Database; use error::{Error, Result, lmdb_result}; use flags::{DatabaseFlags, EnvironmentFlags, WriteFlags}; @@ -102,6 +102,15 @@ pub trait Transaction : Sized { } Ok(DatabaseFlags::from_bits_truncate(flags)) } + + /// Retrieves database statistics. + fn stat(&self, db: Database) -> Result { + unsafe { + let mut stat = Stat::new(); + lmdb_try!(ffi::mdb_stat(self.txn(), db.dbi(), &mut stat.0)); + Ok(stat) + } + } } /// An LMDB read-only transaction. @@ -654,6 +663,96 @@ mod test { } } + #[test] + fn test_stat() { + let dir = TempDir::new("test").unwrap(); + let env = Environment::new().open(dir.path()).unwrap(); + let db = env.create_db(None, DatabaseFlags::empty()).unwrap(); + + let mut txn = env.begin_rw_txn().unwrap(); + txn.put(db, b"key1", b"val1", WriteFlags::empty()).unwrap(); + txn.put(db, b"key2", b"val2", WriteFlags::empty()).unwrap(); + txn.put(db, b"key3", b"val3", WriteFlags::empty()).unwrap(); + txn.commit().unwrap(); + + { + let txn = env.begin_ro_txn().unwrap(); + let stat = txn.stat(db).unwrap(); + assert_eq!(stat.entries(), 3); + } + + let mut txn = env.begin_rw_txn().unwrap(); + txn.del(db, b"key1", None).unwrap(); + txn.del(db, b"key2", None).unwrap(); + txn.commit().unwrap(); + + { + let txn = env.begin_ro_txn().unwrap(); + let stat = txn.stat(db).unwrap(); + assert_eq!(stat.entries(), 1); + } + + let mut txn = env.begin_rw_txn().unwrap(); + txn.put(db, b"key4", b"val4", WriteFlags::empty()).unwrap(); + txn.put(db, b"key5", b"val5", WriteFlags::empty()).unwrap(); + txn.put(db, b"key6", b"val6", WriteFlags::empty()).unwrap(); + txn.commit().unwrap(); + + { + let txn = env.begin_ro_txn().unwrap(); + let stat = txn.stat(db).unwrap(); + assert_eq!(stat.entries(), 4); + } + } + + #[test] + fn test_stat_dupsort() { + let dir = TempDir::new("test").unwrap(); + let env = Environment::new().open(dir.path()).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(); + txn.put(db, b"key1", b"val2", WriteFlags::empty()).unwrap(); + txn.put(db, b"key1", b"val3", WriteFlags::empty()).unwrap(); + txn.put(db, b"key2", b"val1", WriteFlags::empty()).unwrap(); + txn.put(db, b"key2", b"val2", WriteFlags::empty()).unwrap(); + txn.put(db, b"key2", b"val3", WriteFlags::empty()).unwrap(); + txn.put(db, b"key3", b"val1", WriteFlags::empty()).unwrap(); + txn.put(db, b"key3", b"val2", WriteFlags::empty()).unwrap(); + txn.put(db, b"key3", b"val3", WriteFlags::empty()).unwrap(); + txn.commit().unwrap(); + + { + let txn = env.begin_ro_txn().unwrap(); + let stat = txn.stat(db).unwrap(); + assert_eq!(stat.entries(), 9); + } + + let mut txn = env.begin_rw_txn().unwrap(); + txn.del(db, b"key1", Some(b"val2")).unwrap(); + txn.del(db, b"key2", None).unwrap(); + txn.commit().unwrap(); + + { + let txn = env.begin_ro_txn().unwrap(); + let stat = txn.stat(db).unwrap(); + assert_eq!(stat.entries(), 5); + } + + let mut txn = env.begin_rw_txn().unwrap(); + txn.put(db, b"key4", b"val1", WriteFlags::empty()).unwrap(); + txn.put(db, b"key4", b"val2", WriteFlags::empty()).unwrap(); + txn.put(db, b"key4", b"val3", WriteFlags::empty()).unwrap(); + txn.commit().unwrap(); + + { + let txn = env.begin_ro_txn().unwrap(); + let stat = txn.stat(db).unwrap(); + assert_eq!(stat.entries(), 8); + } + } + #[bench] fn bench_get_rand(b: &mut Bencher) { let n = 100u32;