mirror of
https://github.com/hinto-janai/cuprate.git
synced 2024-11-16 15:58:14 +00:00
database: use readme for docs, link in lib.rs
This commit is contained in:
parent
a0a2cb6707
commit
bb81d34868
2 changed files with 126 additions and 124 deletions
125
storage/database/README.md
Normal file
125
storage/database/README.md
Normal file
|
@ -0,0 +1,125 @@
|
|||
# `database`
|
||||
|
||||
Cuprate's database abstraction.
|
||||
|
||||
This documentation is mostly for practical usage of `database`.
|
||||
|
||||
For a high-level overview, see the database section in
|
||||
[Cuprate's architecture book](https://architecture.cuprate.org).
|
||||
|
||||
# Purpose
|
||||
This crate does 3 things abstracts various database backends with traits.
|
||||
|
||||
If you need blockchain specific capabilities, consider using the higher-level
|
||||
`cuprate-blockchain` crate which builds upon this one.
|
||||
|
||||
# Terminology
|
||||
To be more clear on some terms used in this crate:
|
||||
|
||||
| Term | Meaning |
|
||||
|------------------|--------------------------------------|
|
||||
| `Env` | The 1 database environment, the "whole" thing
|
||||
| `DatabaseR{o,w}` | A _actively open_ readable/writable `key/value` store
|
||||
| `Table` | Solely the metadata of a `Database` (the `key` and `value` types, and the name)
|
||||
| `TxR{o,w}` | A read/write transaction
|
||||
| `Storable` | A data that type can be stored in the database
|
||||
|
||||
The dataflow is `Env` -> `Tx` -> `Database`
|
||||
|
||||
Which reads as:
|
||||
1. You have a database `Environment`
|
||||
1. You open up a `Transaction`
|
||||
1. You open a particular `Table` from that `Environment`, getting a `Database`
|
||||
1. You can now read/write data from/to that `Database`
|
||||
|
||||
# `ConcreteEnv`
|
||||
This crate exposes [`ConcreteEnv`], which is a non-generic/non-dynamic,
|
||||
concrete object representing a database [`Env`]ironment.
|
||||
|
||||
The actual backend for this type is determined via feature flags.
|
||||
|
||||
This object existing means `E: Env` doesn't need to be spread all through the codebase,
|
||||
however, it also means some small invariants should be kept in mind.
|
||||
|
||||
As `ConcreteEnv` is just a re-exposed type which has varying inner types,
|
||||
it means some properties will change depending on the backend used.
|
||||
|
||||
For example:
|
||||
- [`std::mem::size_of::<ConcreteEnv>`]
|
||||
- [`std::mem::align_of::<ConcreteEnv>`]
|
||||
|
||||
Things like these functions are affected by the backend and inner data,
|
||||
and should not be relied upon. This extends to any `struct/enum` that contains `ConcreteEnv`.
|
||||
|
||||
`ConcreteEnv` invariants you can rely on:
|
||||
- It implements [`Env`]
|
||||
- Upon [`Drop::drop`], all database data will sync to disk
|
||||
|
||||
Note that `ConcreteEnv` itself is not a clonable type,
|
||||
it should be wrapped in [`std::sync::Arc`].
|
||||
|
||||
<!-- SOMEDAY: replace `ConcreteEnv` with `fn Env::open() -> impl Env`/
|
||||
and use `<E: Env>` everywhere it is stored instead. This would allow
|
||||
generic-backed dynamic runtime selection of the database backend, i.e.
|
||||
the user can select which database backend they use. -->
|
||||
|
||||
# Feature flags
|
||||
The `service` module requires the `service` feature to be enabled.
|
||||
See the module for more documentation.
|
||||
|
||||
Different database backends are enabled by the feature flags:
|
||||
- `heed` (LMDB)
|
||||
- `redb`
|
||||
|
||||
The default is `heed`.
|
||||
|
||||
`tracing` is always enabled and cannot be disabled via feature-flag.
|
||||
<!-- FIXME: tracing should be behind a feature flag -->
|
||||
|
||||
# Examples
|
||||
The below is an example of using `database`.
|
||||
|
||||
```rust
|
||||
use database::{
|
||||
ConcreteEnv,
|
||||
config::ConfigBuilder,
|
||||
Env, EnvInner,
|
||||
DatabaseRo, DatabaseRw, TxRo, TxRw,
|
||||
};
|
||||
|
||||
# fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Create a configuration for the database environment.
|
||||
let db_dir = tempfile::tempdir()?;
|
||||
let config = ConfigBuilder::new()
|
||||
.db_directory(db_dir.path().to_path_buf())
|
||||
.build();
|
||||
|
||||
// Initialize the database environment.
|
||||
let env = ConcreteEnv::open(config)?;
|
||||
|
||||
// Open up a transaction + tables for writing.
|
||||
struct Table;
|
||||
impl database::Table for Table {
|
||||
const NAME: &'static str = "table";
|
||||
type Key = u8;
|
||||
type Value = u8;
|
||||
}
|
||||
|
||||
let env_inner = env.env_inner();
|
||||
let tx_rw = env_inner.tx_rw()?;
|
||||
env_inner.create_db::<Table>(&tx_rw)?;
|
||||
let mut table = env_inner.open_db_rw::<Table>(&tx_rw)?;
|
||||
|
||||
// Write data to the table.
|
||||
table.put(&0, &1)?;
|
||||
|
||||
// Commit the data written.
|
||||
drop(table);
|
||||
TxRw::commit(tx_rw)?;
|
||||
|
||||
// Read the data, assert it is correct.
|
||||
let tx_ro = env_inner.tx_ro()?;
|
||||
let table = env_inner.open_db_ro::<Table>(&tx_ro)?;
|
||||
assert_eq!(table.first()?, (0, 1));
|
||||
# Ok(()) }
|
||||
```
|
|
@ -1,127 +1,4 @@
|
|||
//! Cuprate's database abstraction.
|
||||
//!
|
||||
//! This documentation is mostly for practical usage of `database`.
|
||||
//!
|
||||
//! For a high-level overview, see the database section in
|
||||
//! [Cuprate's architecture book](https://architecture.cuprate.org).
|
||||
//!
|
||||
//! # Purpose
|
||||
//! This crate does 3 things abstracts various database backends with traits.
|
||||
//!
|
||||
//! If you need blockchain specific capabilities, consider using the higher-level
|
||||
//! `cuprate-blockchain` crate which builds upon this one.
|
||||
//!
|
||||
//! # Terminology
|
||||
//! To be more clear on some terms used in this crate:
|
||||
//!
|
||||
//! | Term | Meaning |
|
||||
//! |------------------|--------------------------------------|
|
||||
//! | `Env` | The 1 database environment, the "whole" thing
|
||||
//! | `DatabaseR{o,w}` | A _actively open_ readable/writable `key/value` store
|
||||
//! | `Table` | Solely the metadata of a `Database` (the `key` and `value` types, and the name)
|
||||
//! | `TxR{o,w}` | A read/write transaction
|
||||
//! | `Storable` | A data that type can be stored in the database
|
||||
//!
|
||||
//! The dataflow is `Env` -> `Tx` -> `Database`
|
||||
//!
|
||||
//! Which reads as:
|
||||
//! 1. You have a database `Environment`
|
||||
//! 1. You open up a `Transaction`
|
||||
//! 1. You open a particular `Table` from that `Environment`, getting a `Database`
|
||||
//! 1. You can now read/write data from/to that `Database`
|
||||
//!
|
||||
//! # `ConcreteEnv`
|
||||
//! This crate exposes [`ConcreteEnv`], which is a non-generic/non-dynamic,
|
||||
//! concrete object representing a database [`Env`]ironment.
|
||||
//!
|
||||
//! The actual backend for this type is determined via feature flags.
|
||||
//!
|
||||
//! This object existing means `E: Env` doesn't need to be spread all through the codebase,
|
||||
//! however, it also means some small invariants should be kept in mind.
|
||||
//!
|
||||
//! As `ConcreteEnv` is just a re-exposed type which has varying inner types,
|
||||
//! it means some properties will change depending on the backend used.
|
||||
//!
|
||||
//! For example:
|
||||
//! - [`std::mem::size_of::<ConcreteEnv>`]
|
||||
//! - [`std::mem::align_of::<ConcreteEnv>`]
|
||||
//!
|
||||
//! Things like these functions are affected by the backend and inner data,
|
||||
//! and should not be relied upon. This extends to any `struct/enum` that contains `ConcreteEnv`.
|
||||
//!
|
||||
//! `ConcreteEnv` invariants you can rely on:
|
||||
//! - It implements [`Env`]
|
||||
//! - Upon [`Drop::drop`], all database data will sync to disk
|
||||
//!
|
||||
//! Note that `ConcreteEnv` itself is not a clonable type,
|
||||
//! it should be wrapped in [`std::sync::Arc`].
|
||||
//!
|
||||
//! <!-- SOMEDAY: replace `ConcreteEnv` with `fn Env::open() -> impl Env`/
|
||||
//! and use `<E: Env>` everywhere it is stored instead. This would allow
|
||||
//! generic-backed dynamic runtime selection of the database backend, i.e.
|
||||
//! the user can select which database backend they use. -->
|
||||
//!
|
||||
//! # Feature flags
|
||||
//! The `service` module requires the `service` feature to be enabled.
|
||||
//! See the module for more documentation.
|
||||
//!
|
||||
//! Different database backends are enabled by the feature flags:
|
||||
//! - `heed` (LMDB)
|
||||
//! - `redb`
|
||||
//!
|
||||
//! The default is `heed`.
|
||||
//!
|
||||
//! `tracing` is always enabled and cannot be disabled via feature-flag.
|
||||
//! <!-- FIXME: tracing should be behind a feature flag -->
|
||||
//!
|
||||
//! # Examples
|
||||
//! The below is an example of using `database`.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use database::{
|
||||
//! ConcreteEnv,
|
||||
//! config::ConfigBuilder,
|
||||
//! Env, EnvInner,
|
||||
//! DatabaseRo, DatabaseRw, TxRo, TxRw,
|
||||
//! };
|
||||
//!
|
||||
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
//! // Create a configuration for the database environment.
|
||||
//! let db_dir = tempfile::tempdir()?;
|
||||
//! let config = ConfigBuilder::new()
|
||||
//! .db_directory(db_dir.path().to_path_buf())
|
||||
//! .build();
|
||||
//!
|
||||
//! // Initialize the database environment.
|
||||
//! let env = ConcreteEnv::open(config)?;
|
||||
//!
|
||||
//! // Open up a transaction + tables for writing.
|
||||
//! struct Table;
|
||||
//! impl database::Table for Table {
|
||||
//! const NAME: &'static str = "table";
|
||||
//! type Key = u8;
|
||||
//! type Value = u8;
|
||||
//! }
|
||||
//!
|
||||
//! let env_inner = env.env_inner();
|
||||
//! let tx_rw = env_inner.tx_rw()?;
|
||||
//! env_inner.create_db::<Table>(&tx_rw)?;
|
||||
//! let mut table = env_inner.open_db_rw::<Table>(&tx_rw)?;
|
||||
//!
|
||||
//! // Write data to the table.
|
||||
//! table.put(&0, &1)?;
|
||||
//!
|
||||
//! // Commit the data written.
|
||||
//! drop(table);
|
||||
//! TxRw::commit(tx_rw)?;
|
||||
//!
|
||||
//! // Read the data, assert it is correct.
|
||||
//! let tx_ro = env_inner.tx_ro()?;
|
||||
//! let table = env_inner.open_db_ro::<Table>(&tx_ro)?;
|
||||
//! assert_eq!(table.first()?, (0, 1));
|
||||
//! # Ok(()) }
|
||||
//! ```
|
||||
|
||||
#![doc = include_str!("../README.md")]
|
||||
//---------------------------------------------------------------------------------------------------- Lints
|
||||
// Forbid lints.
|
||||
// Our code, and code generated (e.g macros) cannot overrule these.
|
||||
|
|
Loading…
Reference in a new issue