refactored blockchain extras keys building

This commit is contained in:
debris 2016-04-15 18:54:35 +02:00
parent ca4ddfb963
commit 295efdba55
4 changed files with 150 additions and 125 deletions

View File

@ -30,6 +30,7 @@ use blockchain::bloom_indexer::BloomIndexer;
use blockchain::tree_route::TreeRoute; use blockchain::tree_route::TreeRoute;
use blockchain::update::ExtrasUpdate; use blockchain::update::ExtrasUpdate;
use blockchain::{CacheSize, ImportRoute}; use blockchain::{CacheSize, ImportRoute};
use db::{Writable, Readable, Key};
const BLOOM_INDEX_SIZE: usize = 16; const BLOOM_INDEX_SIZE: usize = 16;
const BLOOM_LEVELS: u8 = 3; const BLOOM_LEVELS: u8 = 3;
@ -314,8 +315,8 @@ impl BlockChain {
bc.blocks_db.put(&hash, genesis).unwrap(); bc.blocks_db.put(&hash, genesis).unwrap();
let batch = DBTransaction::new(); let batch = DBTransaction::new();
batch.put_extras(&hash, &details); batch.write(&hash, &details);
batch.put_extras(&header.number(), &hash); batch.write(&header.number(), &hash);
batch.put(b"best", &hash).unwrap(); batch.put(b"best", &hash).unwrap();
bc.extras_db.write(batch).unwrap(); bc.extras_db.write(batch).unwrap();
@ -467,7 +468,7 @@ impl BlockChain {
{ {
let mut write_details = self.block_details.write().unwrap(); let mut write_details = self.block_details.write().unwrap();
for (hash, details) in update.block_details.into_iter() { for (hash, details) in update.block_details.into_iter() {
batch.put_extras(&hash, &details); batch.write(&hash, &details);
self.note_used(CacheID::Extras(ExtrasIndex::BlockDetails, hash.clone())); self.note_used(CacheID::Extras(ExtrasIndex::BlockDetails, hash.clone()));
write_details.insert(hash, details); write_details.insert(hash, details);
} }
@ -476,7 +477,7 @@ impl BlockChain {
{ {
let mut write_receipts = self.block_receipts.write().unwrap(); let mut write_receipts = self.block_receipts.write().unwrap();
for (hash, receipt) in &update.block_receipts { for (hash, receipt) in &update.block_receipts {
batch.put_extras(hash, receipt); batch.write(hash, receipt);
write_receipts.remove(hash); write_receipts.remove(hash);
} }
} }
@ -484,7 +485,7 @@ impl BlockChain {
{ {
let mut write_blocks_blooms = self.blocks_blooms.write().unwrap(); let mut write_blocks_blooms = self.blocks_blooms.write().unwrap();
for (bloom_hash, blocks_bloom) in &update.blocks_blooms { for (bloom_hash, blocks_bloom) in &update.blocks_blooms {
batch.put_extras(bloom_hash, blocks_bloom); batch.write(bloom_hash, blocks_bloom);
write_blocks_blooms.remove(bloom_hash); write_blocks_blooms.remove(bloom_hash);
} }
} }
@ -508,12 +509,12 @@ impl BlockChain {
} }
for (number, hash) in &update.block_hashes { for (number, hash) in &update.block_hashes {
batch.put_extras(number, hash); batch.write(number, hash);
write_hashes.remove(number); write_hashes.remove(number);
} }
for (hash, tx_address) in &update.transactions_addresses { for (hash, tx_address) in &update.transactions_addresses {
batch.put_extras(hash, tx_address); batch.write(hash, tx_address);
write_txs.remove(hash); write_txs.remove(hash);
} }
@ -747,8 +748,9 @@ impl BlockChain {
} }
fn query_extras<K, T>(&self, hash: &K, cache: &RwLock<HashMap<K, T>>) -> Option<T> where fn query_extras<K, T>(&self, hash: &K, cache: &RwLock<HashMap<K, T>>) -> Option<T> where
T: Clone + Decodable + ExtrasIndexable, T: ExtrasIndexable + Clone + Decodable,
K: ExtrasSliceConvertable + Eq + Hash + Clone { K: Key<T> + Eq + Hash + Clone,
H256: From<K> {
{ {
let read = cache.read().unwrap(); let read = cache.read().unwrap();
if let Some(v) = read.get(hash) { if let Some(v) = read.get(hash) {
@ -756,11 +758,9 @@ impl BlockChain {
} }
} }
if let Some(h) = hash.as_h256() { self.note_used(CacheID::Extras(T::index(), H256::from(hash.clone())));
self.note_used(CacheID::Extras(T::extras_index(), h.clone()));
}
self.extras_db.get_extras(hash).map(| t: T | { self.extras_db.read(hash).map(|t: T| {
let mut write = cache.write().unwrap(); let mut write = cache.write().unwrap();
write.insert(hash.clone(), t.clone()); write.insert(hash.clone(), t.clone());
t t
@ -768,8 +768,7 @@ impl BlockChain {
} }
fn query_extras_exist<K, T>(&self, hash: &K, cache: &RwLock<HashMap<K, T>>) -> bool where fn query_extras_exist<K, T>(&self, hash: &K, cache: &RwLock<HashMap<K, T>>) -> bool where
K: ExtrasSliceConvertable + Eq + Hash + Clone, K: Key<T> + Eq + Hash + Clone {
T: ExtrasIndexable {
{ {
let read = cache.read().unwrap(); let read = cache.read().unwrap();
if let Some(_) = read.get(hash) { if let Some(_) = read.get(hash) {
@ -777,7 +776,7 @@ impl BlockChain {
} }
} }
self.extras_db.extras_exists::<_, T>(hash) self.extras_db.exists::<T>(hash)
} }
/// Get current cache size. /// Get current cache size.

61
ethcore/src/db.rs Normal file
View File

@ -0,0 +1,61 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Extras db utils.
use util::{H264, DBTransaction, Database};
use util::rlp::{encode, Encodable, decode, Decodable};
/// Should be used to get database key associated with given value.
pub trait Key<T> {
/// Returns db key.
fn key(&self) -> H264;
}
/// Should be used to write value into database.
pub trait Writable {
/// Writes key into database.
fn write<T>(&self, key: &Key<T>, value: &T) where T: Encodable;
}
/// Should be used to read values from database.
pub trait Readable {
/// Returns value for given key.
fn read<T>(&self, key: &Key<T>) -> Option<T> where T: Decodable;
/// Returns true if given value exists.
fn exists<T>(&self, key: &Key<T>) -> bool;
}
impl Writable for DBTransaction {
fn write<T>(&self, key: &Key<T>, value: &T) where T: Encodable {
self.put(&key.key(), &encode(value))
.expect("db put failed");
}
}
impl Readable for Database {
fn read<T>(&self, key: &Key<T>) -> Option<T> where T: Decodable {
self.get(&key.key())
.expect("db get failed")
.map(|v| decode(&v))
}
fn exists<T>(&self, key: &Key<T>) -> bool {
self.get(&key.key())
.expect("db get failed")
.is_some()
}
}

View File

@ -19,6 +19,7 @@
use util::*; use util::*;
use header::BlockNumber; use header::BlockNumber;
use receipt::Receipt; use receipt::Receipt;
use db::Key;
/// Represents index of extra data in database /// Represents index of extra data in database
#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)] #[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
@ -37,95 +38,88 @@ pub enum ExtrasIndex {
BlockReceipts = 5, BlockReceipts = 5,
} }
/// trait used to write Extras data to db fn with_index(hash: &H256, i: ExtrasIndex) -> H264 {
pub trait ExtrasWritable { let mut slice = H264::from_slice(hash);
/// Write extra data to db slice[32] = i as u8;
fn put_extras<K, T>(&self, hash: &K, value: &T) where slice
T: ExtrasIndexable + Encodable,
K: ExtrasSliceConvertable;
} }
/// trait used to read Extras data from db
pub trait ExtrasReadable {
/// Read extra data from db
fn get_extras<K, T>(&self, hash: &K) -> Option<T> where
T: ExtrasIndexable + Decodable,
K: ExtrasSliceConvertable;
/// Check if extra data exists in the db
fn extras_exists<K, T>(&self, hash: &K) -> bool where
T: ExtrasIndexable,
K: ExtrasSliceConvertable;
}
impl ExtrasWritable for DBTransaction {
fn put_extras<K, T>(&self, hash: &K, value: &T) where
T: ExtrasIndexable + Encodable,
K: ExtrasSliceConvertable {
self.put(&hash.to_extras_slice(T::extras_index()), &encode(value)).unwrap()
}
}
impl ExtrasReadable for Database {
fn get_extras<K, T>(&self, hash: &K) -> Option<T> where
T: ExtrasIndexable + Decodable,
K: ExtrasSliceConvertable {
self.get(&hash.to_extras_slice(T::extras_index())).unwrap()
.map(|v| decode(&v))
}
fn extras_exists<K, T>(&self, hash: &K) -> bool where
T: ExtrasIndexable,
K: ExtrasSliceConvertable {
self.get(&hash.to_extras_slice(T::extras_index())).unwrap().is_some()
}
}
/// Implementations should convert arbitrary type to database key slice
pub trait ExtrasSliceConvertable {
/// Convert self, with `i` (the index), to a 264-bit extras DB key.
fn to_extras_slice(&self, i: ExtrasIndex) -> H264;
/// Interpret self as a 256-bit hash, if natively `H256`.
fn as_h256(&self) -> Option<&H256> { None }
}
impl ExtrasSliceConvertable for H256 {
fn to_extras_slice(&self, i: ExtrasIndex) -> H264 {
let mut slice = H264::from_slice(self);
slice[32] = i as u8;
slice
}
fn as_h256(&self) -> Option<&H256> { Some(self) }
}
impl ExtrasSliceConvertable for U256 {
fn to_extras_slice(&self, i: ExtrasIndex) -> H264 {
H256::from(self).to_extras_slice(i)
}
}
// NICE: make less horrible.
impl ExtrasSliceConvertable for BlockNumber {
fn to_extras_slice(&self, i: ExtrasIndex) -> H264 {
U256::from(*self).to_extras_slice(i)
}
}
/// Types implementing this trait can be indexed in extras database
pub trait ExtrasIndexable { pub trait ExtrasIndexable {
/// Returns this data index fn index() -> ExtrasIndex;
fn extras_index() -> ExtrasIndex;
} }
impl ExtrasIndexable for H256 { impl ExtrasIndexable for H256 {
fn extras_index() -> ExtrasIndex { fn index() -> ExtrasIndex {
ExtrasIndex::BlockHash ExtrasIndex::BlockHash
} }
} }
impl ExtrasIndexable for BlockDetails {
fn index() -> ExtrasIndex {
ExtrasIndex::BlockDetails
}
}
impl ExtrasIndexable for TransactionAddress {
fn index() -> ExtrasIndex {
ExtrasIndex::TransactionAddress
}
}
impl ExtrasIndexable for BlockLogBlooms {
fn index() -> ExtrasIndex {
ExtrasIndex::BlockLogBlooms
}
}
impl ExtrasIndexable for BlocksBlooms {
fn index() -> ExtrasIndex {
ExtrasIndex::BlocksBlooms
}
}
impl ExtrasIndexable for BlockReceipts {
fn index() -> ExtrasIndex {
ExtrasIndex::BlockReceipts
}
}
impl Key<H256> for BlockNumber {
fn key(&self) -> H264 {
with_index(&H256::from(*self), ExtrasIndex::BlockHash)
}
}
impl Key<BlockDetails> for H256 {
fn key(&self) -> H264 {
with_index(self, ExtrasIndex::BlockDetails)
}
}
impl Key<TransactionAddress> for H256 {
fn key(&self) -> H264 {
with_index(self, ExtrasIndex::TransactionAddress)
}
}
impl Key<BlockLogBlooms> for H256 {
fn key(&self) -> H264 {
with_index(self, ExtrasIndex::BlockLogBlooms)
}
}
impl Key<BlocksBlooms> for H256 {
fn key(&self) -> H264 {
with_index(self, ExtrasIndex::BlocksBlooms)
}
}
impl Key<BlockReceipts> for H256 {
fn key(&self) -> H264 {
with_index(self, ExtrasIndex::BlockReceipts)
}
}
/// Familial details concerning a block /// Familial details concerning a block
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct BlockDetails { pub struct BlockDetails {
@ -139,12 +133,6 @@ pub struct BlockDetails {
pub children: Vec<H256> pub children: Vec<H256>
} }
impl ExtrasIndexable for BlockDetails {
fn extras_index() -> ExtrasIndex {
ExtrasIndex::BlockDetails
}
}
impl HeapSizeOf for BlockDetails { impl HeapSizeOf for BlockDetails {
fn heap_size_of_children(&self) -> usize { fn heap_size_of_children(&self) -> usize {
self.children.heap_size_of_children() self.children.heap_size_of_children()
@ -181,12 +169,6 @@ pub struct BlockLogBlooms {
pub blooms: Vec<H2048> pub blooms: Vec<H2048>
} }
impl ExtrasIndexable for BlockLogBlooms {
fn extras_index() -> ExtrasIndex {
ExtrasIndex::BlockLogBlooms
}
}
impl HeapSizeOf for BlockLogBlooms { impl HeapSizeOf for BlockLogBlooms {
fn heap_size_of_children(&self) -> usize { fn heap_size_of_children(&self) -> usize {
self.blooms.heap_size_of_children() self.blooms.heap_size_of_children()
@ -227,12 +209,6 @@ impl BlocksBlooms {
} }
} }
impl ExtrasIndexable for BlocksBlooms {
fn extras_index() -> ExtrasIndex {
ExtrasIndex::BlocksBlooms
}
}
impl HeapSizeOf for BlocksBlooms { impl HeapSizeOf for BlocksBlooms {
fn heap_size_of_children(&self) -> usize { 0 } fn heap_size_of_children(&self) -> usize { 0 }
} }
@ -277,12 +253,6 @@ pub struct TransactionAddress {
pub index: usize pub index: usize
} }
impl ExtrasIndexable for TransactionAddress {
fn extras_index() -> ExtrasIndex {
ExtrasIndex::TransactionAddress
}
}
impl HeapSizeOf for TransactionAddress { impl HeapSizeOf for TransactionAddress {
fn heap_size_of_children(&self) -> usize { 0 } fn heap_size_of_children(&self) -> usize { 0 }
} }
@ -340,9 +310,3 @@ impl HeapSizeOf for BlockReceipts {
self.receipts.heap_size_of_children() self.receipts.heap_size_of_children()
} }
} }
impl ExtrasIndexable for BlockReceipts {
fn extras_index() -> ExtrasIndex {
ExtrasIndex::BlockReceipts
}
}

View File

@ -104,6 +104,7 @@ pub mod views;
pub mod receipt; pub mod receipt;
pub mod pod_state; pub mod pod_state;
mod db;
mod common; mod common;
mod basic_types; mod basic_types;
#[macro_use] mod evm; #[macro_use] mod evm;