Replace RocksDB with LevelDB

This commit is contained in:
Paul Hauner 2019-05-21 16:29:34 +10:00
parent f1584dada4
commit 7d067926dd
No known key found for this signature in database
GPG Key ID: 5E2CFF9B75FA63DF
3 changed files with 125 additions and 1 deletions

View File

@ -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" }

View 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),
}
}
}

View File

@ -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();