84 releases (19 stable)
|new 1.2.8||Jul 25, 2021|
|1.2.5||Jun 15, 2021|
|1.2.0||Mar 9, 2021|
|0.15.11||Jan 17, 2021|
|0.2.0||Mar 30, 2016|
#52 in Database interfaces
573 downloads per month
Used in 6 crates (5 directly)
Sanakirja is an on-disk transactional key-value store, based on B trees and copy-on-write.
An optional transactional reference counting makes it efficient to clone tables. Formally, the
fork_db operation is in O(log n) in the worst case, where n is bounded above by the total number of entries in the entire file.
This crate is relatively low-level, in the sense that it is possible to keep pointers to a freed database, and to leak memory. The only constraint is this: all calls that modify a
Db may change that
Db, and it is invalid to keep an old value. Moreover, if you forget to record the new value of a
Db, or a newly-created
Db, this may leak memory.
One strong point of this design is to be able to use arbitrary type hierarchies, by using tables (i.e. the
Db type) as values in another table. In such cases, it is easy to write wrappers around these types to update values automatically just before committing a transaction.
A more basic crate called Sanakirja-core is also available, and compiles with
no_std. The main difference with this crate (Sanakirja) is that Sanakirja implements allocator traits required by Sanakirja-core, using operating system primitives such as
This makes it possible to use Sanakirja-core in contexts such as WASM, or even to use Sanakirja-core as part of a filesystem.
In the following example, the calls to method
set_root register the B trees created by
fork_db as "root tables" (there can be at most 510 root tables), so we don't lose track of these tables.
use sanakirja::*; let env = Env::new("db", 1 << 20, 2).unwrap(); let mut txn = Env::mut_txn_begin(&env).unwrap(); let mut db = btree::create_db::<_, u64, u64>(&mut txn).unwrap(); let db2 = btree::fork_db(&mut txn, &db).unwrap(); btree::put(&mut txn, &mut db, &12u64, &5432u64).unwrap(); let ndb = 0; let ndb2 = 1; txn.set_root(ndb, db.db); txn.set_root(ndb2, db2.db); txn.commit().unwrap(); let txn = Env::txn_begin(&env).unwrap(); let db: btree::Db<u64, u64> = txn.root_db(ndb).unwrap(); assert_eq!(btree::get(&txn, &db, &12, None).unwrap(), Some((&12, &5432))); let db2: btree::Db<u64, u64> = txn.root_db(ndb2).unwrap(); assert_eq!(btree::get(&txn, &db, &12, None).unwrap(), None);