Merge pull request #391 from paritytech/auto_flushing
AutoFlushingOverlayDatabase
This commit is contained in:
commit
a65be02b25
|
@ -14,7 +14,7 @@ use ser::{
|
|||
};
|
||||
use kv::{
|
||||
KeyValueDatabase, OverlayDatabase, Transaction as DBTransaction, Location, Value, DiskDatabase,
|
||||
DatabaseConfig, MemoryDatabase
|
||||
DatabaseConfig, MemoryDatabase, AutoFlushingOverlayDatabase
|
||||
};
|
||||
use best_block::BestBlock;
|
||||
use {
|
||||
|
@ -58,7 +58,7 @@ impl<'a, T> ForkChain for ForkChainDatabase<'a, T> where T: KeyValueDatabase {
|
|||
}
|
||||
}
|
||||
|
||||
impl BlockChainDatabase<DiskDatabase> {
|
||||
impl BlockChainDatabase<AutoFlushingOverlayDatabase<DiskDatabase>> {
|
||||
pub fn open_at_path<P>(path: P, total_cache: usize) -> Result<Self, Error> where P: AsRef<Path> {
|
||||
fs::create_dir_all(path.as_ref()).map_err(|err| Error::DatabaseError(err.to_string()))?;
|
||||
let mut cfg = DatabaseConfig::with_columns(Some(COL_COUNT));
|
||||
|
@ -74,7 +74,7 @@ impl BlockChainDatabase<DiskDatabase> {
|
|||
cfg.bloom_filters.insert(Some(COL_TRANSACTIONS_META), 32);
|
||||
|
||||
match DiskDatabase::open(cfg, path) {
|
||||
Ok(db) => Ok(Self::open(db)),
|
||||
Ok(db) => Ok(Self::open_with_cache(db)),
|
||||
Err(err) => Err(Error::DatabaseError(err))
|
||||
}
|
||||
}
|
||||
|
@ -92,6 +92,17 @@ impl BlockChainDatabase<MemoryDatabase> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> BlockChainDatabase<AutoFlushingOverlayDatabase<T>> where T: KeyValueDatabase {
|
||||
pub fn open_with_cache(db: T) -> Self {
|
||||
let db = AutoFlushingOverlayDatabase::new(db, 50);
|
||||
let best_block = Self::read_best_block(&db).unwrap_or_default();
|
||||
BlockChainDatabase {
|
||||
best_block: RwLock::new(best_block),
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> BlockChainDatabase<T> where T: KeyValueDatabase {
|
||||
fn read_best_block(db: &T) -> Option<BestBlock> {
|
||||
let best_number = db.get(COL_META.into(), KEY_BEST_BLOCK_NUMBER);
|
||||
|
|
|
@ -7,5 +7,5 @@ mod transaction;
|
|||
pub use self::db::KeyValueDatabase;
|
||||
pub use self::diskdb::{Database as DiskDatabase, DatabaseConfig, CompactionProfile};
|
||||
pub use self::memorydb::{MemoryDatabase, SharedMemoryDatabase};
|
||||
pub use self::overlaydb::OverlayDatabase;
|
||||
pub use self::overlaydb::{OverlayDatabase, AutoFlushingOverlayDatabase};
|
||||
pub use self::transaction::{Transaction, Operation, Location, Key, Value, KeyState};
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use parking_lot::Mutex;
|
||||
use kv::{Transaction, Location, Value, KeyValueDatabase, MemoryDatabase};
|
||||
|
||||
pub struct OverlayDatabase<'a, T> where T: 'a + KeyValueDatabase {
|
||||
|
@ -31,3 +32,52 @@ impl<'a, T> KeyValueDatabase for OverlayDatabase<'a, T> where T: 'a + KeyValueDa
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AutoFlushingOverlayDatabase<T> where T: KeyValueDatabase {
|
||||
db: T,
|
||||
overlay: MemoryDatabase,
|
||||
operations: Mutex<usize>,
|
||||
max_operations: usize,
|
||||
}
|
||||
|
||||
impl<T> AutoFlushingOverlayDatabase<T> where T: KeyValueDatabase {
|
||||
pub fn new(db: T, max_operations: usize) -> Self {
|
||||
AutoFlushingOverlayDatabase {
|
||||
db: db,
|
||||
overlay: MemoryDatabase::default(),
|
||||
operations: Mutex::default(),
|
||||
max_operations: max_operations,
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&self) -> Result<(), String> {
|
||||
self.db.write(self.overlay.drain_transaction())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> KeyValueDatabase for AutoFlushingOverlayDatabase<T> where T: KeyValueDatabase {
|
||||
fn write(&self, tx: Transaction) -> Result<(), String> {
|
||||
let mut operations = self.operations.lock();
|
||||
*operations += 1;
|
||||
self.overlay.write(tx)?;
|
||||
if *operations == self.max_operations {
|
||||
self.flush()?;
|
||||
*operations = 0;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get(&self, location: Location, key: &[u8]) -> Result<Option<Value>, String> {
|
||||
if self.overlay.is_known(location, key) {
|
||||
self.overlay.get(location, key)
|
||||
} else {
|
||||
self.db.get(location, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for AutoFlushingOverlayDatabase<T> where T: KeyValueDatabase {
|
||||
fn drop(&mut self) {
|
||||
self.flush().expect("Failed to save database");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue