db cache refactor in progress

This commit is contained in:
debris 2017-04-21 13:59:06 +02:00
parent 6aa78e42e1
commit f4c958e9f2
7 changed files with 236 additions and 198 deletions

View File

@ -1,7 +1,7 @@
use kv::{Location, Transaction, Value, DatabaseKey};
use kv::{Transaction, KeyState, Key, Value};
pub trait KeyValueDatabase: Send + Sync {
fn write(&self, tx: Transaction) -> Result<(), String>;
fn get<Key, Value>(&self, key: &Key) -> Result<Option<Value>, String> where Key: DatabaseKey<Value>;
fn get(&self, key: &Key) -> Result<KeyState<Value>, String>;
}

View File

@ -6,7 +6,9 @@ use rocksdb::{
DB, Writable, WriteBatch, WriteOptions, IteratorMode, DBIterator,
Options, DBCompactionStyle, BlockBasedOptions, Cache, Column, ReadOptions
};
use kv::{Transaction, RawTransaction, RawOperation, Location, Value, KeyValueDatabase, DatabaseKey};
use bytes::Bytes;
use kv::{Transaction, RawTransaction, RawOperation, Location, Value, KeyValueDatabase, Key, KeyState, RawKeyValue,
RawKey};
const DB_BACKGROUND_FLUSHES: i32 = 2;
const DB_BACKGROUND_COMPACTIONS: i32 = 2;
@ -121,13 +123,14 @@ pub struct Database {
impl KeyValueDatabase for Database {
fn write(&self, tx: Transaction) -> Result<(), String> {
Database::write(self, tx.into())
Database::write(self, (&tx).into())
}
fn get<Key, Value>(&self, key: &Key) -> Result<Option<Value>, String> where Key: DatabaseKey<Value> {
unimplemented!();
//fn get(&self, location: Location, key: &[u8]) -> Result<Option<Value>, String> {
//Database::get(self, location, key)
fn get(&self, key: &Key) -> Result<KeyState<Value>, String> {
match Database::get(self, &key.into())? {
Some(value) => Ok(KeyState::Insert(Value::for_key(key, &value)?)),
None => Ok(KeyState::Unknown)
}
}
}
@ -246,11 +249,11 @@ impl Database {
let batch = WriteBatch::new();
for op in tx.operations.into_iter() {
match op {
RawOperation::Insert { location, key, value } => match location {
RawOperation::Insert(RawKeyValue { location, key, value }) => match location {
Location::DB => batch.put(&key, &value)?,
Location::Column(col) => batch.put_cf(cfs[col as usize], &key, &value)?,
},
RawOperation::Delete { location, key } => match location {
RawOperation::Delete(RawKey { location, key }) => match location {
Location::DB => batch.delete(&key)?,
Location::Column(col) => batch.delete_cf(cfs[col as usize], &key)?,
},
@ -260,15 +263,15 @@ impl Database {
}
/// Get value by key.
pub fn get(&self, location: Location, key: &[u8]) -> Result<Option<Value>, String> {
pub fn get(&self, key: &RawKey) -> Result<Option<Bytes>, String> {
let DBAndColumns { ref db, ref cfs } = self.db;
match location {
match key.location {
Location::DB => {
let value = db.get_opt(key, &self.read_opts)?;
let value = db.get_opt(&key.key, &self.read_opts)?;
Ok(value.map(|v| (&*v).into()))
},
Location::Column(col) => {
let value = db.get_cf_opt(cfs[col as usize], key, &self.read_opts)?;
let value = db.get_cf_opt(cfs[col as usize], &key.key, &self.read_opts)?;
Ok(value.map(|v| (&*v).into()))
}
}

View File

@ -6,7 +6,7 @@ use hash::H256;
use bytes::Bytes;
use ser::List;
use chain::{Transaction as ChainTransaction, BlockHeader};
use kv::{Transaction, Key, KeyState, Location, Operation, Value, KeyValueDatabase, DatabaseKey, Insert, Delete};
use kv::{Transaction, Key, KeyState, Operation, Value, KeyValueDatabase, KeyValue};
use {TransactionMeta};
#[derive(Default, Debug)]
@ -29,40 +29,25 @@ impl MemoryDatabase {
pub fn drain_transaction(&self) -> Transaction {
let mut db = self.db.write();
let meta = replace(&mut db.meta, HashMap::default()).into_iter()
.map(|(key, state)| match state {
KeyState::Insert(value) => Operation::Insert(Insert::Meta(key, value)),
KeyState::Delete => Operation::Delete(Delete::Meta(key)),
});
.flat_map(|(key, state)| state.into_operation(key, KeyValue::Meta, Key::Meta));
let block_hash = replace(&mut db.block_hash, HashMap::default()).into_iter()
.map(|(key, state)| match state {
KeyState::Insert(value) => Operation::Insert(Insert::BlockHash(key, value)),
KeyState::Delete => Operation::Delete(Delete::BlockHash(key)),
});
.flat_map(|(key, state)| state.into_operation(key, KeyValue::BlockHash, Key::BlockHash));
let block_header = replace(&mut db.block_header, HashMap::default()).into_iter()
.map(|(key, state)| match state {
KeyState::Insert(value) => Operation::Insert(Insert::BlockHeader(key, value)),
KeyState::Delete => Operation::Delete(Delete::BlockHeader(key)),
});
.flat_map(|(key, state)| state.into_operation(key, KeyValue::BlockHeader, Key::BlockHeader));
let block_transactions = replace(&mut db.block_transactions, HashMap::default()).into_iter()
.map(|(key, state)| match state {
KeyState::Insert(value) => Operation::Insert(Insert::BlockTransactions(key, value)),
KeyState::Delete => Operation::Delete(Delete::BlockTransactions(key)),
});
.flat_map(|(key, state)| state.into_operation(key, KeyValue::BlockTransactions, Key::BlockTransactions));
let transaction = replace(&mut db.transaction, HashMap::default()).into_iter()
.map(|(key, state)| match state {
KeyState::Insert(value) => Operation::Insert(Insert::Transaction(key, value)),
KeyState::Delete => Operation::Delete(Delete::Transaction(key)),
});
.flat_map(|(key, state)| state.into_operation(key, KeyValue::Transaction, Key::Transaction));
let transaction_meta = replace(&mut db.transaction_meta, HashMap::default()).into_iter()
.map(|(key, state)| match state {
KeyState::Insert(value) => Operation::Insert(Insert::TransactionMeta(key, value)),
KeyState::Delete => Operation::Delete(Delete::TransactionMeta(key)),
});
.flat_map(|(key, state)| state.into_operation(key, KeyValue::TransactionMeta, Key::TransactionMeta));
let block_number = replace(&mut db.block_number, HashMap::default()).into_iter()
.map(|(key, state)| match state {
KeyState::Insert(value) => Operation::Insert(Insert::BlockNumber(key, value)),
KeyState::Delete => Operation::Delete(Delete::BlockNumber(key)),
});
.flat_map(|(key, state)| state.into_operation(key, KeyValue::BlockNumber, Key::BlockNumber));
Transaction {
operations: meta
@ -83,44 +68,41 @@ impl KeyValueDatabase for MemoryDatabase {
for op in tx.operations.into_iter() {
match op {
Operation::Insert(insert) => match insert {
Insert::Meta(key, value) => { db.meta.insert(key, KeyState::Insert(value)); },
Insert::BlockHash(key, value) => { db.block_hash.insert(key, KeyState::Insert(value)); },
Insert::BlockHeader(key, value) => { db.block_header.insert(key, KeyState::Insert(value)); },
Insert::BlockTransactions(key, value) => { db.block_transactions.insert(key, KeyState::Insert(value)); },
Insert::Transaction(key, value) => { db.transaction.insert(key, KeyState::Insert(value)); },
Insert::TransactionMeta(key, value) => { db.transaction_meta.insert(key, KeyState::Insert(value)); },
Insert::BlockNumber(key, value) => { db.block_number.insert(key, KeyState::Insert(value)); },
KeyValue::Meta(key, value) => { db.meta.insert(key, KeyState::Insert(value)); },
KeyValue::BlockHash(key, value) => { db.block_hash.insert(key, KeyState::Insert(value)); },
KeyValue::BlockHeader(key, value) => { db.block_header.insert(key, KeyState::Insert(value)); },
KeyValue::BlockTransactions(key, value) => { db.block_transactions.insert(key, KeyState::Insert(value)); },
KeyValue::Transaction(key, value) => { db.transaction.insert(key, KeyState::Insert(value)); },
KeyValue::TransactionMeta(key, value) => { db.transaction_meta.insert(key, KeyState::Insert(value)); },
KeyValue::BlockNumber(key, value) => { db.block_number.insert(key, KeyState::Insert(value)); },
},
Operation::Delete(delete) => match delete {
Delete::Meta(key) => { db.meta.insert(key, KeyState::Delete); }
Delete::BlockHash(key) => { db.block_hash.insert(key, KeyState::Delete); }
Delete::BlockHeader(key) => { db.block_header.insert(key, KeyState::Delete); }
Delete::BlockTransactions(key) => { db.block_transactions.insert(key, KeyState::Delete); }
Delete::Transaction(key) => { db.transaction.insert(key, KeyState::Delete); }
Delete::TransactionMeta(key) => { db.transaction_meta.insert(key, KeyState::Delete); }
Delete::BlockNumber(key) => { db.block_number.insert(key, KeyState::Delete); }
Key::Meta(key) => { db.meta.insert(key, KeyState::Delete); }
Key::BlockHash(key) => { db.block_hash.insert(key, KeyState::Delete); }
Key::BlockHeader(key) => { db.block_header.insert(key, KeyState::Delete); }
Key::BlockTransactions(key) => { db.block_transactions.insert(key, KeyState::Delete); }
Key::Transaction(key) => { db.transaction.insert(key, KeyState::Delete); }
Key::TransactionMeta(key) => { db.transaction_meta.insert(key, KeyState::Delete); }
Key::BlockNumber(key) => { db.block_number.insert(key, KeyState::Delete); }
}
}
}
Ok(())
}
fn get<Key, Value>(&self, key: &Key) -> Result<Option<Value>, String> where Key: DatabaseKey<Value> {
unimplemented!();
//use kv::transaction::{COL_META};
fn get(&self, key: &Key) -> Result<KeyState<Value>, String> {
let db = self.db.read();
let result = match *key {
Key::Meta(ref key) => db.meta.get(key).cloned().unwrap_or_default().map(Value::Meta),
Key::BlockHash(ref key) => db.block_hash.get(key).cloned().unwrap_or_default().map(Value::BlockHash),
Key::BlockHeader(ref key) => db.block_header.get(key).cloned().unwrap_or_default().map(Value::BlockHeader),
Key::BlockTransactions(ref key) => db.block_transactions.get(key).cloned().unwrap_or_default().map(Value::BlockTransactions),
Key::Transaction(ref key) => db.transaction.get(key).cloned().unwrap_or_default().map(Value::Transaction),
Key::TransactionMeta(ref key) => db.transaction_meta.get(key).cloned().unwrap_or_default().map(Value::TransactionMeta),
Key::BlockNumber(ref key) => db.block_number.get(key).cloned().unwrap_or_default().map(Value::BlockNumber),
};
//let db = self.db.read();
//let result = match Key::location() {
//Location::Column(COL_META) => db.meta.get(key).and_then(|state| state.clone().into_option()),
//_ => { unimplemented!(); }
//};
//Ok(result)
//fn get(&self, location: Location, key: &Key) -> Result<Option<Value>, String> {
//match self.db.read().get(&location).and_then(|db| db.get(key)) {
//Some(&KeyState::Insert(ref value)) => Ok(Some(value.clone())),
//Some(&KeyState::Delete) | None => Ok(None),
//}
Ok(result)
}
}
@ -150,9 +132,7 @@ impl KeyValueDatabase for SharedMemoryDatabase {
self.db.write(tx)
}
fn get<Key, Value>(&self, key: &Key) -> Result<Option<Value>, String> where Key: DatabaseKey<Value> {
unimplemented!();
//fn get(&self, location: Location, key: &[u8]) -> Result<Option<Value>, String> {
//self.db.get(location, key)
fn get(&self, key: &Key) -> Result<KeyState<Value>, String> {
self.db.get(key)
}
}

View File

@ -1,14 +1,14 @@
mod db;
//mod diskdb;
//mod memorydb;
//mod overlaydb;
mod diskdb;
mod memorydb;
mod overlaydb;
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, AutoFlushingOverlayDatabase};
pub use self::diskdb::{Database as DiskDatabase, DatabaseConfig, CompactionProfile};
pub use self::memorydb::{MemoryDatabase, SharedMemoryDatabase};
pub use self::overlaydb::{OverlayDatabase, AutoFlushingOverlayDatabase};
pub use self::transaction::{
RawTransaction, Transaction, RawOperation, Operation, Location, Key, Value, KeyState, DatabaseKey,
Insert, Delete
RawTransaction, Transaction, RawOperation, Operation, Location, KeyState,
Key, Value, KeyValue, RawKeyValue, RawKey
};

View File

@ -1,5 +1,5 @@
use parking_lot::Mutex;
use kv::{Transaction, Location, Value, KeyValueDatabase, MemoryDatabase, DatabaseKey};
use kv::{Transaction, Value, KeyValueDatabase, MemoryDatabase, KeyState, Key};
pub struct OverlayDatabase<'a, T> where T: 'a + KeyValueDatabase {
db: &'a T,
@ -24,14 +24,11 @@ impl<'a, T> KeyValueDatabase for OverlayDatabase<'a, T> where T: 'a + KeyValueDa
self.overlay.write(tx)
}
fn get<Key, Value>(&self, key: &Key) -> Result<Option<Value>, String> where Key: DatabaseKey<Value> {
unimplemented!();
//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)
//}
fn get(&self, key: &Key) -> Result<KeyState<Value>, String> {
match self.overlay.get(key)? {
KeyState::Unknown => self.db.get(key),
exists => Ok(exists)
}
}
}
@ -69,14 +66,11 @@ impl<T> KeyValueDatabase for AutoFlushingOverlayDatabase<T> where T: KeyValueDat
Ok(())
}
//fn get(&self, location: Location, key: &[u8]) -> Result<Option<Value>, String> {
fn get<Key, Value>(&self, key: &Key) -> Result<Option<Value>, String> where Key: DatabaseKey<Value> {
unimplemented!();
//if self.overlay.is_known(location, key) {
//self.overlay.get(location, key)
//} else {
//self.db.get(location, key)
//}
fn get(&self, key: &Key) -> Result<KeyState<Value>, String> {
match self.overlay.get(key)? {
KeyState::Unknown => self.db.get(key),
exists => Ok(exists)
}
}
}

View File

@ -1,7 +1,6 @@
use elastic_array::{ElasticArray32, ElasticArray128};
use bytes::Bytes;
use hash::H256;
use ser::{Serializable, serialize, List};
use ser::{serialize, List, deserialize};
use chain::{Transaction as ChainTransaction, BlockHeader};
use {TransactionMeta};
@ -13,17 +12,14 @@ pub const COL_TRANSACTIONS: u32 = 4;
pub const COL_TRANSACTIONS_META: u32 = 5;
pub const COL_BLOCK_NUMBERS: u32 = 6;
pub type Key = Bytes;
pub type Value = Bytes;
#[derive(Debug)]
pub enum Operation {
Insert(Insert),
Delete(Delete),
Insert(KeyValue),
Delete(Key),
}
#[derive(Debug)]
pub enum Insert {
pub enum KeyValue {
Meta(&'static str, Bytes),
BlockHash(u32, H256),
BlockHeader(H256, BlockHeader),
@ -34,7 +30,7 @@ pub enum Insert {
}
#[derive(Debug)]
pub enum Delete {
pub enum Key {
Meta(&'static str),
BlockHash(u32),
BlockHeader(H256),
@ -45,63 +41,116 @@ pub enum Delete {
}
#[derive(Debug, Clone)]
pub enum KeyState<Value> {
Insert(Value),
Delete,
pub enum Value {
Meta(Bytes),
BlockHash(H256),
BlockHeader(BlockHeader),
BlockTransactions(List<H256>),
Transaction(ChainTransaction),
TransactionMeta(TransactionMeta),
BlockNumber(u32),
}
impl<Value> KeyState<Value> {
pub fn into_option(self) -> Option<Value> {
impl Value {
pub fn for_key(key: &Key, bytes: &[u8]) -> Result<Self, String> {
match *key {
Key::Meta(_) => deserialize(bytes).map(Value::Meta),
Key::BlockHash(_) => deserialize(bytes).map(Value::BlockHash),
Key::BlockHeader(_) => deserialize(bytes).map(Value::BlockHeader),
Key::BlockTransactions(_) => deserialize(bytes).map(Value::BlockTransactions),
Key::Transaction(_) => deserialize(bytes).map(Value::Transaction),
Key::TransactionMeta(_) => deserialize(bytes).map(Value::TransactionMeta),
Key::BlockNumber(_) => deserialize(bytes).map(Value::BlockNumber),
}.map_err(|e| format!("{:?}", e))
}
pub fn as_meta(self) -> Option<Bytes> {
match self {
KeyState::Insert(value) => Some(value),
KeyState::Delete => None,
Value::Meta(bytes) => Some(bytes),
_ => None,
}
}
pub fn as_block_hash(self) -> Option<H256> {
match self {
Value::BlockHash(block_hash) => Some(block_hash),
_ => None,
}
}
pub fn as_block_header(self) -> Option<BlockHeader> {
match self {
Value::BlockHeader(block_header) => Some(block_header),
_ => None,
}
}
pub fn as_block_transactions(self) -> Option<List<H256>> {
match self {
Value::BlockTransactions(list) => Some(list),
_ => None,
}
}
pub fn as_transaction(self) -> Option<ChainTransaction> {
match self {
Value::Transaction(transaction) => Some(transaction),
_ => None,
}
}
pub fn as_transaction_meta(self) -> Option<TransactionMeta> {
match self {
Value::TransactionMeta(meta) => Some(meta),
_ => None,
}
}
pub fn as_block_number(self) -> Option<u32> {
match self {
Value::BlockNumber(number) => Some(number),
_ => None,
}
}
}
pub trait DatabaseKey<Value> {
fn location() -> Location;
#[derive(Debug, Clone)]
pub enum KeyState<V> {
Insert(V),
Delete,
Unknown,
}
impl DatabaseKey<Bytes> for &'static str {
fn location() -> Location {
COL_META.into()
impl<V> Default for KeyState<V> {
fn default() -> Self {
KeyState::Unknown
}
}
impl DatabaseKey<H256> for u32 {
fn location() -> Location {
COL_BLOCK_HASHES.into()
impl<V> KeyState<V> {
pub fn map<U, F>(self, f: F) -> KeyState<U> where F: FnOnce(V) -> U {
match self {
KeyState::Insert(value) => KeyState::Insert(f(value)),
KeyState::Delete => KeyState::Delete,
KeyState::Unknown => KeyState::Unknown,
}
}
}
impl DatabaseKey<BlockHeader> for H256 {
fn location() -> Location {
COL_BLOCK_HEADERS.into()
pub fn into_option(self) -> Option<V> {
match self {
KeyState::Insert(value) => Some(value),
KeyState::Delete => None,
KeyState::Unknown => None,
}
}
}
impl DatabaseKey<List<H256>> for H256 {
fn location() -> Location {
COL_BLOCK_TRANSACTIONS.into()
}
}
impl DatabaseKey<ChainTransaction> for H256 {
fn location() -> Location {
COL_TRANSACTIONS.into()
}
}
impl DatabaseKey<TransactionMeta> for H256 {
fn location() -> Location {
COL_TRANSACTIONS_META.into()
}
}
impl DatabaseKey<u32> for H256 {
fn location() -> Location {
COL_BLOCK_NUMBERS.into()
pub fn into_operation<K, I, D>(self, key: K, insert: I, delete: D) -> Option<Operation>
where I: FnOnce(K, V) -> KeyValue, D: FnOnce(K) -> Key {
match self {
KeyState::Insert(value) => Some(Operation::Insert(insert(key, value))),
KeyState::Delete => Some(Operation::Delete(delete(key))),
KeyState::Unknown => None,
}
}
}
@ -123,11 +172,11 @@ impl Transaction {
Transaction::default()
}
pub fn insert(&mut self, insert: Insert) {
pub fn insert(&mut self, insert: KeyValue) {
self.operations.push(Operation::Insert(insert));
}
pub fn delete(&mut self, delete: Delete) {
pub fn delete(&mut self, delete: Key) {
self.operations.push(Operation::Delete(delete));
}
}
@ -145,53 +194,65 @@ impl From<u32> for Location {
}
pub enum RawOperation {
Insert {
location: Location,
key: Key,
value: Value,
},
Delete {
location: Location,
key: Key,
Insert(RawKeyValue),
Delete(RawKey),
}
pub struct RawKeyValue {
pub location: Location,
pub key: Bytes,
pub value: Bytes,
}
impl<'a> From<&'a KeyValue> for RawKeyValue {
fn from(i: &'a KeyValue) -> Self {
let (location, key, value) = match *i {
KeyValue::Meta(ref key, ref value) => (COL_META, serialize(key), serialize(value)),
KeyValue::BlockHash(ref key, ref value) => (COL_BLOCK_HASHES, serialize(key), serialize(value)),
KeyValue::BlockHeader(ref key, ref value) => (COL_BLOCK_HEADERS, serialize(key), serialize(value)),
KeyValue::BlockTransactions(ref key, ref value) => (COL_BLOCK_TRANSACTIONS, serialize(key), serialize(value)),
KeyValue::Transaction(ref key, ref value) => (COL_TRANSACTIONS, serialize(key), serialize(value)),
KeyValue::TransactionMeta(ref key, ref value) => (COL_TRANSACTIONS_META, serialize(key), serialize(value)),
KeyValue::BlockNumber(ref key, ref value) => (COL_BLOCK_NUMBERS, serialize(key), serialize(value)),
};
RawKeyValue {
location: location.into(),
key: key,
value: value,
}
}
}
fn raw_insert<Key, Value>(key: &Key, value: &Value) -> RawOperation where Key: DatabaseKey<Value> + Serializable, Value: Serializable {
RawOperation::Insert {
location: Key::location(),
key: serialize(key),
value: serialize(value),
pub struct RawKey {
pub location: Location,
pub key: Bytes,
}
impl<'a> From<&'a Key> for RawKey {
fn from(d: &'a Key) -> Self {
let (location, key) = match *d {
Key::Meta(ref key) => (COL_META, serialize(key)),
Key::BlockHash(ref key) => (COL_BLOCK_HASHES, serialize(key)),
Key::BlockHeader(ref key) => (COL_BLOCK_HEADERS, serialize(key)),
Key::BlockTransactions(ref key) => (COL_BLOCK_TRANSACTIONS, serialize(key)),
Key::Transaction(ref key) => (COL_TRANSACTIONS, serialize(key)),
Key::TransactionMeta(ref key) => (COL_TRANSACTIONS_META, serialize(key)),
Key::BlockNumber(ref key) => (COL_BLOCK_NUMBERS, serialize(key)),
};
RawKey {
location: location.into(),
key: key,
}
}
}
fn raw_delete<Key, Value>(key: &Key) -> RawOperation where Key: DatabaseKey<Value> + Serializable {
RawOperation::Delete {
location: Key::location(),
key: serialize(key),
}
}
impl From<Operation> for RawOperation {
fn from(o: Operation) -> Self {
match o {
Operation::Insert(insert) => match insert {
Insert::Meta(key, value) => raw_insert(&key, &value),
Insert::BlockHash(key, value) => raw_insert(&key, &value),
Insert::BlockHeader(key, value) => raw_insert(&key, &value),
Insert::BlockTransactions(key, value) => raw_insert(&key, &value),
Insert::Transaction(key, value) => raw_insert(&key, &value),
Insert::TransactionMeta(key, value) => raw_insert(&key, &value),
Insert::BlockNumber(key, value) => raw_insert(&key, &value),
},
Operation::Delete(delete) => match delete {
Delete::Meta(key) => raw_delete::<_, Bytes>(&key),
Delete::BlockHash(key) => raw_delete::<_, H256>(&key),
Delete::BlockHeader(key) => raw_delete::<_, BlockHeader>(&key),
Delete::BlockTransactions(key) => raw_delete::<_, List<H256>>(&key),
Delete::Transaction(key) => raw_delete::<_, ChainTransaction>(&key),
Delete::TransactionMeta(key) => raw_delete::<_, TransactionMeta>(&key),
Delete::BlockNumber(key) => raw_delete::<_, u32>(&key),
},
impl<'a> From<&'a Operation> for RawOperation {
fn from(o: &'a Operation) -> Self {
match *o {
Operation::Insert(ref insert) => RawOperation::Insert(insert.into()),
Operation::Delete(ref delete) => RawOperation::Delete(delete.into()),
}
}
}
@ -200,10 +261,10 @@ pub struct RawTransaction {
pub operations: Vec<RawOperation>,
}
impl From<Transaction> for RawTransaction {
fn from(tx: Transaction) -> Self {
impl<'a> From<&'a Transaction> for RawTransaction {
fn from(tx: &'a Transaction) -> Self {
RawTransaction {
operations: tx.operations.into_iter().map(Into::into).collect()
operations: tx.operations.iter().map(Into::into).collect()
}
}
}

View File

@ -1,7 +1,7 @@
use std::io;
use {Serializable, Deserializable, Error, Reader, Stream};
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct List<T>(Vec<T>);
impl<T> List<T> where T: Serializable + Deserializable {