Skip to content

Commit 371ff69

Browse files
author
Joon-Mo Yang
committed
Add action data cache in top level state
1 parent 068132a commit 371ff69

File tree

7 files changed

+120
-4
lines changed

7 files changed

+120
-4
lines changed

state/src/action_handler/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2018 Kodebox, Inc.
2+
// This file is part of CodeChain.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as
6+
// published by the Free Software Foundation, either version 3 of the
7+
// License, or (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
use ctypes::parcel::Outcome;
18+
use primitives::Bytes;
19+
use trie::TrieMut;
20+
21+
use super::{StateResult, TopLevelState};
22+
23+
pub trait ActionHandler: Send + Sync {
24+
fn init(&self, state: &mut TrieMut) -> StateResult<()>;
25+
fn is_target(&self, bytes: &Bytes) -> bool;
26+
fn execute(&self, bytes: &Bytes, state: &mut TopLevelState) -> StateResult<Outcome>;
27+
}

state/src/backend.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
4040
use ckey::Address;
4141
use hashdb::HashDB;
42+
use primitives::{Bytes, H256};
4243

4344
use super::{
4445
Account, Asset, AssetAddress, AssetScheme, AssetSchemeAddress, Metadata, MetadataAddress, Shard, ShardAddress,
@@ -59,12 +60,14 @@ pub trait TopBackend: Send {
5960
fn add_to_account_cache(&mut self, addr: Address, data: Option<Account>, modified: bool);
6061
fn add_to_metadata_cache(&mut self, address: MetadataAddress, item: Option<Metadata>, modified: bool);
6162
fn add_to_shard_cache(&mut self, address: ShardAddress, item: Option<Shard>, modified: bool);
63+
fn add_to_action_data_cache(&mut self, address: H256, item: Option<Bytes>, modified: bool);
6264

6365
/// Get basic copy of the cached account. Not required to include storage.
6466
/// Returns 'None' if cache is disabled or if the account is not cached.
6567
fn get_cached_account(&self, addr: &Address) -> Option<Option<Account>>;
6668
fn get_cached_metadata(&self, addr: &MetadataAddress) -> Option<Option<Metadata>>;
6769
fn get_cached_shard(&self, addr: &ShardAddress) -> Option<Option<Shard>>;
70+
fn get_cached_action_data(&self, key: &H256) -> Option<Option<Bytes>>;
6871

6972
/// Get value from a cached account.
7073
/// `None` is passed to the closure if the account entry cached

state/src/db.rs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use kvdb::DBTransaction;
2727
use kvdb_memorydb;
2828
use lru_cache::LruCache;
2929
use parking_lot::Mutex;
30-
use primitives::H256;
30+
use primitives::{Bytes, H256};
3131
use util_error::UtilError;
3232

3333
use super::{
@@ -40,9 +40,10 @@ const STATE_CACHE_BLOCKS: usize = 12;
4040
// The percentage of supplied cache size to go to accounts.
4141
const ACCOUNT_CACHE_RATIO: usize = 40;
4242
const METADATA_CACHE_RATIO: usize = 1;
43-
const SHARD_CACHE_RATIO: usize = 9;
43+
const SHARD_CACHE_RATIO: usize = 8;
4444
const ASSET_SCHEME_CACHE_RATIO: usize = 10;
4545
const ASSET_CACHE_RATIO: usize = 40;
46+
const ACTION_DATA_CACHE_RATIO: usize = 1;
4647

4748
/// Shared canonical state cache.
4849
struct Cache<Item>
@@ -108,13 +109,15 @@ pub struct StateDB {
108109
shard_cache: Arc<Mutex<Cache<Shard>>>,
109110
asset_scheme_cache: Arc<Mutex<Cache<AssetScheme>>>,
110111
asset_cache: Arc<Mutex<Cache<Asset>>>,
112+
action_data_cache: Arc<Mutex<Cache<Bytes>>>,
111113

112114
/// Local dirty cache.
113115
local_account_cache: Vec<CacheQueueItem<Account>>,
114116
local_metadata_cache: Vec<CacheQueueItem<Metadata>>,
115117
local_shard_cache: Vec<CacheQueueItem<Shard>>,
116118
local_asset_scheme_cache: Vec<CacheQueueItem<AssetScheme>>,
117119
local_asset_cache: Vec<CacheQueueItem<Asset>>,
120+
local_action_data_cache: Vec<CacheQueueItem<Bytes>>,
118121
/// Hash of the block on top of which this instance was created or
119122
/// `None` if cache is disabled
120123
parent_hash: Option<H256>,
@@ -137,6 +140,7 @@ impl StateDB {
137140
+ SHARD_CACHE_RATIO
138141
+ ASSET_SCHEME_CACHE_RATIO
139142
+ ASSET_CACHE_RATIO
143+
+ ACTION_DATA_CACHE_RATIO
140144
);
141145

142146
let account_cache_size = cache_size * ACCOUNT_CACHE_RATIO / 100;
@@ -154,6 +158,9 @@ impl StateDB {
154158
let asset_cache_size = cache_size * ASSET_CACHE_RATIO / 100;
155159
let asset_cache_items = asset_cache_size / ::std::mem::size_of::<Option<Asset>>();
156160

161+
let action_data_cache_size = cache_size * ACTION_DATA_CACHE_RATIO / 100;
162+
let action_data_cache_items = action_data_cache_size / ::std::mem::size_of::<Option<Bytes>>();
163+
157164
StateDB {
158165
db,
159166
account_cache: Arc::new(Mutex::new(Cache {
@@ -176,12 +183,17 @@ impl StateDB {
176183
cache: LruCache::new(asset_cache_items),
177184
modifications: VecDeque::new(),
178185
})),
186+
action_data_cache: Arc::new(Mutex::new(Cache {
187+
cache: LruCache::new(action_data_cache_items),
188+
modifications: VecDeque::new(),
189+
})),
179190

180191
local_account_cache: Vec::new(),
181192
local_metadata_cache: Vec::new(),
182193
local_shard_cache: Vec::new(),
183194
local_asset_scheme_cache: Vec::new(),
184195
local_asset_cache: Vec::new(),
196+
local_action_data_cache: Vec::new(),
185197
parent_hash: None,
186198
commit_hash: None,
187199
commit_number: None,
@@ -271,6 +283,17 @@ impl StateDB {
271283
&self.commit_hash,
272284
&self.commit_number,
273285
);
286+
287+
Self::sync_cache_impl(
288+
enacted,
289+
retracted,
290+
is_best,
291+
&mut self.action_data_cache,
292+
&mut self.local_action_data_cache,
293+
&self.parent_hash,
294+
&self.commit_hash,
295+
&self.commit_number,
296+
);
274297
}
275298

276299
fn sync_cache_impl<Item>(
@@ -392,12 +415,14 @@ impl StateDB {
392415
shard_cache: self.shard_cache.clone(),
393416
asset_scheme_cache: self.asset_scheme_cache.clone(),
394417
asset_cache: self.asset_cache.clone(),
418+
action_data_cache: self.action_data_cache.clone(),
395419

396420
local_account_cache: Vec::new(),
397421
local_metadata_cache: Vec::new(),
398422
local_shard_cache: Vec::new(),
399423
local_asset_scheme_cache: Vec::new(),
400424
local_asset_cache: Vec::new(),
425+
local_action_data_cache: Vec::new(),
401426

402427
parent_hash: Some(parent.clone()),
403428
commit_hash: None,
@@ -425,6 +450,7 @@ impl StateDB {
425450
+ Self::mem_used_impl(&self.shard_cache.lock())
426451
+ Self::mem_used_impl(&self.asset_scheme_cache.lock())
427452
+ Self::mem_used_impl(&self.asset_cache.lock())
453+
+ Self::mem_used_impl(&self.action_data_cache.lock())
428454
}
429455

430456
/// Returns underlying `JournalDB`.
@@ -503,12 +529,14 @@ impl Clone for StateDB {
503529
shard_cache: self.shard_cache.clone(),
504530
asset_scheme_cache: self.asset_scheme_cache.clone(),
505531
asset_cache: self.asset_cache.clone(),
532+
action_data_cache: self.action_data_cache.clone(),
506533

507534
local_account_cache: Vec::new(),
508535
local_metadata_cache: Vec::new(),
509536
local_shard_cache: Vec::new(),
510537
local_asset_scheme_cache: Vec::new(),
511538
local_asset_cache: Vec::new(),
539+
local_action_data_cache: Vec::new(),
512540

513541
parent_hash: None,
514542
commit_hash: None,
@@ -552,6 +580,14 @@ impl TopBackend for StateDB {
552580
})
553581
}
554582

583+
fn add_to_action_data_cache(&mut self, address: H256, item: Option<Bytes>, modified: bool) {
584+
self.local_action_data_cache.push(CacheQueueItem {
585+
address,
586+
item,
587+
modified,
588+
})
589+
}
590+
555591
fn get_cached_account(&self, addr: &Address) -> Option<Option<Account>> {
556592
self.get_cached(addr, &self.account_cache)
557593
}
@@ -564,6 +600,10 @@ impl TopBackend for StateDB {
564600
self.get_cached(addr, &self.shard_cache)
565601
}
566602

603+
fn get_cached_action_data(&self, key: &H256) -> Option<Option<Bytes>> {
604+
self.get_cached(key, &self.action_data_cache)
605+
}
606+
567607
fn get_cached_account_with<F, U>(&self, a: &Address, f: F) -> Option<U>
568608
where
569609
F: FnOnce(Option<&mut Account>) -> U, {

state/src/impls/top_level.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ use ctypes::invoice::Invoice;
4444
use ctypes::parcel::{Action, ChangeShard, Error as ParcelError, Outcome as ParcelOutcome, Parcel};
4545
use ctypes::transaction::{Error as TransactionError, Outcome as TransactionOutcome, Transaction};
4646
use ctypes::ShardId;
47-
use primitives::{H256, U256};
47+
use primitives::{Bytes, H256, U256};
48+
use rlp::NULL_RLP;
4849
use trie::{Result as TrieResult, Trie, TrieError, TrieFactory};
4950
use unexpected::Mismatch;
5051

@@ -108,6 +109,7 @@ pub struct TopLevelState {
108109
account: Cache<Account>,
109110
metadata: Cache<Metadata>,
110111
shard: Cache<Shard>,
112+
action_data: Cache<Bytes>,
111113
id_of_checkpoints: Vec<CheckpointId>,
112114
trie_factory: TrieFactory,
113115
}
@@ -161,6 +163,11 @@ impl TopStateInfo for TopLevelState {
161163
ShardLevelState::from_existing(shard_id, self.db.clone(), shard_root, self.trie_factory)?;
162164
shard_level_state.asset(asset_address)
163165
}
166+
167+
fn action_data(&self, key: &H256) -> TrieResult<Bytes> {
168+
let action_data = self.require_action_data(key)?;
169+
Ok(action_data.clone())
170+
}
164171
}
165172

166173
const PARCEL_FEE_CHECKPOINT: CheckpointId = 123;
@@ -172,6 +179,7 @@ impl StateWithCheckpoint for TopLevelState {
172179
self.account.checkpoint();
173180
self.metadata.checkpoint();
174181
self.shard.checkpoint();
182+
self.action_data.checkpoint();
175183
}
176184

177185
fn discard_checkpoint(&mut self, id: CheckpointId) {
@@ -181,6 +189,7 @@ impl StateWithCheckpoint for TopLevelState {
181189
self.account.discard_checkpoint();
182190
self.metadata.discard_checkpoint();
183191
self.shard.discard_checkpoint();
192+
self.action_data.discard_checkpoint();
184193
}
185194

186195
fn revert_to_checkpoint(&mut self, id: CheckpointId) {
@@ -190,6 +199,7 @@ impl StateWithCheckpoint for TopLevelState {
190199
self.account.revert_to_checkpoint();
191200
self.metadata.revert_to_checkpoint();
192201
self.shard.revert_to_checkpoint();
202+
self.action_data.revert_to_checkpoint();
193203
}
194204
}
195205

@@ -199,6 +209,7 @@ impl StateWithCache for TopLevelState {
199209
self.account.commit(&mut trie)?;
200210
self.metadata.commit(&mut trie)?;
201211
self.shard.commit(&mut trie)?;
212+
self.action_data.commit(&mut trie)?;
202213
Ok(())
203214
}
204215

@@ -213,12 +224,16 @@ impl StateWithCache for TopLevelState {
213224
self.shard.propagate_to_global_cache(|address, item, modified| {
214225
db.add_to_shard_cache(address, item, modified);
215226
});
227+
self.action_data.propagate_to_global_cache(|address, item, modified| {
228+
db.add_to_action_data_cache(address, item, modified);
229+
});
216230
}
217231

218232
fn clear(&mut self) {
219233
self.account.clear();
220234
self.metadata.clear();
221235
self.shard.clear();
236+
self.action_data.clear();
222237
}
223238
}
224239

@@ -238,6 +253,7 @@ impl TopLevelState {
238253
account: Cache::new(),
239254
metadata: Cache::new(),
240255
shard: Cache::new(),
256+
action_data: Cache::new(),
241257
id_of_checkpoints: Default::default(),
242258
trie_factory,
243259
}
@@ -255,6 +271,7 @@ impl TopLevelState {
255271
account: Cache::new(),
256272
metadata: Cache::new(),
257273
shard: Cache::new(),
274+
action_data: Cache::new(),
258275
id_of_checkpoints: Default::default(),
259276
trie_factory,
260277
};
@@ -511,13 +528,21 @@ impl TopLevelState {
511528
let from_db = || self.db.get_cached_shard(&shard_address);
512529
self.shard.require_item_or_from(&shard_address, default, db, from_db)
513530
}
531+
532+
fn require_action_data<'a>(&'a self, key: &H256) -> TrieResult<RefMut<'a, Bytes>> {
533+
let default = || NULL_RLP.to_vec();
534+
let db = self.trie_factory.readonly(self.db.as_hashdb(), &self.root)?;
535+
let from_db = || self.db.get_cached_action_data(key);
536+
self.action_data.require_item_or_from(key, default, db, from_db)
537+
}
514538
}
515539

516540
impl fmt::Debug for TopLevelState {
517541
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
518542
writeln!(f, "account: {:?}", self.account)?;
519543
writeln!(f, "metadata: {:?}", self.metadata)?;
520544
writeln!(f, "shard: {:?}", self.shard)?;
545+
writeln!(f, "action_data: {:?}", self.action_data)?;
521546
Ok(())
522547
}
523548
}
@@ -533,6 +558,7 @@ impl Clone for TopLevelState {
533558
account: self.account.clone(),
534559
metadata: self.metadata.clone(),
535560
shard: self.shard.clone(),
561+
action_data: self.action_data.clone(),
536562
trie_factory: self.trie_factory.clone(),
537563
}
538564
}
@@ -620,6 +646,12 @@ impl TopState<StateDB> for TopLevelState {
620646
shard.set_root(*new_root);
621647
Ok(())
622648
}
649+
650+
fn update_action_data(&mut self, key: &H256, data: Bytes) -> StateResult<()> {
651+
let mut action_data = self.require_action_data(key)?;
652+
*action_data = data;
653+
Ok(())
654+
}
623655
}
624656

625657
#[cfg(test)]

state/src/item/cache.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use std::fmt;
2222
use std::hash::Hash;
2323
use std::vec::Vec;
2424

25+
use primitives::{Bytes, H256};
2526
use rlp::{Decodable, Encodable};
2627
use trie::{self, Result as TrieResult, Trie, TrieKinds, TrieMut};
2728

@@ -30,6 +31,13 @@ pub trait CacheableItem: Clone + fmt::Debug + Decodable + Encodable {
3031
fn is_null(&self) -> bool;
3132
}
3233

34+
impl CacheableItem for Bytes {
35+
type Address = H256;
36+
fn is_null(&self) -> bool {
37+
self.is_empty()
38+
}
39+
}
40+
3341
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
3442
/// Account modification state. Used to check if the account was
3543
/// Modified in between commits and overall.

state/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ extern crate serde_derive;
3939
extern crate unexpected;
4040
extern crate util_error;
4141

42+
mod action_handler;
4243
mod backend;
4344
mod checkpoint;
4445
mod db;

0 commit comments

Comments
 (0)