jammdb

Just Another Memory Mapped Database

crates.io docs.rs Build status Coverage Status License Dependency Status

jammdb is an embedded, single-file database that allows you to store key / value pairs as bytes.

It started life as a Rust port of Ben Johnson's BoltDB, which was inspired by Howard Chu's LMDB, so please check out both of these awesome projects!

jammdb offers ACID compliance, serializable and isolated transactions, with multiple lock-free readers and a single concurrent writer. The data is organized in a single level B+ tree so random and sequential reads are very fast. The underlying file is memory mapped, so reads require no additional memory allocation.

Supported platforms

jammdb is continuously cross-compiled and tested on the following platforms: * x86_64-unknown-linux-gnu (Linux) * i686-unknown-linux-gnu * x86_64-unknown-linux-musl (Linux MUSL) * x86_64-apple-darwin (OSX) * x86_64-pc-windows-msvc (Windows) * i686-pc-windows-msvc * x86_64-pc-windows-gnu * i686-pc-windows-gnu

Examples

Here are a couple of simple examples to get you started, but you should check out the docs for more details.

Simple put and get

```rust use jammdb::{DB, Data, Error};

fn main() -> Result<(), Error> { { // open a new database file let db = DB::open("my-database.db")?;

// open a writable transaction so we can make changes
let mut tx = db.tx(true)?;

// create a bucket to store a map of first names to last names
let names_bucket = tx.create_bucket("names")?;
names_bucket.put(b"Kanan", b"Jarrus")?;
names_bucket.put(b"Ezra", b"Bridger")?;

// commit the changes so they are saved to disk
tx.commit()?;

} { // open the existing database file let db = DB::open("my-database.db")?; // open a read-only transaction to get the data let mut tx = db.tx(true)?; // get the bucket we created in the last transaction let namesbucket = tx.getbucket("names")?; // get the key/ value pair we inserted into the bucket if let Some(data) = namesbucket.get(b"Kanan") { assert!(data.iskv()); assert_eq!(data.kv().value(), b"Jarrus"); } } Ok(()) } ```

Storing structs

```rust use jammdb::{DB, Data, Error}; use serde::{Deserialize, Serialize}; // use rmps crate to serialize structs using the MessagePack format use rmp_serde::{Deserializer, Serializer};

[derive(Debug, PartialEq, Deserialize, Serialize)]

struct User { username: String, password: String, }

fn main() -> Result<(), Error> { let user = User{ username: "my-user".tostring(), password: "my-password".tostring(), }; { // open a new database file and start a writable transaction let db = DB::open("my-database.db")?; let mut tx = db.tx(true)?;

// create a bucket to store users
let users_bucket = tx.create_bucket("users")?;

// serialize struct to bytes and store in bucket
let user_bytes = rmp_serde::to_vec(&user).unwrap();
users_bucket.put(b"user1", user_bytes)?;

// commit the changes so they are saved to disk
tx.commit()?;

} { // open the existing database file let db = DB::open("my-database.db")?; // open a read-only transaction to get the data let mut tx = db.tx(true)?; // get the bucket we created in the last transaction let usersbucket = tx.getbucket("users")?; // get the key / value pair we inserted into the bucket if let Some(data) = usersbucket.get(b"user1") { if data.iskv() { let kv = data.kv(); // deserialize into a user struct let dbuser: User = rmpserde::fromslice(kv.value()).unwrap(); asserteq!(db_user, user); } } } Ok(()) } ```

License

Available under both the Apache License or the MIT license.