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
use parking_lot::Mutex; use kv::{Transaction, Value, KeyValueDatabase, MemoryDatabase, KeyState, Key}; pub struct OverlayDatabase<'a, T> where T: 'a + KeyValueDatabase { db: &'a T, overlay: MemoryDatabase, } impl<'a, T> OverlayDatabase<'a, T> where T: 'a + KeyValueDatabase { pub fn new(db: &'a T) -> Self { OverlayDatabase { db: db, overlay: MemoryDatabase::default(), } } pub fn flush(&self) -> Result<(), String> { self.db.write(self.overlay.drain_transaction()) } } impl<'a, T> KeyValueDatabase for OverlayDatabase<'a, T> where T: 'a + KeyValueDatabase { fn write(&self, tx: Transaction) -> Result<(), String> { self.overlay.write(tx) } fn get(&self, key: &Key) -> Result<KeyState<Value>, String> { match self.overlay.get(key)? { KeyState::Unknown => self.db.get(key), exists => Ok(exists) } } } 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, key: &Key) -> Result<KeyState<Value>, String> { match self.overlay.get(key)? { KeyState::Unknown => self.db.get(key), exists => Ok(exists) } } } impl<T> Drop for AutoFlushingOverlayDatabase<T> where T: KeyValueDatabase { fn drop(&mut self) { self.flush().expect("Failed to save database"); } }