Replace RocksDB with LevelDB
This commit is contained in:
parent
f1584dada4
commit
7d067926dd
@ -4,12 +4,16 @@ version = "0.1.0"
|
|||||||
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tempfile = "3"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
blake2-rfc = "0.2.18"
|
blake2-rfc = "0.2.18"
|
||||||
bls = { path = "../../eth2/utils/bls" }
|
bls = { path = "../../eth2/utils/bls" }
|
||||||
bytes = "0.4.10"
|
bytes = "0.4.10"
|
||||||
|
db-key = "0.0.5"
|
||||||
|
leveldb = "0.8.4"
|
||||||
parking_lot = "0.7"
|
parking_lot = "0.7"
|
||||||
rocksdb = "0.10.1"
|
|
||||||
ssz = { path = "../../eth2/utils/ssz" }
|
ssz = { path = "../../eth2/utils/ssz" }
|
||||||
ssz_derive = { path = "../../eth2/utils/ssz_derive" }
|
ssz_derive = { path = "../../eth2/utils/ssz_derive" }
|
||||||
tree_hash = { path = "../../eth2/utils/tree_hash" }
|
tree_hash = { path = "../../eth2/utils/tree_hash" }
|
||||||
|
100
beacon_node/db/src/leveldb_store.rs
Normal file
100
beacon_node/db/src/leveldb_store.rs
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
use super::*;
|
||||||
|
use db_key::Key;
|
||||||
|
use leveldb::database::kv::KV;
|
||||||
|
use leveldb::database::Database;
|
||||||
|
use leveldb::error::Error as LevelDBError;
|
||||||
|
use leveldb::options::{Options, ReadOptions, WriteOptions};
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
pub struct LevelDB<K: Key> {
|
||||||
|
db: RwLock<Database<K>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K: Key> LevelDB<K> {
|
||||||
|
pub fn open(path: &Path) -> Result<Self, Error> {
|
||||||
|
let mut options = Options::new();
|
||||||
|
|
||||||
|
options.create_if_missing = true;
|
||||||
|
|
||||||
|
let db = Database::open(path, options)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
db: RwLock::new(db),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_options(&self) -> ReadOptions<K> {
|
||||||
|
ReadOptions::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_options(&self) -> WriteOptions {
|
||||||
|
WriteOptions::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_key_for_col(col: &str, key: &[u8]) -> BytesKey {
|
||||||
|
let mut col = col.as_bytes().to_vec();
|
||||||
|
col.append(&mut key.to_vec());
|
||||||
|
BytesKey { key: col }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BytesKey {
|
||||||
|
key: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Key for BytesKey {
|
||||||
|
fn from_u8(key: &[u8]) -> Self {
|
||||||
|
Self { key: key.to_vec() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_slice<T, F: Fn(&[u8]) -> T>(&self, f: F) -> T {
|
||||||
|
f(self.key.as_slice())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Store for LevelDB<BytesKey> {
|
||||||
|
fn get_bytes(&self, col: &str, key: &[u8]) -> Result<Option<DBValue>, Error> {
|
||||||
|
let column_key = Self::get_key_for_col(col, key);
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.read()
|
||||||
|
.get(self.read_options(), column_key)
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn put_bytes(&self, col: &str, key: &[u8], val: &[u8]) -> Result<(), Error> {
|
||||||
|
let column_key = Self::get_key_for_col(col, key);
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.write()
|
||||||
|
.put(self.write_options(), column_key, val)
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn key_exists(&self, col: &str, key: &[u8]) -> Result<bool, Error> {
|
||||||
|
let column_key = Self::get_key_for_col(col, key);
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.read()
|
||||||
|
.get(self.read_options(), column_key)
|
||||||
|
.map_err(Into::into)
|
||||||
|
.and_then(|val| Ok(val.is_some()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn key_delete(&self, col: &str, key: &[u8]) -> Result<(), Error> {
|
||||||
|
let column_key = Self::get_key_for_col(col, key);
|
||||||
|
self.db
|
||||||
|
.write()
|
||||||
|
.delete(self.write_options(), column_key)
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LevelDBError> for Error {
|
||||||
|
fn from(e: LevelDBError) -> Error {
|
||||||
|
Error::DBError {
|
||||||
|
message: format!("{:?}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,8 +2,10 @@
|
|||||||
mod block_at_slot;
|
mod block_at_slot;
|
||||||
mod errors;
|
mod errors;
|
||||||
mod impls;
|
mod impls;
|
||||||
|
mod leveldb_store;
|
||||||
mod memory_db;
|
mod memory_db;
|
||||||
|
|
||||||
|
pub use self::leveldb_store::LevelDB;
|
||||||
pub use self::memory_db::MemoryDB;
|
pub use self::memory_db::MemoryDB;
|
||||||
pub use errors::Error;
|
pub use errors::Error;
|
||||||
pub use types::*;
|
pub use types::*;
|
||||||
@ -106,6 +108,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use ssz::{Decode, Encode};
|
use ssz::{Decode, Encode};
|
||||||
use ssz_derive::{Decode, Encode};
|
use ssz_derive::{Decode, Encode};
|
||||||
|
use tempfile::tempdir;
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Encode, Decode)]
|
#[derive(PartialEq, Debug, Encode, Decode)]
|
||||||
struct StorableThing {
|
struct StorableThing {
|
||||||
@ -127,6 +130,23 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn leveldb_can_store_and_retrieve() {
|
||||||
|
let dir = tempdir().unwrap();
|
||||||
|
let path = dir.path();
|
||||||
|
|
||||||
|
let store = LevelDB::open(&path).unwrap();
|
||||||
|
|
||||||
|
let key = Hash256::random();
|
||||||
|
let item = StorableThing { a: 1, b: 42 };
|
||||||
|
|
||||||
|
store.put(&key, &item).unwrap();
|
||||||
|
|
||||||
|
let retrieved = store.get(&key).unwrap().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(item, retrieved);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn memorydb_can_store_and_retrieve() {
|
fn memorydb_can_store_and_retrieve() {
|
||||||
let store = MemoryDB::open();
|
let store = MemoryDB::open();
|
||||||
|
Loading…
Reference in New Issue
Block a user