use mmdb::{DB, DbOptions, ErrorKind, ReadOptions, WriteBatch, WriteOptions};
fn main() -> mmdb::Result<()> {
let dir = tempfile::tempdir().expect("tempdir");
let opts = DbOptions {
create_if_missing: true,
..DbOptions::balanced()
};
let db = DB::open(opts, dir.path())?;
db.put(b"user:alice", b"1000")?;
db.put(b"user:bob", b"2000")?;
assert_eq!(db.get(b"user:alice")?, Some(b"1000".to_vec()));
let sync_opts = WriteOptions {
sync: true,
..Default::default()
};
db.put_with_options(&sync_opts, b"user:carol", b"3000")?;
let mut batch = WriteBatch::new();
batch.put(b"acct:1", b"open");
batch.put(b"acct:2", b"open");
batch.delete(b"user:bob");
db.write(batch)?;
assert_eq!(db.get(b"user:bob")?, None);
let snap = db.snapshot();
db.put(b"user:alice", b"9999")?;
assert_eq!(
db.get_with_options(&snap.read_options(), b"user:alice")?,
Some(b"1000".to_vec()),
"snapshot sees the old value"
);
assert_eq!(db.get(b"user:alice")?, Some(b"9999".to_vec()));
drop(snap);
let mut user_iter = db.iter_with_prefix(b"user:", &ReadOptions::default())?;
let users: Vec<_> = user_iter.by_ref().collect();
if let Some(error) = user_iter.error() {
return Err(mmdb::Error::io(std::io::Error::other(error)));
}
println!("{} keys under user:", users.len());
let scan_opts = ReadOptions {
fill_cache: false,
..Default::default()
};
let mut range_iter = db.iter_with_range(&scan_opts, Some(b"acct:1"), Some(b"acct:9"))?;
for (k, v) in range_iter.by_ref() {
println!("{} = {}", String::from_utf8_lossy(&k), v.len());
}
if let Some(error) = range_iter.error() {
return Err(mmdb::Error::io(std::io::Error::other(error)));
}
db.delete_range(b"acct:1", b"acct:9")?;
assert_eq!(db.get(b"acct:1")?, None);
match DB::open(
DbOptions {
num_levels: 0, ..Default::default()
},
dir.path().join("bad"),
) {
Err(e) if e.kind() == ErrorKind::InvalidArgument => {
println!("rejected as expected:\n{e}");
}
Err(e) => panic!("expected InvalidArgument, got {e:?}"),
Ok(_) => panic!("expected InvalidArgument, got Ok"),
}
db.flush()?;
Ok(())
}