--pruning=auto option.
This commit is contained in:
parent
6e97496b27
commit
fa95419c27
@ -17,6 +17,7 @@
|
|||||||
//! Blockchain database client.
|
//! Blockchain database client.
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::path::PathBuf;
|
||||||
use util::*;
|
use util::*;
|
||||||
use util::panics::*;
|
use util::panics::*;
|
||||||
use views::BlockView;
|
use views::BlockView;
|
||||||
@ -126,22 +127,29 @@ impl Client<CanonVerifier> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_db_path(path: &Path, pruning: journaldb::Algorithm, genesis_hash: H256) -> PathBuf {
|
||||||
|
let mut dir = path.to_path_buf();
|
||||||
|
dir.push(H64::from(genesis_hash).hex());
|
||||||
|
//TODO: sec/fat: pruned/full versioning
|
||||||
|
// version here is a bit useless now, since it's controlled only be the pruning algo.
|
||||||
|
dir.push(format!("v{}-sec-{}", CLIENT_DB_VER_STR, pruning));
|
||||||
|
dir
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_path(path: &Path, item: &str) -> String {
|
||||||
|
let mut p = path.to_path_buf();
|
||||||
|
p.push(item);
|
||||||
|
p.to_str().unwrap().to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
impl<V> Client<V> where V: Verifier {
|
impl<V> Client<V> where V: Verifier {
|
||||||
/// Create a new client with given spec and DB path and custom verifier.
|
/// Create a new client with given spec and DB path and custom verifier.
|
||||||
pub fn new_with_verifier(config: ClientConfig, spec: Spec, path: &Path, message_channel: IoChannel<NetSyncMessage> ) -> Result<Arc<Client<V>>, Error> {
|
pub fn new_with_verifier(config: ClientConfig, spec: Spec, path: &Path, message_channel: IoChannel<NetSyncMessage> ) -> Result<Arc<Client<V>>, Error> {
|
||||||
let mut dir = path.to_path_buf();
|
let path = get_db_path(path, config.pruning, spec.genesis_header().hash());
|
||||||
dir.push(H64::from(spec.genesis_header().hash()).hex());
|
|
||||||
//TODO: sec/fat: pruned/full versioning
|
|
||||||
// version here is a bit useless now, since it's controlled only be the pruning algo.
|
|
||||||
dir.push(format!("v{}-sec-{}", CLIENT_DB_VER_STR, config.pruning));
|
|
||||||
let path = dir.as_path();
|
|
||||||
let gb = spec.genesis_block();
|
let gb = spec.genesis_block();
|
||||||
let chain = Arc::new(BlockChain::new(config.blockchain, &gb, path));
|
let chain = Arc::new(BlockChain::new(config.blockchain, &gb, &path));
|
||||||
let mut state_path = path.to_path_buf();
|
|
||||||
state_path.push("state");
|
|
||||||
|
|
||||||
let state_path_str = state_path.to_str().unwrap();
|
let mut state_db = journaldb::new(&append_path(&path, "state"), config.pruning);
|
||||||
let mut state_db = journaldb::new(state_path_str, config.pruning);
|
|
||||||
|
|
||||||
if state_db.is_empty() && spec.ensure_db_good(state_db.as_hashdb_mut()) {
|
if state_db.is_empty() && spec.ensure_db_good(state_db.as_hashdb_mut()) {
|
||||||
state_db.commit(0, &spec.genesis_header().hash(), None).expect("Error commiting genesis state to state DB");
|
state_db.commit(0, &spec.genesis_header().hash(), None).expect("Error commiting genesis state to state DB");
|
||||||
|
@ -542,24 +542,25 @@ impl Configuration {
|
|||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_best_db(path: &str) -> Option<journaldb::Algorithm> {
|
fn find_best_db(&self, spec: &Spec) -> Option<journaldb::Algorithm> {
|
||||||
let mut ret = None;
|
let mut ret = None;
|
||||||
let mut latest_era = None;
|
let mut latest_era = None;
|
||||||
for i in [journaldb::Algorithm::Archive, journaldb::Algorithm::EarlyMerge, journaldb::Algorithm::OverlayRecent, journaldb::Algorithm::RefCounted].into_iter() {
|
let jdb_types = [journaldb::Algorithm::Archive, journaldb::Algorithm::EarlyMerge, journaldb::Algorithm::OverlayRecent, journaldb::Algorithm::RefCounted];
|
||||||
let db = journaldb::new(path, i);
|
for i in jdb_types.into_iter() {
|
||||||
|
let db = journaldb::new(&append_path(&get_db_path(&Path::new(&self.path()), *i, spec.genesis_header().hash()), "state"), *i);
|
||||||
match (latest_era, db.latest_era()) {
|
match (latest_era, db.latest_era()) {
|
||||||
(Some(best), Some(this)) if best >= this => {}
|
(Some(best), Some(this)) if best >= this => {}
|
||||||
(_, None) => {}
|
(_, None) => {}
|
||||||
(_, Some(this)) => {
|
(_, Some(this)) => {
|
||||||
latest_era = Some(this);
|
latest_era = Some(this);
|
||||||
ret = Some(i);
|
ret = Some(*i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
fn client_config(&self) -> ClientConfig {
|
fn client_config(&self, spec: &Spec) -> ClientConfig {
|
||||||
let mut client_config = ClientConfig::default();
|
let mut client_config = ClientConfig::default();
|
||||||
match self.args.flag_cache {
|
match self.args.flag_cache {
|
||||||
Some(mb) => {
|
Some(mb) => {
|
||||||
@ -576,9 +577,10 @@ impl Configuration {
|
|||||||
"light" => journaldb::Algorithm::EarlyMerge,
|
"light" => journaldb::Algorithm::EarlyMerge,
|
||||||
"fast" => journaldb::Algorithm::OverlayRecent,
|
"fast" => journaldb::Algorithm::OverlayRecent,
|
||||||
"basic" => journaldb::Algorithm::RefCounted,
|
"basic" => journaldb::Algorithm::RefCounted,
|
||||||
"auto" => Self::find_best_db().unwrap_or(journaldb::Algorithm::OverlayRecent),
|
"auto" => self.find_best_db(spec).unwrap_or(journaldb::Algorithm::OverlayRecent),
|
||||||
_ => { die!("Invalid pruning method given."); }
|
_ => { die!("Invalid pruning method given."); }
|
||||||
};
|
};
|
||||||
|
info!("Using state DB of {}", client_config.pruning);
|
||||||
client_config.name = self.args.flag_identity.clone();
|
client_config.name = self.args.flag_identity.clone();
|
||||||
client_config.queue.max_mem_use = self.args.flag_queue_max_size;
|
client_config.queue.max_mem_use = self.args.flag_queue_max_size;
|
||||||
client_config
|
client_config
|
||||||
@ -673,13 +675,14 @@ impl Configuration {
|
|||||||
let spec = self.spec();
|
let spec = self.spec();
|
||||||
let net_settings = self.net_settings(&spec);
|
let net_settings = self.net_settings(&spec);
|
||||||
let sync_config = self.sync_config(&spec);
|
let sync_config = self.sync_config(&spec);
|
||||||
|
let client_config = self.client_config(&spec);
|
||||||
|
|
||||||
// Secret Store
|
// Secret Store
|
||||||
let account_service = Arc::new(self.account_service());
|
let account_service = Arc::new(self.account_service());
|
||||||
|
|
||||||
// Build client
|
// Build client
|
||||||
let mut service = ClientService::start(
|
let mut service = ClientService::start(
|
||||||
self.client_config(), spec, net_settings, &Path::new(&self.path())
|
client_config, spec, net_settings, &Path::new(&self.path())
|
||||||
).unwrap_or_else(|e| die_with_error(e));
|
).unwrap_or_else(|e| die_with_error(e));
|
||||||
|
|
||||||
panic_handler.forward_from(&service);
|
panic_handler.forward_from(&service);
|
||||||
|
@ -41,7 +41,7 @@ pub struct ArchiveDB {
|
|||||||
// all keys must be at least 12 bytes
|
// all keys must be at least 12 bytes
|
||||||
const LATEST_ERA_KEY : [u8; 12] = [ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
const LATEST_ERA_KEY : [u8; 12] = [ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
||||||
const VERSION_KEY : [u8; 12] = [ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
const VERSION_KEY : [u8; 12] = [ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
||||||
const DB_VERSION : u32 = 259;
|
const DB_VERSION : u32 = 0x103;
|
||||||
|
|
||||||
impl ArchiveDB {
|
impl ArchiveDB {
|
||||||
/// Create a new instance from file
|
/// Create a new instance from file
|
||||||
@ -55,7 +55,7 @@ impl ArchiveDB {
|
|||||||
if !backing.is_empty() {
|
if !backing.is_empty() {
|
||||||
match backing.get(&VERSION_KEY).map(|d| d.map(|v| decode::<u32>(&v))) {
|
match backing.get(&VERSION_KEY).map(|d| d.map(|v| decode::<u32>(&v))) {
|
||||||
Ok(Some(DB_VERSION)) => {},
|
Ok(Some(DB_VERSION)) => {},
|
||||||
v => panic!("Incompatible DB version, expected {}, got {:?}", DB_VERSION, v)
|
v => panic!("Incompatible DB version, expected {}, got {:?}; to resolve, remove {} and restart.", DB_VERSION, v, path)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
backing.put(&VERSION_KEY, &encode(&DB_VERSION)).expect("Error writing version to database");
|
backing.put(&VERSION_KEY, &encode(&DB_VERSION)).expect("Error writing version to database");
|
||||||
@ -168,7 +168,7 @@ impl JournalDB for ArchiveDB {
|
|||||||
Ok((inserts + deletes) as u32)
|
Ok((inserts + deletes) as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn latest_era() -> Option<u64> { self.latest_era }
|
fn latest_era(&self) -> Option<u64> { self.latest_era }
|
||||||
|
|
||||||
fn state(&self, id: &H256) -> Option<Bytes> {
|
fn state(&self, id: &H256) -> Option<Bytes> {
|
||||||
self.backing.get_by_prefix(&id.bytes()[0..12]).and_then(|b| Some(b.to_vec()))
|
self.backing.get_by_prefix(&id.bytes()[0..12]).and_then(|b| Some(b.to_vec()))
|
||||||
|
@ -70,7 +70,7 @@ pub struct EarlyMergeDB {
|
|||||||
// all keys must be at least 12 bytes
|
// all keys must be at least 12 bytes
|
||||||
const LATEST_ERA_KEY : [u8; 12] = [ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
const LATEST_ERA_KEY : [u8; 12] = [ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
||||||
const VERSION_KEY : [u8; 12] = [ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
const VERSION_KEY : [u8; 12] = [ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
||||||
const DB_VERSION : u32 = 3;
|
const DB_VERSION : u32 = 0x003;
|
||||||
const PADDING : [u8; 10] = [ 0u8; 10 ];
|
const PADDING : [u8; 10] = [ 0u8; 10 ];
|
||||||
|
|
||||||
impl EarlyMergeDB {
|
impl EarlyMergeDB {
|
||||||
@ -85,7 +85,7 @@ impl EarlyMergeDB {
|
|||||||
if !backing.is_empty() {
|
if !backing.is_empty() {
|
||||||
match backing.get(&VERSION_KEY).map(|d| d.map(|v| decode::<u32>(&v))) {
|
match backing.get(&VERSION_KEY).map(|d| d.map(|v| decode::<u32>(&v))) {
|
||||||
Ok(Some(DB_VERSION)) => {},
|
Ok(Some(DB_VERSION)) => {},
|
||||||
v => panic!("Incompatible DB version, expected {}, got {:?}", DB_VERSION, v)
|
v => panic!("Incompatible DB version, expected {}, got {:?}; to resolve, remove {} and restart.", DB_VERSION, v, path)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
backing.put(&VERSION_KEY, &encode(&DB_VERSION)).expect("Error writing version to database");
|
backing.put(&VERSION_KEY, &encode(&DB_VERSION)).expect("Error writing version to database");
|
||||||
@ -333,7 +333,7 @@ impl JournalDB for EarlyMergeDB {
|
|||||||
self.backing.get(&LATEST_ERA_KEY).expect("Low level database error").is_none()
|
self.backing.get(&LATEST_ERA_KEY).expect("Low level database error").is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn latest_era() -> Option<u64> { self.latest_era }
|
fn latest_era(&self) -> Option<u64> { self.latest_era }
|
||||||
|
|
||||||
fn mem_used(&self) -> usize {
|
fn mem_used(&self) -> usize {
|
||||||
self.overlay.mem_used() + match self.refs {
|
self.overlay.mem_used() + match self.refs {
|
||||||
@ -342,7 +342,6 @@ impl JournalDB for EarlyMergeDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
|
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
|
||||||
fn commit(&mut self, now: u64, id: &H256, end: Option<(u64, H256)>) -> Result<u32, UtilError> {
|
fn commit(&mut self, now: u64, id: &H256, end: Option<(u64, H256)>) -> Result<u32, UtilError> {
|
||||||
// journal format:
|
// journal format:
|
||||||
|
@ -29,7 +29,7 @@ mod refcounteddb;
|
|||||||
pub use self::traits::JournalDB;
|
pub use self::traits::JournalDB;
|
||||||
|
|
||||||
/// A journal database algorithm.
|
/// A journal database algorithm.
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum Algorithm {
|
pub enum Algorithm {
|
||||||
/// Keep all keys forever.
|
/// Keep all keys forever.
|
||||||
Archive,
|
Archive,
|
||||||
|
@ -95,7 +95,7 @@ impl Clone for OverlayRecentDB {
|
|||||||
// all keys must be at least 12 bytes
|
// all keys must be at least 12 bytes
|
||||||
const LATEST_ERA_KEY : [u8; 12] = [ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
const LATEST_ERA_KEY : [u8; 12] = [ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
||||||
const VERSION_KEY : [u8; 12] = [ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
const VERSION_KEY : [u8; 12] = [ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
||||||
const DB_VERSION : u32 = 0x200 + 3;
|
const DB_VERSION : u32 = 0x203;
|
||||||
const PADDING : [u8; 10] = [ 0u8; 10 ];
|
const PADDING : [u8; 10] = [ 0u8; 10 ];
|
||||||
|
|
||||||
impl OverlayRecentDB {
|
impl OverlayRecentDB {
|
||||||
@ -115,7 +115,7 @@ impl OverlayRecentDB {
|
|||||||
if !backing.is_empty() {
|
if !backing.is_empty() {
|
||||||
match backing.get(&VERSION_KEY).map(|d| d.map(|v| decode::<u32>(&v))) {
|
match backing.get(&VERSION_KEY).map(|d| d.map(|v| decode::<u32>(&v))) {
|
||||||
Ok(Some(DB_VERSION)) => {}
|
Ok(Some(DB_VERSION)) => {}
|
||||||
v => panic!("Incompatible DB version, expected {}, got {:?}", DB_VERSION, v)
|
v => panic!("Incompatible DB version, expected {}, got {:?}; to resolve, remove {} and restart.", DB_VERSION, v, path)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
backing.put(&VERSION_KEY, &encode(&DB_VERSION)).expect("Error writing version to database");
|
backing.put(&VERSION_KEY, &encode(&DB_VERSION)).expect("Error writing version to database");
|
||||||
@ -213,7 +213,7 @@ impl JournalDB for OverlayRecentDB {
|
|||||||
self.backing.get(&LATEST_ERA_KEY).expect("Low level database error").is_none()
|
self.backing.get(&LATEST_ERA_KEY).expect("Low level database error").is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn latest_era() -> Option<u64> { self.latest_era }
|
fn latest_era(&self) -> Option<u64> { self.journal_overlay.read().unwrap().latest_era }
|
||||||
|
|
||||||
fn commit(&mut self, now: u64, id: &H256, end: Option<(u64, H256)>) -> Result<u32, UtilError> {
|
fn commit(&mut self, now: u64, id: &H256, end: Option<(u64, H256)>) -> Result<u32, UtilError> {
|
||||||
// record new commit's details.
|
// record new commit's details.
|
||||||
|
@ -42,7 +42,7 @@ pub struct RefCountedDB {
|
|||||||
|
|
||||||
const LATEST_ERA_KEY : [u8; 12] = [ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
const LATEST_ERA_KEY : [u8; 12] = [ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
||||||
const VERSION_KEY : [u8; 12] = [ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
const VERSION_KEY : [u8; 12] = [ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
||||||
const DB_VERSION : u32 = 512;
|
const DB_VERSION : u32 = 0x200;
|
||||||
const PADDING : [u8; 10] = [ 0u8; 10 ];
|
const PADDING : [u8; 10] = [ 0u8; 10 ];
|
||||||
|
|
||||||
impl RefCountedDB {
|
impl RefCountedDB {
|
||||||
@ -57,7 +57,7 @@ impl RefCountedDB {
|
|||||||
if !backing.is_empty() {
|
if !backing.is_empty() {
|
||||||
match backing.get(&VERSION_KEY).map(|d| d.map(|v| decode::<u32>(&v))) {
|
match backing.get(&VERSION_KEY).map(|d| d.map(|v| decode::<u32>(&v))) {
|
||||||
Ok(Some(DB_VERSION)) => {},
|
Ok(Some(DB_VERSION)) => {},
|
||||||
v => panic!("Incompatible DB version, expected {}, got {:?}", DB_VERSION, v)
|
v => panic!("Incompatible DB version, expected {}, got {:?}; to resolve, remove {} and restart.", DB_VERSION, v, path)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
backing.put(&VERSION_KEY, &encode(&DB_VERSION)).expect("Error writing version to database");
|
backing.put(&VERSION_KEY, &encode(&DB_VERSION)).expect("Error writing version to database");
|
||||||
@ -112,7 +112,7 @@ impl JournalDB for RefCountedDB {
|
|||||||
self.latest_era.is_none()
|
self.latest_era.is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn latest_era() -> Option<u64> { self.latest_era }
|
fn latest_era(&self) -> Option<u64> { self.latest_era }
|
||||||
|
|
||||||
fn commit(&mut self, now: u64, id: &H256, end: Option<(u64, H256)>) -> Result<u32, UtilError> {
|
fn commit(&mut self, now: u64, id: &H256, end: Option<(u64, H256)>) -> Result<u32, UtilError> {
|
||||||
// journal format:
|
// journal format:
|
||||||
|
@ -32,7 +32,7 @@ pub trait JournalDB : HashDB + Send + Sync {
|
|||||||
fn is_empty(&self) -> bool;
|
fn is_empty(&self) -> bool;
|
||||||
|
|
||||||
/// Get the latest era in the DB. None if there isn't yet any data in there.
|
/// Get the latest era in the DB. None if there isn't yet any data in there.
|
||||||
fn latest_era() -> Option<u64> { self.latest_era }
|
fn latest_era(&self) -> Option<u64>;
|
||||||
|
|
||||||
/// Commit all recent insert operations and canonical historical commits' removals from the
|
/// Commit all recent insert operations and canonical historical commits' removals from the
|
||||||
/// old era to the backing database, reverting any non-canonical historical commit's inserts.
|
/// old era to the backing database, reverting any non-canonical historical commit's inserts.
|
||||||
|
Loading…
Reference in New Issue
Block a user