Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Store the database in a role specific subdirectory #9645

Merged
6 commits merged into from
Sep 7, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bin/node/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ sp-trie = { version = "4.0.0-dev", default-features = false, path = "../../../pr

[dev-dependencies]
sc-keystore = { version = "4.0.0-dev", path = "../../../client/keystore" }
sc-client-db = { version = "0.10.0-dev", path = "../../../client/db" }
sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" }
sc-consensus-babe = { version = "0.10.0-dev", path = "../../../client/consensus/babe" }
sc-consensus-epochs = { version = "0.10.0-dev", path = "../../../client/consensus/epochs" }
Expand Down
2 changes: 1 addition & 1 deletion bin/node/cli/tests/check_block_works.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub mod common;
fn check_block_works() {
let base_path = tempdir().expect("could not create a temp dir");

common::run_dev_node_for_a_while(base_path.path());
common::run_node_for_a_while(base_path.path(), &["--dev"]);

let status = Command::new(cargo_bin("substrate"))
.args(&["check-block", "--dev", "--pruning", "archive", "-d"])
Expand Down
15 changes: 13 additions & 2 deletions bin/node/cli/tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ pub fn wait_for(child: &mut Child, secs: usize) -> Option<ExitStatus> {
}

/// Run the node for a while (30 seconds)
pub fn run_dev_node_for_a_while(base_path: &Path) {
pub fn run_node_for_a_while(base_path: &Path, args: &[&str]) {
let mut cmd = Command::new(cargo_bin("substrate"));

let mut cmd = cmd.args(&["--dev"]).arg("-d").arg(base_path).spawn().unwrap();
let mut cmd = cmd.args(args).arg("-d").arg(base_path).spawn().unwrap();

// Let it produce some blocks.
thread::sleep(Duration::from_secs(30));
Expand All @@ -67,3 +67,14 @@ pub fn run_dev_node_for_a_while(base_path: &Path) {
kill(Pid::from_raw(cmd.id().try_into().unwrap()), SIGINT).unwrap();
assert!(wait_for(&mut cmd, 40).map(|x| x.success()).unwrap_or_default());
}

/// Run the node asserting that it fails with an error
pub fn run_node_assert_fail(base_path: &Path, args: &[&str]) {
let mut cmd = Command::new(cargo_bin("substrate"));

let mut cmd = cmd.args(args).arg("-d").arg(base_path).spawn().unwrap();

// Let it produce some blocks.
thread::sleep(Duration::from_secs(10));
assert!(cmd.try_wait().unwrap().is_some(), "the process should not be running anymore");
}
115 changes: 115 additions & 0 deletions bin/node/cli/tests/database_role_subdir_migration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// This file is part of Substrate.

// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program 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.

// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.

use sc_client_db::{
light::LightStorage, DatabaseSettings, DatabaseSource, KeepBlocks, PruningMode,
TransactionStorageMode,
};
use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper};
use tempfile::tempdir;

pub mod common;

#[test]
#[cfg(unix)]
fn database_role_subdir_migration() {
type Block = RawBlock<ExtrinsicWrapper<u64>>;

let base_path = tempdir().expect("could not create a temp dir");
let path = base_path.path().join("chains/dev/db");
// create a dummy database dir
{
let _old_db = LightStorage::<Block>::new(DatabaseSettings {
state_cache_size: 0,
state_cache_child_ratio: None,
state_pruning: PruningMode::ArchiveAll,
source: DatabaseSource::RocksDb { path: path.to_path_buf(), cache_size: 128 },
keep_blocks: KeepBlocks::All,
transaction_storage: TransactionStorageMode::BlockBody,
})
.unwrap();
}

assert!(path.join("db_version").exists());
assert!(!path.join("light").exists());

// start a light client
common::run_node_for_a_while(
base_path.path(),
&[
"--dev",
"--light",
"--port",
"30335",
"--rpc-port",
"44444",
"--ws-port",
"44445",
"--no-prometheus",
],
);

// check if the database dir had been migrated
assert!(!path.join("db_version").exists());
assert!(path.join("light/db_version").exists());
}

#[test]
#[cfg(unix)]
fn database_role_subdir_migration_fail_on_different_role() {
type Block = RawBlock<ExtrinsicWrapper<u64>>;

let base_path = tempdir().expect("could not create a temp dir");
let path = base_path.path().join("chains/dev/db");

// create a database with the old layout
{
let _old_db = LightStorage::<Block>::new(DatabaseSettings {
state_cache_size: 0,
state_cache_child_ratio: None,
state_pruning: PruningMode::ArchiveAll,
source: DatabaseSource::RocksDb { path: path.to_path_buf(), cache_size: 128 },
keep_blocks: KeepBlocks::All,
transaction_storage: TransactionStorageMode::BlockBody,
})
.unwrap();
}

assert!(path.join("db_version").exists());
assert!(!path.join("light/db_version").exists());

// start a client with a different role (full), it should fail and not change any files on disk
common::run_node_assert_fail(
&base_path.path(),
&[
"--dev",
"--port",
"30334",
"--rpc-port",
"44446",
"--ws-port",
"44447",
"--no-prometheus",
],
);

// check if the files are unchanged
assert!(path.join("db_version").exists());
assert!(!path.join("light/db_version").exists());
assert!(!path.join("full/db_version").exists());
}
2 changes: 1 addition & 1 deletion bin/node/cli/tests/export_import_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ fn export_import_revert() {
let exported_blocks_file = base_path.path().join("exported_blocks");
let db_path = base_path.path().join("db");

common::run_dev_node_for_a_while(base_path.path());
common::run_node_for_a_while(base_path.path(), &["--dev"]);

let mut executor = ExportImportRevertExecutor::new(&base_path, &exported_blocks_file, &db_path);

Expand Down
2 changes: 1 addition & 1 deletion bin/node/cli/tests/inspect_works.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub mod common;
fn inspect_works() {
let base_path = tempdir().expect("could not create a temp dir");

common::run_dev_node_for_a_while(base_path.path());
common::run_node_for_a_while(base_path.path(), &["--dev"]);

let status = Command::new(cargo_bin("substrate"))
.args(&["inspect", "--dev", "--pruning", "archive", "-d"])
Expand Down
4 changes: 2 additions & 2 deletions bin/node/cli/tests/purge_chain_works.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub mod common;
fn purge_chain_works() {
let base_path = tempdir().expect("could not create a temp dir");

common::run_dev_node_for_a_while(base_path.path());
common::run_node_for_a_while(base_path.path(), &["--dev"]);

let status = Command::new(cargo_bin("substrate"))
.args(&["purge-chain", "--dev", "-d"])
Expand All @@ -39,5 +39,5 @@ fn purge_chain_works() {

// Make sure that the `dev` chain folder exists, but the `db` is deleted.
assert!(base_path.path().join("chains/dev/").exists());
assert!(!base_path.path().join("chains/dev/db").exists());
assert!(!base_path.path().join("chains/dev/db/full").exists());
}
11 changes: 8 additions & 3 deletions client/cli/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,14 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
base_path: &PathBuf,
cache_size: usize,
database: Database,
role: &Role,
) -> Result<DatabaseSource> {
let rocksdb_path = base_path.join("db");
let paritydb_path = base_path.join("paritydb");
let role_dir = match role {
Role::Light => "light",
Role::Full | Role::Authority => "full",
};
let rocksdb_path = base_path.join("db").join(role_dir);
let paritydb_path = base_path.join("paritydb").join(role_dir);
Ok(match database {
Database::RocksDb => DatabaseSource::RocksDb { path: rocksdb_path, cache_size },
Database::ParityDb => DatabaseSource::ParityDb { path: rocksdb_path },
Expand Down Expand Up @@ -499,7 +504,7 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
)?,
keystore_remote,
keystore,
database: self.database_config(&config_dir, database_cache_size, database)?,
database: self.database_config(&config_dir, database_cache_size, database, &role)?,
state_cache_size: self.state_cache_size()?,
state_cache_child_ratio: self.state_cache_child_ratio()?,
state_pruning: self.state_pruning(unsafe_pruning, &role)?,
Expand Down
18 changes: 17 additions & 1 deletion client/db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ pub enum DatabaseSource {
}

impl DatabaseSource {
/// Return dabase path for databases that are on the disk.
/// Return path for databases that are stored on disk.
pub fn path(&self) -> Option<&Path> {
match self {
// as per https://github.com/paritytech/substrate/pull/9500#discussion_r684312550
Expand All @@ -367,6 +367,22 @@ impl DatabaseSource {
DatabaseSource::Custom(..) => None,
}
}

/// Set path for databases that are stored on disk.
pub fn set_path(&mut self, p: &Path) -> bool {
match self {
DatabaseSource::Auto { ref mut paritydb_path, .. } => {
*paritydb_path = p.into();
true
},
DatabaseSource::RocksDb { ref mut path, .. } |
DatabaseSource::ParityDb { ref mut path } => {
*path = p.into();
true
},
DatabaseSource::Custom(..) => false,
}
}
}

impl std::fmt::Display for DatabaseSource {
Expand Down
23 changes: 13 additions & 10 deletions client/db/src/upgrade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ mod tests {
}
}

fn open_database(db_path: &Path) -> sp_blockchain::Result<()> {
fn open_database(db_path: &Path, db_type: DatabaseType) -> sp_blockchain::Result<()> {
crate::utils::open_database::<Block>(
&DatabaseSettings {
state_cache_size: 0,
Expand All @@ -196,7 +196,7 @@ mod tests {
keep_blocks: KeepBlocks::All,
transaction_storage: TransactionStorageMode::BlockBody,
},
DatabaseType::Full,
db_type,
)
.map(|_| ())
}
Expand All @@ -205,25 +205,28 @@ mod tests {
fn downgrade_never_happens() {
let db_dir = tempfile::TempDir::new().unwrap();
create_db(db_dir.path(), Some(CURRENT_VERSION + 1));
assert!(open_database(db_dir.path()).is_err());
assert!(open_database(db_dir.path(), DatabaseType::Full).is_err());
}

#[test]
fn open_empty_database_works() {
let db_type = DatabaseType::Full;
let db_dir = tempfile::TempDir::new().unwrap();
open_database(db_dir.path()).unwrap();
open_database(db_dir.path()).unwrap();
assert_eq!(current_version(db_dir.path()).unwrap(), CURRENT_VERSION);
let db_dir = db_dir.path().join(db_type.as_str());
open_database(&db_dir, db_type).unwrap();
open_database(&db_dir, db_type).unwrap();
assert_eq!(current_version(&db_dir).unwrap(), CURRENT_VERSION);
}

#[test]
fn upgrade_to_3_works() {
let db_type = DatabaseType::Full;
for version_from_file in &[None, Some(1), Some(2)] {
let db_dir = tempfile::TempDir::new().unwrap();
let db_path = db_dir.path();
create_db(db_path, *version_from_file);
open_database(db_path).unwrap();
assert_eq!(current_version(db_path).unwrap(), CURRENT_VERSION);
let db_path = db_dir.path().join(db_type.as_str());
create_db(&db_path, *version_from_file);
open_database(&db_path, db_type).unwrap();
assert_eq!(current_version(&db_path).unwrap(), CURRENT_VERSION);
}
}
}
Loading