# Quickstart

> UStore for Rust

A `Database` owns its directory, and a `Collection` addresses one collection in it by name, as the Python binding does with `db['movies']`.

```rust
use ustore::{jsontape, Arena, Database, Durability, Edge, Key, RAMOptions, Role};

let database = Database::init_ram(&RAMOptions::default())?;
let [avatar, titanic] = [1u64, 2].map(Key::from);

database.collection("movies")?.docs().set(avatar, &jsontape::parse(br#"{"title":"Avatar","year":2009}"#)?)?;
database.collection("posters")?.blobs().set(avatar, &png_bytes)?;
database.collection("similar")?.graph().add_edge(avatar, titanic)?;

let mut movies = database.collection("movies")?;
let description = movies.docs().get(avatar)?.expect("written above");
assert_eq!(description["year"].as_u64(), Some(2009));

let mut posters = database.collection("posters")?;
let thumbnail: Option<Vec<u8>> = posters.blobs().get(avatar)?;

let mut similar = database.collection("similar")?;
let recommendations: Vec<Edge> = similar.graph().read_edges(&[avatar], Role::Source)?;

let mut arena = Arena::new()?;
let mut pictures = database.collection("pictures")?;
let images = pictures.sample(1000, &mut arena)?;
let tape = images.values().tape();

let mut transaction = database.transaction()?;
transaction.collection("movies")?.docs().set(titanic, &jsontape::parse(br#"{"title":"Titanic","year":1997}"#)?)?;
transaction.collection("similar")?.graph().add_edge(titanic, avatar)?;
transaction.collection("posters")?.blobs().set(titanic, &png_bytes)?;
transaction.commit(Durability::Buffered)?;
```

A collection resolves its name through its view once, and every verb goes through a view of one modality: `blobs`, `docs` or `graph`.
The first write through a view creates a missing collection holding that view's modality, a read of a missing one fails with `Status::NotFound`, and a view of another modality fails with `Status::InvalidArgument`.
`sample` draws keys at random and reads their values through the same view, so a sample holds both.

A collection keeps no arena.
A call with no arena to pass, such as `get`, `contains`, the document reads and the graph lookups, makes a one-off arena through `ustore_arena_init`, copies what it read out of it, and frees it with the call: slower than reusing an arena, and stateless.
The batch reads, `Blobs::read` and `Collection::sample`, take the `Arena` they land in and answer views into it.
Writes land `Durability::Buffered`, and every call through a collection runs on the calling thread.
`Transaction::collection` reads and writes inside the transaction, while its name resolves at the head.
Collections are created and dropped nowhere but at the head, so a first write from inside a transaction creates the collection there at once, and a name never joins the transaction's conflicts.
Its collections borrow the transaction, so they are no longer used by the time `Transaction::commit` takes it mutably.

### Engines & Lifecycle

The constructor names the engine and what it does with a directory: `init_ram` starts an empty database in memory alone, `open_<engine>` serves a directory in place, and `view_rocksdb` serves one read-only.
An engine the build left out fails to open with `Status::Unsupported`.

```rust
use ustore::{DropMode, Engine, Isolation, LevelDBOptions, RAMOptions, RocksDBOptions};

let scratch = Database::init_ram(&RAMOptions { isolation: Isolation::Snapshot, ..RAMOptions::default() })?;
let imaged = Database::open_ram("/var/lib/imaged", &RAMOptions::default())?;
let people = Database::open_rocksdb(&RocksDBOptions::at("/var/lib/people"))?;
let replica = Database::view_rocksdb(&RocksDBOptions::at("/var/lib/replica"))?;
let places = Database::open_leveldb(&LevelDBOptions::at("/var/lib/places"))?;

let description = people.describe()?;
assert_eq!(description.engine, Engine::RocksDB);
println!("{} keys in {} bytes on disk", description.keys, description.disk_bytes);

people.clear(DropMode::Values)?;  // keeps every key, emptying its value
people.compact(None)?;            // reclaims what overwritten and removed data still takes
people.snapshot()?.save("/var/lib/people-copy")?;
```

`open_ram` loads the image its directory holds, if any, and rewrites it whole on a flushed commit and on close.
A database `view_rocksdb` opened reads the state its directory held at open and refuses every call that would change it with `Status::ReadOnly`: writes, removes, transactions, collection creates and drops, clears and compactions, while snapshots and their saves still serve.
`describe` answers the engine, the isolation transactions see, the keys across every collection, and the bytes the data takes in memory and on disk, where every size is the engine's estimate and zero where it keeps none.

`clear` empties every collection at once, as `collection_drop` empties one: `DropMode::Pairs` keeps the collections and their names, `DropMode::Collection` drops every collection with its name, and `DropMode::Values` keeps the keys where the engine can.
The RAM and RocksDB engines refuse to drop the collections while a snapshot is open, with `Status::InvalidArgument`, since the snapshot belongs to its holder.
`compact` reclaims space one collection at a time: RocksDB and LevelDB flush and compact their trees, and the RAM engine frees the versions no reader needs and rewrites its image.
`Snapshot::save` writes the snapshot out as a new database of the same engine, holding exactly the collections and names the snapshot records, which that engine's open then serves.
RocksDB and LevelDB create the path, while the RAM engine writes its image into the existing directory the path names.
`clear` and `compact` are verbs of the head, and `save` of a snapshot, so each runs on an executor or defers as every other verb does.

`use ustore::DataDirectory;`

`use ustore::Database;`

`use ustore::Engine;`

`use ustore::LevelDBOptions;`

`use ustore::NVMEOptions;`

`use ustore::RAMOptions;`

`use ustore::RocksDBOptions;`

## DataDirectory

A directory the data files may occupy, with the bytes they may take there.

```rust
pub struct DataDirectory<'path>
```

- `path` `&'path str`: The directory, which must exist; on NVMe also a raw device from a base, like
`/dev/nvme0n1@64GiB`.
- `max_bytes` `u64`: Bytes the files may take there: zero is unlimited on RocksDB and the whole medium on NVMe.

Implements: `Clone`, `Copy`, `StructuralPartialEq`, `PartialEq`, `Eq`, `Debug`, `Default`, `Hash`

## Database

An open embedded database, which owns its directory until it is dropped.

```rust
pub struct Database
```

No two processes may open one directory at once, and the handle is shared across threads freely;
the transactions taken from it are not. Dropping it waits for every deferred call naming it to finish.

Implements: `Debug`, `Send`, `Sync`, `Drop`

## collection

The collection `name` addresses at the head, resolved now and created by its first write.

```rust
pub fn collection(&self, name: &str) -> Result<Collection<'_>>
```

## init_ram

Starts an empty database of the in-memory engine, which persists nowhere.

```rust
pub fn init_ram(options: &RAMOptions<'_>) -> Result<Self>
```

Calls `ustore_database_init_ram`.

## open_ram

Serves an existing directory in place through the in-memory engine, loading the image it holds, if any, and rewriting it whole on a flushed commit and on close.

```rust
pub fn open_ram(directory: &str, options: &RAMOptions<'_>) -> Result<Self>
```

Calls `ustore_database_open_ram`.

## open_rocksdb

Serves a directory in place through the RocksDB engine, creating the database when it holds none, or fails with [`Status::Unsupported`](https://www.unum.cloud/docs/ustore/rust/errors.md#Unsupported) in a build without the engine.

```rust
pub fn open_rocksdb(options: &RocksDBOptions<'_>) -> Result<Self>
```

Calls `ustore_database_open_rocksdb`.

## view_rocksdb

Serves an existing directory in place through the RocksDB engine, read-only, or fails with [`Status::Unsupported`](https://www.unum.cloud/docs/ustore/rust/errors.md#Unsupported) in a build without the engine.

```rust
pub fn view_rocksdb(options: &RocksDBOptions<'_>) -> Result<Self>
```

The database reads the state its directory held at open, and refuses every call that would change it with
[[`Status::ReadOnly`](https://www.unum.cloud/docs/ustore/rust/errors.md#ReadOnly)]: writes, removes, transactions, collection creates and drops, clears and compactions.
Snapshots and their saves still serve.

Calls `ustore_database_view_rocksdb`.

## open_leveldb

Serves a directory in place through the LevelDB engine, creating the database when it holds none, or fails with [`Status::Unsupported`](https://www.unum.cloud/docs/ustore/rust/errors.md#Unsupported) in a build without the engine.

```rust
pub fn open_leveldb(options: &LevelDBOptions<'_>) -> Result<Self>
```

Calls `ustore_database_open_leveldb`.

## open_nvme

Serves the database a manifest names through the NVMe engine, or fails with [`Status::Unsupported`](https://www.unum.cloud/docs/ustore/rust/errors.md#Unsupported) in a build without it.

```rust
pub fn open_nvme(options: &NVMEOptions<'_>) -> Result<Self>
```

Calls `ustore_database_open_nvme`.

## describe

The engine behind this database, what it supports and how much it holds.

```rust
pub fn describe(&self) -> Result<Description>
```

Calls `ustore_database_describe`.

## clear

Empties every collection at once at the head; see [`On::clear`](https://www.unum.cloud/docs/ustore/rust/batches-and-arenas.md#clear).

```rust
pub fn clear(&self, mode: DropMode) -> Result<()>
```

## compact

Reclaims the space overwritten and removed data still takes, one collection at a time; see [`On::compact`](https://www.unum.cloud/docs/ustore/rust/batches-and-arenas.md#compact).

```rust
pub fn compact<'config>(&self, config: impl Into<CompactConfig<'config>>) -> Result<()>
```

## flush

Makes every commit that returned before the call durable; see [`On::flush`](https://www.unum.cloud/docs/ustore/rust/batches-and-arenas.md#flush).

```rust
pub fn flush(&self) -> Result<()>
```

## head

The head of the database, where writes land and reads see the latest committed state.

```rust
pub fn head(&self) -> On<'_>
```

## transaction

Begins a transaction over this database, which conflicts rather than blocks.

```rust
pub fn transaction(&self) -> Result<Transaction<'_>>
```

## snapshot

Pins a point-in-time view of the database, which it releases when dropped.

```rust
pub fn snapshot(&self) -> Result<Snapshot<'_>>
```

## collection_create

Creates an empty collection holding `modality` and binds `name` to it, refusing a name already in use.

```rust
pub fn collection_create(&self, name: &str, modality: Modality) -> Result<CollectionID>
```

Calls `ustore_collection_create`.

## collection_drop

Removes the contents of a collection, or the collection itself together with its name.

```rust
pub fn collection_drop(&self, collection: CollectionID, mode: DropMode) -> Result<()>
```

## changes_cursor

Opens a feed of the changes committed to [`collection`](https://www.unum.cloud/docs/ustore/rust/transactions.md#collection) after `since`, oldest first, reading nothing until its first pull.

```rust
pub fn changes_cursor(
    &self,
    collection: CollectionID,
    config: impl Into<ChangesCursorConfig>,
) -> Result<ChangesCursor<'_>>
```

A feed whose history is already gone is refused with [`Status::WriteConflict`](https://www.unum.cloud/docs/ustore/rust/errors.md#WriteConflict), and an
engine that keeps no stamps, as LevelDB does, refuses it with [`Status::Unsupported`](https://www.unum.cloud/docs/ustore/rust/errors.md#Unsupported).

## Engine

The engine serving a database, as `ustore_engine_t` spells it.

```rust
pub enum Engine
```

- `RAM` = `0`: The in-memory engine of [`Database::init_ram`](#init_ram) and [`Database::open_ram`](#open_ram).
- `RocksDB` = `1`: The RocksDB engine of [`Database::open_rocksdb`](#open_rocksdb) and [`Database::view_rocksdb`](#view_rocksdb).
- `LevelDB` = `2`: The LevelDB engine of [`Database::open_leveldb`](#open_leveldb).
- `NVME` = `3`: The NVMe engine of [`Database::open_nvme`](#open_nvme).

Implements: `Clone`, `Copy`, `StructuralPartialEq`, `PartialEq`, `Eq`, `Debug`, `Hash`, `Display`, `FromStr`

## LevelDBOptions

What [`Database::open_leveldb`](#open_leveldb) opens.

```rust
pub struct LevelDBOptions<'options>
```

- `directory` `&'options str`: The database's directory, which must exist.
- `executor` `Option<&'options Executor>`: The executor the open runs on, after the calls submitted there before it; [`None`](https://www.unum.cloud/docs/ustore/rust/transactions.md#None) opens on the calling thread.

Implements: `Clone`, `Copy`, `Debug`, `Default`

## at

A database in an existing directory.

```rust
pub fn at(directory: &'options str) -> Self
```

## NVMEOptions

What [`Database::open_nvme`](#open_nvme) opens, where every zero size or count keeps the engine's default.

```rust
pub struct NVMEOptions<'path>
```

- `manifest` `&'path str`: The manifest, `<database>.ustore.json` in an existing directory, or the raw address of
the first slot.
- `data_directories` `&'path [DataDirectory<'path>]`: Further data directories the runs land on, the one with the most free bytes taking each.
- `executor` `Option<&'path Executor>`: The executor the open runs on, after the calls submitted there before it; [`None`](https://www.unum.cloud/docs/ustore/rust/transactions.md#None) opens on the calling thread.
The database moves bytes as one of [`Executor::for_nvme`](https://www.unum.cloud/docs/ustore/rust/batches-and-arenas.md#for_nvme) says, read once at the open, and with that call's
defaults for any other executor and for none.
- `compactions` `Option<&'path Executor>`: The executor of [`Executor::for_vram`](https://www.unum.cloud/docs/ustore/rust/batches-and-arenas.md#for_vram) whose device and scratch limit every merge takes, read once at the open;
[`None`](https://www.unum.cloud/docs/ustore/rust/transactions.md#None) merges on host threads.
- `memory_limit` `u64`: Bytes of host memory the engine may pin and cache.
- `transaction_max_bytes` `u64`: Bytes a transaction may buffer before it must commit.
- `transaction_max_deltas` `usize`: Deltas a transaction may buffer before it must commit.
- `collection_concurrency_limit` `usize`: Operations that may run on one collection at once.
- `collection_cache_limit` `u64`: Bytes of values each collection may cache.
- `collection_memory_runs_max_bytes` `u64`: Bytes of memory runs a collection holds before the commit that crosses them flushes level 0.
- `collection_memory_runs_max_deltas` `usize`: Deltas of memory runs a collection holds before the commit that crosses them flushes level 0.
- `collection_level_enlarge_factor` `usize`: How many times larger each level of a collection is than the one above it.
- `collection_value_size` `u64`: Bytes of every value of a collection whose values share one size, or zero for varying sizes.
- `collection_value_max_size` `u64`: Bytes of the largest value of a collection whose values vary in size.
- `cpu_class` `Option<CPUClass>`: The CPU class the database confines itself to, failing with [`Status::Unsupported`](https://www.unum.cloud/docs/ustore/rust/errors.md#Unsupported) where the CPU does not run
it; [`None`](https://www.unum.cloud/docs/ustore/rust/transactions.md#None) takes what the CPU offers.

Implements: `Clone`, `Copy`, `Debug`, `Default`

## at

The database a manifest names, with every default.

```rust
pub fn at(manifest: &'path str) -> Self
```

## RAMOptions

How [`Database::init_ram`](#init_ram) and [`Database::open_ram`](#open_ram) start the in-memory engine.

```rust
pub struct RAMOptions<'options>
```

- `isolation` `Isolation`: How transactions see each other.
- `executor` `Option<&'options Executor>`: The executor the open runs on, after the calls submitted there before it; [`None`](https://www.unum.cloud/docs/ustore/rust/transactions.md#None) opens on the calling thread.
- `cpu_class` `Option<CPUClass>`: The CPU class the database confines itself to, failing with [`Status::Unsupported`](https://www.unum.cloud/docs/ustore/rust/errors.md#Unsupported) where the CPU does not run
it; [`None`](https://www.unum.cloud/docs/ustore/rust/transactions.md#None) takes what the CPU offers.

Implements: `Clone`, `Copy`, `Debug`, `Default`

## RocksDBOptions

What [`Database::open_rocksdb`](#open_rocksdb) and [`Database::view_rocksdb`](#view_rocksdb) open.

```rust
pub struct RocksDBOptions<'options>
```

- `directory` `&'options str`: The database's directory, which must exist.
- `data_directories` `&'options [DataDirectory<'options>]`: Directories the table files fill in order, or none to keep them in `directory`.
- `executor` `Option<&'options Executor>`: The executor the open runs on, after the calls submitted there before it; [`None`](https://www.unum.cloud/docs/ustore/rust/transactions.md#None) opens on the calling thread.

Implements: `Clone`, `Copy`, `Debug`, `Default`

## at

A database in an existing directory.

```rust
pub fn at(directory: &'options str) -> Self
```

