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
use std::error::Error; use std::path::PathBuf; use crate::account::db_state::DBState; use crate::database::IDB; use crate::traits::{Decode, Encode, Exception}; use rocksdb::DB as RocksDB; use starling::traits::Database; impl<DBType> Database for StateDB<DBType> where DBType: IDB, { type NodeType = DBState; type EntryType = (Vec<u8>, Self::NodeType); fn open(_path: &PathBuf) -> Result<StateDB<DBType, Self::EntryType>, Box<Error>> { return Err(Box::new(Exception::new( "Open the database using new, not open", ))); } fn get_node(&self, key: &[u8]) -> Result<Option<Self::NodeType>, Box<Error>> { let bytes = self.database._get(&key)?; Ok(Some(Self::NodeType::decode(&bytes)?)) } fn insert(&mut self, key: &[u8], value: &Self::NodeType) -> Result<(), Box<Error>> { self.pending_inserts.push((key.to_vec(), value.clone())); Ok(()) } fn remove(&mut self, key: &[u8]) -> Result<(), Box<Error>> { self.database.delete(key)?; Ok(()) } fn batch_write(&mut self) -> Result<(), Box<Error>> { let mut batch = Vec::with_capacity(self.pending_inserts.len()); while self.pending_inserts.len() > 0 { let entry = self.pending_inserts.remove(0); let key = entry.0; let value = entry.1; batch.push((key, value.encode()?)); } self.database.write_batch(batch)?; Ok(()) } } pub struct StateDB<DatabaseType = RocksDB, EntryType = (Vec<u8>, DBState)> { database: DatabaseType, pending_inserts: Vec<EntryType>, } impl<DatabaseType, EntryType, OptionType> StateDB<DatabaseType, EntryType> where DatabaseType: IDB<OptionType = OptionType>, { pub fn new( path: PathBuf, options: Option<OptionType>, ) -> Result<StateDB<DatabaseType, EntryType>, Box<Error>> { let database = DatabaseType::open(path, options)?; let pending_inserts = Vec::with_capacity(40000); Ok(StateDB { database, pending_inserts, }) } } #[cfg(test)] mod tests { use super::*; use crate::database::mock::RocksDBMock; #[test] fn it_opens_a_state_db() { let path = PathBuf::new(); let _state_db: StateDB<RocksDBMock> = StateDB::new(path, None).unwrap(); } }