1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use std::path::Path;
use casper_types::bytesrepr::Bytes;
use lmdb::{
self, Database, Environment, EnvironmentFlags, RoTransaction, RwTransaction, WriteFlags,
};
use crate::storage::{
error,
transaction_source::{Readable, Transaction, TransactionSource, Writable},
MAX_DBS,
};
const EE_DB_FILENAME: &str = "data.lmdb";
impl<'a> Transaction for RoTransaction<'a> {
type Error = lmdb::Error;
type Handle = Database;
fn commit(self) -> Result<(), Self::Error> {
lmdb::Transaction::commit(self)
}
}
impl<'a> Readable for RoTransaction<'a> {
fn read(&self, handle: Self::Handle, key: &[u8]) -> Result<Option<Bytes>, Self::Error> {
match lmdb::Transaction::get(self, handle, &key) {
Ok(bytes) => Ok(Some(Bytes::from(bytes))),
Err(lmdb::Error::NotFound) => Ok(None),
Err(e) => Err(e),
}
}
}
impl<'a> Transaction for RwTransaction<'a> {
type Error = lmdb::Error;
type Handle = Database;
fn commit(self) -> Result<(), Self::Error> {
<RwTransaction<'a> as lmdb::Transaction>::commit(self)
}
}
impl<'a> Readable for RwTransaction<'a> {
fn read(&self, handle: Self::Handle, key: &[u8]) -> Result<Option<Bytes>, Self::Error> {
match lmdb::Transaction::get(self, handle, &key) {
Ok(bytes) => Ok(Some(Bytes::from(bytes))),
Err(lmdb::Error::NotFound) => Ok(None),
Err(e) => Err(e),
}
}
}
impl<'a> Writable for RwTransaction<'a> {
fn write(&mut self, handle: Self::Handle, key: &[u8], value: &[u8]) -> Result<(), Self::Error> {
self.put(handle, &key, &value, WriteFlags::empty())
.map_err(Into::into)
}
}
#[derive(Debug)]
pub struct LmdbEnvironment {
env: Environment,
}
impl LmdbEnvironment {
pub fn new<P: AsRef<Path>>(
path: P,
map_size: usize,
max_readers: u32,
) -> Result<Self, error::Error> {
let env = Environment::new()
.set_flags(EnvironmentFlags::NO_SUB_DIR)
.set_max_dbs(MAX_DBS)
.set_map_size(map_size)
.set_max_readers(max_readers)
.open(&path.as_ref().join(EE_DB_FILENAME))?;
Ok(LmdbEnvironment { env })
}
pub fn env(&self) -> &Environment {
&self.env
}
}
impl<'a> TransactionSource<'a> for LmdbEnvironment {
type Error = lmdb::Error;
type Handle = Database;
type ReadTransaction = RoTransaction<'a>;
type ReadWriteTransaction = RwTransaction<'a>;
fn create_read_txn(&'a self) -> Result<RoTransaction<'a>, Self::Error> {
self.env.begin_ro_txn()
}
fn create_read_write_txn(&'a self) -> Result<RwTransaction<'a>, Self::Error> {
self.env.begin_rw_txn()
}
}