Skip to main content

fjall/
lib.rs

1// Copyright (c) 2024-present, fjall-rs
2// This source code is licensed under both the Apache 2.0 and MIT License
3// (found in the LICENSE-* files in the repository)
4
5//! Fjall is a log-structured embeddable key-value storage engine written in Rust. It features:
6//!
7//! - A thread-safe BTreeMap-like API
8//! - 100% safe & stable Rust
9//! - LSM-tree-based storage similar to `RocksDB`
10//! - Range & prefix searching with forward and reverse iteration
11//! - Keyspaces (a.k.a. column families) with cross-keyspace atomic semantics
12//! - Built-in compression (default = `LZ4`)
13//! - Serializable transactions (optional)
14//! - Key-value separation for large blob use cases (optional)
15//! - Automatic background maintenance
16//!
17//! It is not:
18//!
19//! - A standalone database server
20//! - A relational or wide-column database: it has no notion of columns or query language
21//!
22//! Keys are limited to 65536 bytes, values are limited to 2^32 bytes. As is normal with any kind of storage engine, larger keys and values have a bigger performance impact.
23//!
24//! For the underlying LSM-tree implementation, see: <https://crates.io/crates/lsm-tree>.
25//!
26//! ## Basic usage
27//!
28//! ```
29//! use fjall::{PersistMode, Database, KeyspaceCreateOptions};
30//! #
31//! # let folder = tempfile::tempdir().unwrap();
32//!
33//! // A database may contain multiple keyspaces
34//! // You should probably only use a single database for your application
35//! let db = Database::builder(&folder).open()?;
36//! // TxDatabase::builder for transactional semantics
37//!
38//! // Each keyspace is its own physical LSM-tree
39//! let items = db.keyspace("my_items", KeyspaceCreateOptions::default)?;
40//!
41//! // Write some data
42//! items.insert("a", "hello")?;
43//!
44//! // And retrieve it
45//! let bytes = items.get("a")?;
46//!
47//! // Or remove it again
48//! items.remove("a")?;
49//!
50//! // Search by prefix
51//! for kv in items.prefix("user1") {
52//!   // ...
53//! }
54//!
55//! // Iterators implement DoubleEndedIterator, so you can search backwards, too!
56//! for kv in items.prefix("prefix").rev() {
57//!   // ...
58//! }
59//!
60//! // Search by range
61//! for kv in items.range("a"..="z") {
62//!   // ...
63//! }
64//!
65//! // Sync the journal to disk to make sure data is definitely durable
66//! // When the database is dropped, it will try to persist with `PersistMode::SyncAll` as well
67//! db.persist(PersistMode::SyncAll)?;
68//! #
69//! # Ok::<_, fjall::Error>(())
70//! ```
71
72#![doc(html_logo_url = "https://raw.githubusercontent.com/fjall-rs/fjall/main/logo.png")]
73#![doc(html_favicon_url = "https://raw.githubusercontent.com/fjall-rs/fjall/main/logo.png")]
74#![deny(unsafe_code)]
75#![deny(clippy::all, missing_docs, clippy::cargo)]
76#![deny(clippy::unwrap_used)]
77#![deny(clippy::indexing_slicing)]
78#![warn(clippy::pedantic, clippy::nursery)]
79#![warn(clippy::expect_used)]
80#![allow(clippy::missing_const_for_fn, clippy::significant_drop_tightening)]
81#![warn(clippy::multiple_crate_versions)]
82#![cfg_attr(docsrs, feature(doc_cfg))]
83
84macro_rules! fail_iter {
85    ($e:expr) => {
86        match $e {
87            Ok(v) => v,
88            Err(e) => return Some(Err(e.into())),
89        }
90    };
91}
92
93mod batch;
94mod builder;
95
96/// Contains compaction strategies
97pub mod compaction;
98
99mod db_config;
100
101#[cfg(feature = "__internal_whitebox")]
102#[doc(hidden)]
103pub mod drop;
104
105mod db;
106
107#[cfg(test)]
108mod db_test;
109
110mod error;
111mod file;
112mod flush;
113mod guard;
114mod ingestion;
115mod iter;
116mod journal;
117mod keyspace;
118mod locked_file;
119mod meta_keyspace;
120mod path;
121mod poison_dart;
122mod readable;
123mod recovery;
124mod snapshot;
125mod snapshot_nonce;
126mod snapshot_tracker;
127mod stats;
128mod supervisor;
129mod tx;
130mod version;
131mod worker_pool;
132mod write_buffer_manager;
133
134pub(crate) type HashMap<K, V> = std::collections::HashMap<K, V, xxhash_rust::xxh3::Xxh3Builder>;
135
136/// Configuration policies
137pub mod config {
138    pub use lsm_tree::config::{
139        BlockSizePolicy, BloomConstructionPolicy, CompressionPolicy, FilterPolicy,
140        FilterPolicyEntry, HashRatioPolicy, PartitioningPolicy, PinningPolicy,
141        RestartIntervalPolicy,
142    };
143}
144
145pub use {
146    batch::WriteBatch as OwnedWriteBatch,
147    builder::Builder as DatabaseBuilder,
148    db::Database,
149    db_config::Config,
150    error::{Error, Result},
151    guard::Guard,
152    iter::Iter,
153    journal::{error::RecoveryError as JournalRecoveryError, writer::PersistMode},
154    keyspace::{options::CreateOptions as KeyspaceCreateOptions, Keyspace},
155    readable::Readable,
156    snapshot::Snapshot,
157    version::FormatVersion,
158};
159
160pub use tx::single_writer::{
161    SingleWriterTxKeyspace, TxDatabase as SingleWriterTxDatabase,
162    WriteTransaction as SingleWriterWriteTx,
163};
164
165pub use tx::optimistic::{
166    Conflict, OptimisticTxDatabase, OptimisticTxKeyspace, WriteTransaction as OptimisticWriteTx,
167};
168
169#[doc(hidden)]
170pub use lsm_tree::{AbstractTree, AnyTree, Error as LsmError, TreeType};
171
172pub use lsm_tree::{
173    CompressionType, KvPair, KvSeparationOptions, SeqNo, Slice, UserKey, UserValue,
174};
175
176/// Utility functions
177pub mod util {
178    pub use lsm_tree::util::{prefix_to_range, prefixed_range};
179}