Skip to content

Commit c1c3c41

Browse files
committed
docs(architecture): add documentation page for Persistant Storage
1 parent fe25f14 commit c1c3c41

File tree

2 files changed

+164
-4
lines changed

2 files changed

+164
-4
lines changed

docs/architecture/storage.md

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# Persistent Storage
2+
3+
From the perspective of software architecture, __persistent storage__ is one of the key elements to maintaining a
4+
distributed block chain. Its role is allowing nodes in the network to preserve important data structures that need to be
5+
kept over time for trustless validation of new chain objects.
6+
7+
Namely, those structures are:
8+
9+
- The UTXO set
10+
- Data requests
11+
- Transactions
12+
- Blocks
13+
14+
## Generic `Storage` Trait
15+
16+
__Witnet-rust__ features a generic `Storage` Rust trait ([`storage.rs`][storage]) that exposes a key/value API with the
17+
elemental CRUD methods _(create, read, update, delete)_ while abstracting away from specific storage backend
18+
implementations.
19+
20+
```rust
21+
pub trait Storage<ConnData, Key, Value> { /** **/ }
22+
```
23+
24+
The meaning of the generic types is the following:
25+
26+
| Generic type | Description |
27+
|--------------|-------------------------------------------------------------------------------------------------------|
28+
| ConnData | Type of the data needed by the constructor for creating a connection to the storage backend. |
29+
| Key | Type of the keys used to identify the records in the storage. |
30+
| Value | Type of the values in the storage. |
31+
32+
33+
As of [PR #21][#21], Witnet-rust incorporates implementations for the following storage backends:
34+
35+
- [`rocks.rs`][rocks] : persists data into the local file system using the performant RocksDB engine.
36+
- [`in_memory.rs`][in_memory]: keeps data in a `HashMap` that lives in the memory heap.
37+
38+
!!! warning
39+
In-memory storage is implemented only for the sake of testing the `Storage` trait. It is obviously not a viable
40+
persistence solution as data is totally wiped as soon as references to the storage go out of scope or the app dies.
41+
42+
### Instantiation
43+
44+
All implementors of the `Storage` trait can be instantiated with the `witnet_storage::storage::new()` constructor,
45+
which must be used as a static method.
46+
47+
__Signature__
48+
```rust
49+
fn new(connection_data: ConnData) -> Result<Box<Self>>;
50+
```
51+
52+
!!! tip
53+
Please note that the `witnet_storage::storage::new()` method wraps the return type into a `Box`.
54+
This is to ensure the value is allocated into the heap and to allow a reference to it (the `Box` itself) to outlive
55+
the constructor.
56+
57+
__Example__
58+
```rust
59+
use witnet_storage::backends::in_memory::InMemoryStorage;
60+
61+
let storage: &InMemoryStorage = InMemoryStorage::new().unwrap();
62+
```
63+
64+
### Creating and updating records with the `put()` Method
65+
66+
The `witnet_storage::storage::put()` method allows creating or replacing a value in the storage under a certain key.
67+
68+
__Signature__
69+
```rust
70+
fn put(&mut self, key: Key, value: Value) -> Result<()>;
71+
```
72+
73+
__Example__
74+
```rust
75+
// Put value "bar" into key "foo"
76+
storage.put(b"foo", b"bar".to_vec())?;
77+
// Update value of "foo" to be "beer"
78+
storage.put(b"foo", b"beer".to_vec())?;
79+
```
80+
81+
### Getting records with the `get()` method
82+
83+
The `witnet_storage::storage::get()` method allows reading the value in the storage under a certain key.
84+
85+
__Signature__
86+
```rust
87+
fn get(&self, key: Key) -> Result<Option<Value>>;
88+
```
89+
90+
__Example__
91+
```rust
92+
match storage.get(b"foo") {
93+
Ok(Some(value)) => , // Found a value
94+
Ok(None) => , // The key didn't exist
95+
Err(error) => // Error while reading
96+
}
97+
```
98+
99+
### Deleting records with the `delete()` method
100+
101+
The `witnet_storage::storage::delete()` method allows deleting a record in the storage given its key.
102+
103+
__Signature__
104+
```rust
105+
fn delete(&mut self, key: Key) -> Result<()>;
106+
```
107+
108+
__Example__
109+
```rust
110+
storage.delete(b"foo")?;
111+
```
112+
113+
## RocksDB Storage Backend
114+
115+
The `RocksDB` storage backend ([`rocks.rs`][rocks]) is one of the bundled storage backends in Witnet-rust.
116+
It implements all the methods of the `Storage` trait for the `RocksStorage` struct:
117+
118+
```rust
119+
/// Data structure for the RocksDB storage whose only member is a
120+
/// rocksdb::DB object.
121+
pub struct RocksStorage {
122+
db: DB
123+
}
124+
```
125+
126+
The actual implementor looks like this (function bodies and some lifetime annotations have been omitted for
127+
brevity):
128+
129+
```rust
130+
// Implement the Storage generic trait for the RocksStorage storage
131+
// data structure.
132+
impl Storage<&str, &[u8], Vec<u8>> for RocksStorage {
133+
134+
fn new(path: &str) -> Result<Box<Self>>;
135+
136+
fn put(&mut self, key: &[u8], value: Vec<u8>) -> Result<()>;
137+
138+
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
139+
140+
fn delete(&mut self, key: &[u8]) -> Result<()>;
141+
142+
}
143+
144+
```
145+
146+
These are the specific types for this implementor:
147+
148+
| Generic type | Specific type |
149+
|--------------|-------------------------------------------------------------------------------------------------------|
150+
| `ConnData` | `&str` |
151+
| `Key` | `&[u8]` |
152+
| `Value` | `Vec<u8>` |
153+
154+
The full source code of the `Storage` implementor for `RocksStorage` can be found at [`rocks.rs`][rocks].
155+
156+
[#21]: https://github.com/witnet/witnet-rust/pull/21
157+
[storage]: https://github.com/witnet/witnet-rust/blob/master/storage/src/storage.rs
158+
[rocks]: https://github.com/witnet/witnet-rust/blob/master/storage/src/backends/source.rs
159+
[in_memory]: https://github.com/witnet/witnet-rust/blob/master/storage/src/backends/in_memory.rs

mkdocs.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ nav:
2727
- Connections: architecture/p2p/connections
2828
- Gossiping: architecture/p2p/gossip
2929
- Encoding (FlatBuffers): architecture/p2p/encoding
30-
- Storage: architecture/storage
30+
- Persistent Storage: architecture/storage
3131
- Mempool Management: architecture/mempool-mgmt
3232
- Block Management: architecture/block-mgmt
3333
- UTXO Management: architecture/utxo-mgmt
@@ -50,8 +50,8 @@ theme:
5050
favicon: 'assets/images/favicon.ico'
5151
logo: 'assets/images/logo.svg" alt="Witnet Logo'
5252
palette:
53-
primary: 'indigo'
54-
accent: 'deep purple'
53+
primary: 'brown'
54+
accent: 'deep orange'
5555

5656
repo_name: 'witnet/witnet-rust'
5757
repo_url: 'https://github.com/witnet/witnet-rust'
@@ -70,7 +70,8 @@ extra:
7070

7171
markdown_extensions:
7272
- admonition
73-
- codehilite
73+
- codehilite:
74+
linenums: true
7475
- footnotes
7576
- toc:
7677
permalink: true

0 commit comments

Comments
 (0)