Merge pull request #963 from ethcore/dbkeys

refactored blockchain extras keys building
This commit is contained in:
Nikolay Volf 2016-04-17 20:48:06 +03:00
commit 3c1c3ac156
4 changed files with 162 additions and 125 deletions

View File

@ -30,6 +30,7 @@ use blockchain::bloom_indexer::BloomIndexer;
use blockchain::tree_route::TreeRoute;
use blockchain::update::ExtrasUpdate;
use blockchain::{CacheSize, ImportRoute};
use db::{Writable, Readable, Key};
const BLOOM_INDEX_SIZE: usize = 16;
const BLOOM_LEVELS: u8 = 3;
@ -314,8 +315,8 @@ impl BlockChain {
bc.blocks_db.put(&hash, genesis).unwrap();
let batch = DBTransaction::new();
batch.put_extras(&hash, &details);
batch.put_extras(&header.number(), &hash);
batch.write(&hash, &details);
batch.write(&header.number(), &hash);
batch.put(b"best", &hash).unwrap();
bc.extras_db.write(batch).unwrap();
@ -467,7 +468,7 @@ impl BlockChain {
{
let mut write_details = self.block_details.write().unwrap();
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()));
write_details.insert(hash, details);
}
@ -476,7 +477,7 @@ impl BlockChain {
{
let mut write_receipts = self.block_receipts.write().unwrap();
for (hash, receipt) in &update.block_receipts {
batch.put_extras(hash, receipt);
batch.write(hash, receipt);
write_receipts.remove(hash);
}
}
@ -484,7 +485,7 @@ impl BlockChain {
{
let mut write_blocks_blooms = self.blocks_blooms.write().unwrap();
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);
}
}
@ -508,12 +509,12 @@ impl BlockChain {
}
for (number, hash) in &update.block_hashes {
batch.put_extras(number, hash);
batch.write(number, hash);
write_hashes.remove(number);
}
for (hash, tx_address) in &update.transactions_addresses {
batch.put_extras(hash, tx_address);
batch.write(hash, tx_address);
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
T: Clone + Decodable + ExtrasIndexable,
K: ExtrasSliceConvertable + Eq + Hash + Clone {
T: ExtrasIndexable + Clone + Decodable,
K: Key<T> + Eq + Hash + Clone,
H256: From<K> {
{
let read = cache.read().unwrap();
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::extras_index(), h.clone()));
}
self.note_used(CacheID::Extras(T::index(), H256::from(hash.clone())));
self.extras_db.get_extras(hash).map(| t: T | {
self.extras_db.read(hash).map(|t: T| {
let mut write = cache.write().unwrap();
write.insert(hash.clone(), t.clone());
t
@ -768,8 +768,7 @@ impl BlockChain {
}
fn query_extras_exist<K, T>(&self, hash: &K, cache: &RwLock<HashMap<K, T>>) -> bool where
K: ExtrasSliceConvertable + Eq + Hash + Clone,
T: ExtrasIndexable {
K: Key<T> + Eq + Hash + Clone {
{
let read = cache.read().unwrap();
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.

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

@ -0,0 +1,73 @@
// 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 {
let result = self.put(&key.key(), &encode(value));
if let Err(err) = result {
panic!("db put failed, key: {:?}, err: {:?}", key.key(), err);
}
}
}
impl Readable for Database {
fn read<T>(&self, key: &Key<T>) -> Option<T> where T: Decodable {
let result = self.get(&key.key());
match result {
Ok(option) => option.map(|v| decode(&v)),
Err(err) => {
panic!("db get failed, key: {:?}, err: {:?}", key.key(), err);
}
}
}
fn exists<T>(&self, key: &Key<T>) -> bool {
let result = self.get(&key.key());
match result {
Ok(v) => v.is_some(),
Err(err) => {
panic!("db get failed, key: {:?}, err: {:?}", key.key(), err);
}
}
}
}

View File

@ -19,6 +19,7 @@
use util::*;
use header::BlockNumber;
use receipt::Receipt;
use db::Key;
/// Represents index of extra data in database
#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
@ -37,95 +38,88 @@ pub enum ExtrasIndex {
BlockReceipts = 5,
}
/// trait used to write Extras data to db
pub trait ExtrasWritable {
/// Write extra data to db
fn put_extras<K, T>(&self, hash: &K, value: &T) where
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);
fn with_index(hash: &H256, i: ExtrasIndex) -> H264 {
let mut slice = H264::from_slice(hash);
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 {
/// Returns this data index
fn extras_index() -> ExtrasIndex;
fn index() -> ExtrasIndex;
}
impl ExtrasIndexable for H256 {
fn extras_index() -> ExtrasIndex {
fn index() -> ExtrasIndex {
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
#[derive(Debug, Clone)]
pub struct BlockDetails {
@ -139,12 +133,6 @@ pub struct BlockDetails {
pub children: Vec<H256>
}
impl ExtrasIndexable for BlockDetails {
fn extras_index() -> ExtrasIndex {
ExtrasIndex::BlockDetails
}
}
impl HeapSizeOf for BlockDetails {
fn heap_size_of_children(&self) -> usize {
self.children.heap_size_of_children()
@ -181,12 +169,6 @@ pub struct BlockLogBlooms {
pub blooms: Vec<H2048>
}
impl ExtrasIndexable for BlockLogBlooms {
fn extras_index() -> ExtrasIndex {
ExtrasIndex::BlockLogBlooms
}
}
impl HeapSizeOf for BlockLogBlooms {
fn heap_size_of_children(&self) -> usize {
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 {
fn heap_size_of_children(&self) -> usize { 0 }
}
@ -277,12 +253,6 @@ pub struct TransactionAddress {
pub index: usize
}
impl ExtrasIndexable for TransactionAddress {
fn extras_index() -> ExtrasIndex {
ExtrasIndex::TransactionAddress
}
}
impl HeapSizeOf for TransactionAddress {
fn heap_size_of_children(&self) -> usize { 0 }
}
@ -340,9 +310,3 @@ impl HeapSizeOf for BlockReceipts {
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 pod_state;
mod db;
mod common;
mod basic_types;
#[macro_use] mod evm;