Reformat the source code
This commit is contained in:
@@ -16,10 +16,10 @@
|
||||
|
||||
//! Database-related operations.
|
||||
|
||||
#[path="rocksdb/mod.rs"]
|
||||
#[path = "rocksdb/mod.rs"]
|
||||
mod impls;
|
||||
|
||||
pub use self::impls::{open_db, restoration_db_handler, migrate};
|
||||
pub use self::impls::{migrate, open_db, restoration_db_handler};
|
||||
|
||||
#[cfg(feature = "secretstore")]
|
||||
pub use self::impls::open_secretstore_db;
|
||||
|
||||
@@ -16,73 +16,68 @@
|
||||
|
||||
//! Blooms migration from rocksdb to blooms-db
|
||||
|
||||
use std::path::Path;
|
||||
use ethereum_types::Bloom;
|
||||
use super::{kvdb_rocksdb::DatabaseConfig, open_database};
|
||||
use ethcore::error::Error;
|
||||
use ethereum_types::Bloom;
|
||||
use rlp;
|
||||
use super::kvdb_rocksdb::DatabaseConfig;
|
||||
use super::open_database;
|
||||
use std::path::Path;
|
||||
|
||||
const LOG_BLOOMS_ELEMENTS_PER_INDEX: u64 = 16;
|
||||
|
||||
pub fn migrate_blooms<P: AsRef<Path>>(path: P, config: &DatabaseConfig) -> Result<(), Error> {
|
||||
// init
|
||||
let db = open_database(&path.as_ref().to_string_lossy(), config)?;
|
||||
// init
|
||||
let db = open_database(&path.as_ref().to_string_lossy(), config)?;
|
||||
|
||||
// possible optimization:
|
||||
// pre-allocate space on disk for faster migration
|
||||
// possible optimization:
|
||||
// pre-allocate space on disk for faster migration
|
||||
|
||||
// iterate over header blooms and insert them in blooms-db
|
||||
// Some(3) -> COL_EXTRA
|
||||
// 3u8 -> ExtrasIndex::BlocksBlooms
|
||||
// 0u8 -> level 0
|
||||
let blooms_iterator = db.key_value()
|
||||
.iter_from_prefix(Some(3), &[3u8, 0u8])
|
||||
.filter(|(key, _)| key.len() == 6)
|
||||
.take_while(|(key, _)| {
|
||||
key[0] == 3u8 && key[1] == 0u8
|
||||
})
|
||||
.map(|(key, group)| {
|
||||
let index =
|
||||
(key[2] as u64) << 24 |
|
||||
(key[3] as u64) << 16 |
|
||||
(key[4] as u64) << 8 |
|
||||
(key[5] as u64);
|
||||
let number = index * LOG_BLOOMS_ELEMENTS_PER_INDEX;
|
||||
// iterate over header blooms and insert them in blooms-db
|
||||
// Some(3) -> COL_EXTRA
|
||||
// 3u8 -> ExtrasIndex::BlocksBlooms
|
||||
// 0u8 -> level 0
|
||||
let blooms_iterator = db
|
||||
.key_value()
|
||||
.iter_from_prefix(Some(3), &[3u8, 0u8])
|
||||
.filter(|(key, _)| key.len() == 6)
|
||||
.take_while(|(key, _)| key[0] == 3u8 && key[1] == 0u8)
|
||||
.map(|(key, group)| {
|
||||
let index = (key[2] as u64) << 24
|
||||
| (key[3] as u64) << 16
|
||||
| (key[4] as u64) << 8
|
||||
| (key[5] as u64);
|
||||
let number = index * LOG_BLOOMS_ELEMENTS_PER_INDEX;
|
||||
|
||||
let blooms = rlp::decode_list::<Bloom>(&group);
|
||||
(number, blooms)
|
||||
});
|
||||
let blooms = rlp::decode_list::<Bloom>(&group);
|
||||
(number, blooms)
|
||||
});
|
||||
|
||||
for (number, blooms) in blooms_iterator {
|
||||
db.blooms().insert_blooms(number, blooms.iter())?;
|
||||
}
|
||||
for (number, blooms) in blooms_iterator {
|
||||
db.blooms().insert_blooms(number, blooms.iter())?;
|
||||
}
|
||||
|
||||
// iterate over trace blooms and insert them in blooms-db
|
||||
// Some(4) -> COL_TRACE
|
||||
// 1u8 -> TraceDBIndex::BloomGroups
|
||||
// 0u8 -> level 0
|
||||
let trace_blooms_iterator = db.key_value()
|
||||
.iter_from_prefix(Some(4), &[1u8, 0u8])
|
||||
.filter(|(key, _)| key.len() == 6)
|
||||
.take_while(|(key, _)| {
|
||||
key[0] == 1u8 && key[1] == 0u8
|
||||
})
|
||||
.map(|(key, group)| {
|
||||
let index =
|
||||
(key[2] as u64) |
|
||||
(key[3] as u64) << 8 |
|
||||
(key[4] as u64) << 16 |
|
||||
(key[5] as u64) << 24;
|
||||
let number = index * LOG_BLOOMS_ELEMENTS_PER_INDEX;
|
||||
// iterate over trace blooms and insert them in blooms-db
|
||||
// Some(4) -> COL_TRACE
|
||||
// 1u8 -> TraceDBIndex::BloomGroups
|
||||
// 0u8 -> level 0
|
||||
let trace_blooms_iterator = db
|
||||
.key_value()
|
||||
.iter_from_prefix(Some(4), &[1u8, 0u8])
|
||||
.filter(|(key, _)| key.len() == 6)
|
||||
.take_while(|(key, _)| key[0] == 1u8 && key[1] == 0u8)
|
||||
.map(|(key, group)| {
|
||||
let index = (key[2] as u64)
|
||||
| (key[3] as u64) << 8
|
||||
| (key[4] as u64) << 16
|
||||
| (key[5] as u64) << 24;
|
||||
let number = index * LOG_BLOOMS_ELEMENTS_PER_INDEX;
|
||||
|
||||
let blooms = rlp::decode_list::<Bloom>(&group);
|
||||
(number, blooms)
|
||||
});
|
||||
let blooms = rlp::decode_list::<Bloom>(&group);
|
||||
(number, blooms)
|
||||
});
|
||||
|
||||
for (number, blooms) in trace_blooms_iterator {
|
||||
db.trace_blooms().insert_blooms(number, blooms.iter())?;
|
||||
}
|
||||
for (number, blooms) in trace_blooms_iterator {
|
||||
db.trace_blooms().insert_blooms(number, blooms.iter())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -14,24 +14,27 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::path::Path;
|
||||
use ethcore_db::NUM_COLUMNS;
|
||||
use ethcore::client::{ClientConfig, DatabaseCompactionProfile};
|
||||
use super::kvdb_rocksdb::{CompactionProfile, DatabaseConfig};
|
||||
use ethcore::client::{ClientConfig, DatabaseCompactionProfile};
|
||||
use ethcore_db::NUM_COLUMNS;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn compaction_profile(profile: &DatabaseCompactionProfile, db_path: &Path) -> CompactionProfile {
|
||||
match profile {
|
||||
&DatabaseCompactionProfile::Auto => CompactionProfile::auto(db_path),
|
||||
&DatabaseCompactionProfile::SSD => CompactionProfile::ssd(),
|
||||
&DatabaseCompactionProfile::HDD => CompactionProfile::hdd(),
|
||||
}
|
||||
pub fn compaction_profile(
|
||||
profile: &DatabaseCompactionProfile,
|
||||
db_path: &Path,
|
||||
) -> CompactionProfile {
|
||||
match profile {
|
||||
&DatabaseCompactionProfile::Auto => CompactionProfile::auto(db_path),
|
||||
&DatabaseCompactionProfile::SSD => CompactionProfile::ssd(),
|
||||
&DatabaseCompactionProfile::HDD => CompactionProfile::hdd(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn client_db_config(client_path: &Path, client_config: &ClientConfig) -> DatabaseConfig {
|
||||
let mut client_db_config = DatabaseConfig::with_columns(NUM_COLUMNS);
|
||||
let mut client_db_config = DatabaseConfig::with_columns(NUM_COLUMNS);
|
||||
|
||||
client_db_config.memory_budget = client_config.db_cache_size;
|
||||
client_db_config.compaction = compaction_profile(&client_config.db_compaction, &client_path);
|
||||
client_db_config.memory_budget = client_config.db_cache_size;
|
||||
client_db_config.compaction = compaction_profile(&client_config.db_compaction, &client_path);
|
||||
|
||||
client_db_config
|
||||
client_db_config
|
||||
}
|
||||
|
||||
@@ -14,32 +14,34 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::fs;
|
||||
use std::io::{Read, Write, Error as IoError, ErrorKind};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::fmt::{Display, Formatter, Error as FmtError};
|
||||
use super::migration_rocksdb::{Manager as MigrationManager, Config as MigrationConfig, ChangeColumns};
|
||||
use super::kvdb_rocksdb::{CompactionProfile, DatabaseConfig};
|
||||
use ethcore::client::DatabaseCompactionProfile;
|
||||
use ethcore;
|
||||
use super::{
|
||||
kvdb_rocksdb::{CompactionProfile, DatabaseConfig},
|
||||
migration_rocksdb::{ChangeColumns, Config as MigrationConfig, Manager as MigrationManager},
|
||||
};
|
||||
use ethcore::{self, client::DatabaseCompactionProfile};
|
||||
use std::{
|
||||
fmt::{Display, Error as FmtError, Formatter},
|
||||
fs,
|
||||
io::{Error as IoError, ErrorKind, Read, Write},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use super::helpers;
|
||||
use super::blooms::migrate_blooms;
|
||||
use super::{blooms::migrate_blooms, helpers};
|
||||
|
||||
/// The migration from v10 to v11.
|
||||
/// Adds a column for node info.
|
||||
pub const TO_V11: ChangeColumns = ChangeColumns {
|
||||
pre_columns: Some(6),
|
||||
post_columns: Some(7),
|
||||
version: 11,
|
||||
pre_columns: Some(6),
|
||||
post_columns: Some(7),
|
||||
version: 11,
|
||||
};
|
||||
|
||||
/// The migration from v11 to v12.
|
||||
/// Adds a column for light chain storage.
|
||||
pub const TO_V12: ChangeColumns = ChangeColumns {
|
||||
pre_columns: Some(7),
|
||||
post_columns: Some(8),
|
||||
version: 12,
|
||||
pre_columns: Some(7),
|
||||
post_columns: Some(8),
|
||||
version: 12,
|
||||
};
|
||||
|
||||
/// Database is assumed to be at default version, when no version file is found.
|
||||
@@ -56,22 +58,22 @@ const VERSION_FILE_NAME: &'static str = "db_version";
|
||||
/// Migration related erorrs.
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// Returned when current version cannot be read or guessed.
|
||||
UnknownDatabaseVersion,
|
||||
/// Existing DB is newer than the known one.
|
||||
FutureDBVersion,
|
||||
/// Migration is not possible.
|
||||
MigrationImpossible,
|
||||
/// Blooms-db migration error.
|
||||
BloomsDB(ethcore::error::Error),
|
||||
/// Migration was completed succesfully,
|
||||
/// but there was a problem with io.
|
||||
Io(IoError),
|
||||
/// Returned when current version cannot be read or guessed.
|
||||
UnknownDatabaseVersion,
|
||||
/// Existing DB is newer than the known one.
|
||||
FutureDBVersion,
|
||||
/// Migration is not possible.
|
||||
MigrationImpossible,
|
||||
/// Blooms-db migration error.
|
||||
BloomsDB(ethcore::error::Error),
|
||||
/// Migration was completed succesfully,
|
||||
/// but there was a problem with io.
|
||||
Io(IoError),
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
|
||||
let out = match *self {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
|
||||
let out = match *self {
|
||||
Error::UnknownDatabaseVersion => "Current database version cannot be read".into(),
|
||||
Error::FutureDBVersion => "Database was created with newer client version. Upgrade your client or delete DB and resync.".into(),
|
||||
Error::MigrationImpossible => format!("Database migration to version {} is not possible.", CURRENT_VERSION),
|
||||
@@ -79,153 +81,173 @@ impl Display for Error {
|
||||
Error::Io(ref err) => format!("Unexpected io error on DB migration: {}.", err),
|
||||
};
|
||||
|
||||
write!(f, "{}", out)
|
||||
}
|
||||
write!(f, "{}", out)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IoError> for Error {
|
||||
fn from(err: IoError) -> Self {
|
||||
Error::Io(err)
|
||||
}
|
||||
fn from(err: IoError) -> Self {
|
||||
Error::Io(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the version file path.
|
||||
fn version_file_path(path: &Path) -> PathBuf {
|
||||
let mut file_path = path.to_owned();
|
||||
file_path.push(VERSION_FILE_NAME);
|
||||
file_path
|
||||
let mut file_path = path.to_owned();
|
||||
file_path.push(VERSION_FILE_NAME);
|
||||
file_path
|
||||
}
|
||||
|
||||
/// Reads current database version from the file at given path.
|
||||
/// If the file does not exist returns `DEFAULT_VERSION`.
|
||||
fn current_version(path: &Path) -> Result<u32, Error> {
|
||||
match fs::File::open(version_file_path(path)) {
|
||||
Err(ref err) if err.kind() == ErrorKind::NotFound => Ok(DEFAULT_VERSION),
|
||||
Err(_) => Err(Error::UnknownDatabaseVersion),
|
||||
Ok(mut file) => {
|
||||
let mut s = String::new();
|
||||
file.read_to_string(&mut s).map_err(|_| Error::UnknownDatabaseVersion)?;
|
||||
u32::from_str_radix(&s, 10).map_err(|_| Error::UnknownDatabaseVersion)
|
||||
},
|
||||
}
|
||||
match fs::File::open(version_file_path(path)) {
|
||||
Err(ref err) if err.kind() == ErrorKind::NotFound => Ok(DEFAULT_VERSION),
|
||||
Err(_) => Err(Error::UnknownDatabaseVersion),
|
||||
Ok(mut file) => {
|
||||
let mut s = String::new();
|
||||
file.read_to_string(&mut s)
|
||||
.map_err(|_| Error::UnknownDatabaseVersion)?;
|
||||
u32::from_str_radix(&s, 10).map_err(|_| Error::UnknownDatabaseVersion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes current database version to the file.
|
||||
/// Creates a new file if the version file does not exist yet.
|
||||
fn update_version(path: &Path) -> Result<(), Error> {
|
||||
fs::create_dir_all(path)?;
|
||||
let mut file = fs::File::create(version_file_path(path))?;
|
||||
file.write_all(format!("{}", CURRENT_VERSION).as_bytes())?;
|
||||
Ok(())
|
||||
fs::create_dir_all(path)?;
|
||||
let mut file = fs::File::create(version_file_path(path))?;
|
||||
file.write_all(format!("{}", CURRENT_VERSION).as_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Consolidated database path
|
||||
fn consolidated_database_path(path: &Path) -> PathBuf {
|
||||
let mut state_path = path.to_owned();
|
||||
state_path.push("db");
|
||||
state_path
|
||||
let mut state_path = path.to_owned();
|
||||
state_path.push("db");
|
||||
state_path
|
||||
}
|
||||
|
||||
/// Database backup
|
||||
fn backup_database_path(path: &Path) -> PathBuf {
|
||||
let mut backup_path = path.to_owned();
|
||||
backup_path.pop();
|
||||
backup_path.push("temp_backup");
|
||||
backup_path
|
||||
let mut backup_path = path.to_owned();
|
||||
backup_path.pop();
|
||||
backup_path.push("temp_backup");
|
||||
backup_path
|
||||
}
|
||||
|
||||
/// Default migration settings.
|
||||
pub fn default_migration_settings(compaction_profile: &CompactionProfile) -> MigrationConfig {
|
||||
MigrationConfig {
|
||||
batch_size: BATCH_SIZE,
|
||||
compaction_profile: *compaction_profile,
|
||||
}
|
||||
MigrationConfig {
|
||||
batch_size: BATCH_SIZE,
|
||||
compaction_profile: *compaction_profile,
|
||||
}
|
||||
}
|
||||
|
||||
/// Migrations on the consolidated database.
|
||||
fn consolidated_database_migrations(compaction_profile: &CompactionProfile) -> Result<MigrationManager, Error> {
|
||||
let mut manager = MigrationManager::new(default_migration_settings(compaction_profile));
|
||||
manager.add_migration(TO_V11).map_err(|_| Error::MigrationImpossible)?;
|
||||
manager.add_migration(TO_V12).map_err(|_| Error::MigrationImpossible)?;
|
||||
Ok(manager)
|
||||
fn consolidated_database_migrations(
|
||||
compaction_profile: &CompactionProfile,
|
||||
) -> Result<MigrationManager, Error> {
|
||||
let mut manager = MigrationManager::new(default_migration_settings(compaction_profile));
|
||||
manager
|
||||
.add_migration(TO_V11)
|
||||
.map_err(|_| Error::MigrationImpossible)?;
|
||||
manager
|
||||
.add_migration(TO_V12)
|
||||
.map_err(|_| Error::MigrationImpossible)?;
|
||||
Ok(manager)
|
||||
}
|
||||
|
||||
/// Migrates database at given position with given migration rules.
|
||||
fn migrate_database(version: u32, db_path: &Path, mut migrations: MigrationManager) -> Result<(), Error> {
|
||||
// check if migration is needed
|
||||
if !migrations.is_needed(version) {
|
||||
return Ok(())
|
||||
}
|
||||
fn migrate_database(
|
||||
version: u32,
|
||||
db_path: &Path,
|
||||
mut migrations: MigrationManager,
|
||||
) -> Result<(), Error> {
|
||||
// check if migration is needed
|
||||
if !migrations.is_needed(version) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let backup_path = backup_database_path(&db_path);
|
||||
// remove the backup dir if it exists
|
||||
let _ = fs::remove_dir_all(&backup_path);
|
||||
let backup_path = backup_database_path(&db_path);
|
||||
// remove the backup dir if it exists
|
||||
let _ = fs::remove_dir_all(&backup_path);
|
||||
|
||||
// migrate old database to the new one
|
||||
let temp_path = migrations.execute(&db_path, version)?;
|
||||
// migrate old database to the new one
|
||||
let temp_path = migrations.execute(&db_path, version)?;
|
||||
|
||||
// completely in-place migration leads to the paths being equal.
|
||||
// in that case, no need to shuffle directories.
|
||||
if temp_path == db_path { return Ok(()) }
|
||||
// completely in-place migration leads to the paths being equal.
|
||||
// in that case, no need to shuffle directories.
|
||||
if temp_path == db_path {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// create backup
|
||||
fs::rename(&db_path, &backup_path)?;
|
||||
// create backup
|
||||
fs::rename(&db_path, &backup_path)?;
|
||||
|
||||
// replace the old database with the new one
|
||||
if let Err(err) = fs::rename(&temp_path, &db_path) {
|
||||
// if something went wrong, bring back backup
|
||||
fs::rename(&backup_path, &db_path)?;
|
||||
return Err(err.into());
|
||||
}
|
||||
// replace the old database with the new one
|
||||
if let Err(err) = fs::rename(&temp_path, &db_path) {
|
||||
// if something went wrong, bring back backup
|
||||
fs::rename(&backup_path, &db_path)?;
|
||||
return Err(err.into());
|
||||
}
|
||||
|
||||
// remove backup
|
||||
fs::remove_dir_all(&backup_path).map_err(Into::into)
|
||||
// remove backup
|
||||
fs::remove_dir_all(&backup_path).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn exists(path: &Path) -> bool {
|
||||
fs::metadata(path).is_ok()
|
||||
fs::metadata(path).is_ok()
|
||||
}
|
||||
|
||||
/// Migrates the database.
|
||||
pub fn migrate(path: &Path, compaction_profile: &DatabaseCompactionProfile) -> Result<(), Error> {
|
||||
let compaction_profile = helpers::compaction_profile(&compaction_profile, path);
|
||||
let compaction_profile = helpers::compaction_profile(&compaction_profile, path);
|
||||
|
||||
// read version file.
|
||||
let version = current_version(path)?;
|
||||
// read version file.
|
||||
let version = current_version(path)?;
|
||||
|
||||
// migrate the databases.
|
||||
// main db directory may already exists, so let's check if we have blocks dir
|
||||
if version > CURRENT_VERSION {
|
||||
return Err(Error::FutureDBVersion);
|
||||
}
|
||||
// migrate the databases.
|
||||
// main db directory may already exists, so let's check if we have blocks dir
|
||||
if version > CURRENT_VERSION {
|
||||
return Err(Error::FutureDBVersion);
|
||||
}
|
||||
|
||||
// We are in the latest version, yay!
|
||||
if version == CURRENT_VERSION {
|
||||
return Ok(())
|
||||
}
|
||||
// We are in the latest version, yay!
|
||||
if version == CURRENT_VERSION {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let db_path = consolidated_database_path(path);
|
||||
let db_path = consolidated_database_path(path);
|
||||
|
||||
// Further migrations
|
||||
if version < CURRENT_VERSION && exists(&db_path) {
|
||||
println!("Migrating database from version {} to {}", version, CURRENT_VERSION);
|
||||
migrate_database(version, &db_path, consolidated_database_migrations(&compaction_profile)?)?;
|
||||
// Further migrations
|
||||
if version < CURRENT_VERSION && exists(&db_path) {
|
||||
println!(
|
||||
"Migrating database from version {} to {}",
|
||||
version, CURRENT_VERSION
|
||||
);
|
||||
migrate_database(
|
||||
version,
|
||||
&db_path,
|
||||
consolidated_database_migrations(&compaction_profile)?,
|
||||
)?;
|
||||
|
||||
if version < BLOOMS_DB_VERSION {
|
||||
println!("Migrating blooms to blooms-db...");
|
||||
let db_config = DatabaseConfig {
|
||||
max_open_files: 64,
|
||||
memory_budget: None,
|
||||
compaction: compaction_profile,
|
||||
columns: ethcore_db::NUM_COLUMNS,
|
||||
};
|
||||
if version < BLOOMS_DB_VERSION {
|
||||
println!("Migrating blooms to blooms-db...");
|
||||
let db_config = DatabaseConfig {
|
||||
max_open_files: 64,
|
||||
memory_budget: None,
|
||||
compaction: compaction_profile,
|
||||
columns: ethcore_db::NUM_COLUMNS,
|
||||
};
|
||||
|
||||
migrate_blooms(&db_path, &db_config).map_err(Error::BloomsDB)?;
|
||||
}
|
||||
migrate_blooms(&db_path, &db_config).map_err(Error::BloomsDB)?;
|
||||
}
|
||||
|
||||
println!("Migration finished");
|
||||
}
|
||||
println!("Migration finished");
|
||||
}
|
||||
|
||||
// update version file.
|
||||
update_version(path)
|
||||
// update version file.
|
||||
update_version(path)
|
||||
}
|
||||
|
||||
@@ -14,104 +14,115 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
extern crate ethcore_blockchain;
|
||||
extern crate kvdb_rocksdb;
|
||||
extern crate migration_rocksdb;
|
||||
extern crate ethcore_blockchain;
|
||||
|
||||
use std::{io, fs};
|
||||
use std::sync::Arc;
|
||||
use std::path::Path;
|
||||
use self::{
|
||||
ethcore_blockchain::{BlockChainDB, BlockChainDBHandler},
|
||||
kvdb_rocksdb::{Database, DatabaseConfig},
|
||||
};
|
||||
use blooms_db;
|
||||
use ethcore_db::NUM_COLUMNS;
|
||||
use ethcore::client::{ClientConfig, DatabaseCompactionProfile};
|
||||
use ethcore_db::NUM_COLUMNS;
|
||||
use kvdb::KeyValueDB;
|
||||
use self::ethcore_blockchain::{BlockChainDBHandler, BlockChainDB};
|
||||
use self::kvdb_rocksdb::{Database, DatabaseConfig};
|
||||
use std::{fs, io, path::Path, sync::Arc};
|
||||
|
||||
use cache::CacheConfig;
|
||||
|
||||
mod blooms;
|
||||
mod migration;
|
||||
mod helpers;
|
||||
mod migration;
|
||||
|
||||
pub use self::migration::migrate;
|
||||
|
||||
struct AppDB {
|
||||
key_value: Arc<KeyValueDB>,
|
||||
blooms: blooms_db::Database,
|
||||
trace_blooms: blooms_db::Database,
|
||||
key_value: Arc<KeyValueDB>,
|
||||
blooms: blooms_db::Database,
|
||||
trace_blooms: blooms_db::Database,
|
||||
}
|
||||
|
||||
impl BlockChainDB for AppDB {
|
||||
fn key_value(&self) -> &Arc<KeyValueDB> {
|
||||
&self.key_value
|
||||
}
|
||||
fn key_value(&self) -> &Arc<KeyValueDB> {
|
||||
&self.key_value
|
||||
}
|
||||
|
||||
fn blooms(&self) -> &blooms_db::Database {
|
||||
&self.blooms
|
||||
}
|
||||
fn blooms(&self) -> &blooms_db::Database {
|
||||
&self.blooms
|
||||
}
|
||||
|
||||
fn trace_blooms(&self) -> &blooms_db::Database {
|
||||
&self.trace_blooms
|
||||
}
|
||||
fn trace_blooms(&self) -> &blooms_db::Database {
|
||||
&self.trace_blooms
|
||||
}
|
||||
}
|
||||
|
||||
/// Open a secret store DB using the given secret store data path. The DB path is one level beneath the data path.
|
||||
#[cfg(feature = "secretstore")]
|
||||
pub fn open_secretstore_db(data_path: &str) -> Result<Arc<KeyValueDB>, String> {
|
||||
use std::path::PathBuf;
|
||||
use std::path::PathBuf;
|
||||
|
||||
let mut db_path = PathBuf::from(data_path);
|
||||
db_path.push("db");
|
||||
let db_path = db_path.to_str().ok_or_else(|| "Invalid secretstore path".to_string())?;
|
||||
Ok(Arc::new(Database::open_default(&db_path).map_err(|e| format!("Error opening database: {:?}", e))?))
|
||||
let mut db_path = PathBuf::from(data_path);
|
||||
db_path.push("db");
|
||||
let db_path = db_path
|
||||
.to_str()
|
||||
.ok_or_else(|| "Invalid secretstore path".to_string())?;
|
||||
Ok(Arc::new(
|
||||
Database::open_default(&db_path).map_err(|e| format!("Error opening database: {:?}", e))?,
|
||||
))
|
||||
}
|
||||
|
||||
/// Create a restoration db handler using the config generated by `client_path` and `client_config`.
|
||||
pub fn restoration_db_handler(client_path: &Path, client_config: &ClientConfig) -> Box<BlockChainDBHandler> {
|
||||
let client_db_config = helpers::client_db_config(client_path, client_config);
|
||||
pub fn restoration_db_handler(
|
||||
client_path: &Path,
|
||||
client_config: &ClientConfig,
|
||||
) -> Box<BlockChainDBHandler> {
|
||||
let client_db_config = helpers::client_db_config(client_path, client_config);
|
||||
|
||||
struct RestorationDBHandler {
|
||||
config: DatabaseConfig,
|
||||
}
|
||||
struct RestorationDBHandler {
|
||||
config: DatabaseConfig,
|
||||
}
|
||||
|
||||
impl BlockChainDBHandler for RestorationDBHandler {
|
||||
fn open(&self, db_path: &Path) -> io::Result<Arc<BlockChainDB>> {
|
||||
open_database(&db_path.to_string_lossy(), &self.config)
|
||||
}
|
||||
}
|
||||
impl BlockChainDBHandler for RestorationDBHandler {
|
||||
fn open(&self, db_path: &Path) -> io::Result<Arc<BlockChainDB>> {
|
||||
open_database(&db_path.to_string_lossy(), &self.config)
|
||||
}
|
||||
}
|
||||
|
||||
Box::new(RestorationDBHandler {
|
||||
config: client_db_config,
|
||||
})
|
||||
Box::new(RestorationDBHandler {
|
||||
config: client_db_config,
|
||||
})
|
||||
}
|
||||
|
||||
/// Open a new main DB.
|
||||
pub fn open_db(client_path: &str, cache_config: &CacheConfig, compaction: &DatabaseCompactionProfile) -> io::Result<Arc<BlockChainDB>> {
|
||||
let path = Path::new(client_path);
|
||||
pub fn open_db(
|
||||
client_path: &str,
|
||||
cache_config: &CacheConfig,
|
||||
compaction: &DatabaseCompactionProfile,
|
||||
) -> io::Result<Arc<BlockChainDB>> {
|
||||
let path = Path::new(client_path);
|
||||
|
||||
let db_config = DatabaseConfig {
|
||||
memory_budget: Some(cache_config.blockchain() as usize * 1024 * 1024),
|
||||
compaction: helpers::compaction_profile(&compaction, path),
|
||||
.. DatabaseConfig::with_columns(NUM_COLUMNS)
|
||||
};
|
||||
let db_config = DatabaseConfig {
|
||||
memory_budget: Some(cache_config.blockchain() as usize * 1024 * 1024),
|
||||
compaction: helpers::compaction_profile(&compaction, path),
|
||||
..DatabaseConfig::with_columns(NUM_COLUMNS)
|
||||
};
|
||||
|
||||
open_database(client_path, &db_config)
|
||||
open_database(client_path, &db_config)
|
||||
}
|
||||
|
||||
pub fn open_database(client_path: &str, config: &DatabaseConfig) -> io::Result<Arc<BlockChainDB>> {
|
||||
let path = Path::new(client_path);
|
||||
let path = Path::new(client_path);
|
||||
|
||||
let blooms_path = path.join("blooms");
|
||||
let trace_blooms_path = path.join("trace_blooms");
|
||||
fs::create_dir_all(&blooms_path)?;
|
||||
fs::create_dir_all(&trace_blooms_path)?;
|
||||
let blooms_path = path.join("blooms");
|
||||
let trace_blooms_path = path.join("trace_blooms");
|
||||
fs::create_dir_all(&blooms_path)?;
|
||||
fs::create_dir_all(&trace_blooms_path)?;
|
||||
|
||||
let db = AppDB {
|
||||
key_value: Arc::new(Database::open(&config, client_path)?),
|
||||
blooms: blooms_db::Database::open(blooms_path)?,
|
||||
trace_blooms: blooms_db::Database::open(trace_blooms_path)?,
|
||||
};
|
||||
let db = AppDB {
|
||||
key_value: Arc::new(Database::open(&config, client_path)?),
|
||||
blooms: blooms_db::Database::open(blooms_path)?,
|
||||
trace_blooms: blooms_db::Database::open(trace_blooms_path)?,
|
||||
};
|
||||
|
||||
Ok(Arc::new(db))
|
||||
Ok(Arc::new(db))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user