Added purge subcommand to purge beacon chain db (#971)
This commit is contained in:
parent
869b0621d6
commit
065ea15c9f
@ -221,7 +221,7 @@ where
|
||||
.get::<PersistedBeaconChain>(&Hash256::from_slice(&BEACON_CHAIN_DB_KEY))
|
||||
.map_err(|e| format!("DB error when reading persisted beacon chain: {:?}", e))?
|
||||
.ok_or_else(|| {
|
||||
"No persisted beacon chain found in store. Try deleting the .lighthouse/beacon dir."
|
||||
"No persisted beacon chain found in store. Try purging the beacon chain database."
|
||||
.to_string()
|
||||
})?;
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
use beacon_chain::builder::PUBKEY_CACHE_FILENAME;
|
||||
use network::NetworkConfig;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
@ -11,6 +12,9 @@ const TESTNET_SPEC_CONSTANTS: &str = "minimal";
|
||||
/// Default directory name for the freezer database under the top-level data dir.
|
||||
const DEFAULT_FREEZER_DB_DIR: &str = "freezer_db";
|
||||
|
||||
/// Trap file indicating if chain_db was purged
|
||||
const CHAIN_DB_PURGED_TRAP_FILE: &str = ".db_purged";
|
||||
|
||||
/// Defines how the client should initialize the `BeaconChain` and other components.
|
||||
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum ClientGenesis {
|
||||
@ -97,6 +101,68 @@ impl Config {
|
||||
.map(|data_dir| data_dir.join(&self.db_name))
|
||||
}
|
||||
|
||||
/// Get the path of the chain db purged trap file
|
||||
pub fn get_db_purged_trap_file_path(&self) -> Option<PathBuf> {
|
||||
self.get_data_dir()
|
||||
.map(|data_dir| data_dir.join(CHAIN_DB_PURGED_TRAP_FILE))
|
||||
}
|
||||
|
||||
/// returns whether chain_db was recently purged
|
||||
pub fn chain_db_was_purged(&self) -> bool {
|
||||
self.get_db_purged_trap_file_path()
|
||||
.map_or(false, |trap_file| trap_file.exists())
|
||||
}
|
||||
|
||||
/// purges the chain_db and creates trap file
|
||||
pub fn purge_chain_db(&self) -> Result<(), String> {
|
||||
// create the trap file
|
||||
let trap_file = self
|
||||
.get_db_purged_trap_file_path()
|
||||
.ok_or("Failed to get trap file path".to_string())?;
|
||||
fs::File::create(trap_file)
|
||||
.map_err(|err| format!("Failed to create trap file: {}", err))?;
|
||||
|
||||
// remove the chain_db
|
||||
fs::remove_dir_all(
|
||||
self.get_db_path()
|
||||
.ok_or("Failed to get db_path".to_string())?,
|
||||
)
|
||||
.map_err(|err| format!("Failed to remove chain_db: {}", err))?;
|
||||
|
||||
// remove the freezer db
|
||||
fs::remove_dir_all(
|
||||
self.get_freezer_db_path()
|
||||
.ok_or("Failed to get freezer db path".to_string())?,
|
||||
)
|
||||
.map_err(|err| format!("Failed to remove chain_db: {}", err))?;
|
||||
|
||||
// also need to remove pubkey cache file if it exists
|
||||
let pubkey_cache_file = self
|
||||
.get_data_dir()
|
||||
.map(|data_dir| data_dir.join(PUBKEY_CACHE_FILENAME))
|
||||
.ok_or("Failed to get pubkey cache file path".to_string())?;
|
||||
if !pubkey_cache_file.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
fs::remove_file(pubkey_cache_file)
|
||||
.map_err(|err| format!("Failed to remove pubkey cache: {}", err))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// cleans up purge_db trap file
|
||||
pub fn cleanup_after_purge_db(&self) -> Result<(), String> {
|
||||
let trap_file = self
|
||||
.get_db_purged_trap_file_path()
|
||||
.ok_or("Failed to get trap file path".to_string())?;
|
||||
if !trap_file.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
fs::remove_file(trap_file).map_err(|err| format!("Failed to remove trap file: {}", err))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get the database path, creating it if necessary.
|
||||
pub fn create_db_path(&self) -> Result<PathBuf, String> {
|
||||
let db_path = self
|
||||
|
@ -309,4 +309,12 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
||||
.help("A file from which to read the state"))
|
||||
)
|
||||
)
|
||||
/*
|
||||
* The "purge" sub-command.
|
||||
*
|
||||
* Allows user to purge beacon database
|
||||
*/
|
||||
.subcommand(SubCommand::with_name("purge")
|
||||
.about("Purge the beacon chain database.")
|
||||
)
|
||||
}
|
||||
|
@ -189,15 +189,27 @@ pub fn get_config<E: EthSpec>(
|
||||
("testnet", Some(sub_cmd_args)) => {
|
||||
process_testnet_subcommand(&mut client_config, ð2_config, sub_cmd_args)?
|
||||
}
|
||||
("purge", _) => {
|
||||
client_config.purge_chain_db()?;
|
||||
println!("Successfully purged chain db");
|
||||
std::process::exit(0);
|
||||
}
|
||||
// No sub-command assumes a resume operation.
|
||||
_ => {
|
||||
// If no primary subcommand was given, start the beacon chain from an existing
|
||||
// database.
|
||||
client_config.genesis = ClientGenesis::Resume;
|
||||
|
||||
let db_path_exists: bool = match client_config.get_db_path() {
|
||||
Some(path) => path.exists(),
|
||||
None => false,
|
||||
};
|
||||
|
||||
// Whilst there is no large testnet or mainnet force the user to specify how they want
|
||||
// to start a new chain (e.g., from a genesis YAML file, another node, etc).
|
||||
if !client_config.data_dir.exists() {
|
||||
if !client_config.data_dir.exists()
|
||||
|| (!db_path_exists && client_config.chain_db_was_purged())
|
||||
{
|
||||
info!(
|
||||
log,
|
||||
"Starting from an empty database";
|
||||
@ -392,7 +404,8 @@ fn init_new_client<E: EthSpec>(
|
||||
///
|
||||
/// Returns an error if `self.data_dir` already exists.
|
||||
pub fn create_new_datadir(client_config: &ClientConfig, eth2_config: &Eth2Config) -> Result<()> {
|
||||
if client_config.data_dir.exists() {
|
||||
let rebuild_db = client_config.chain_db_was_purged();
|
||||
if client_config.data_dir.exists() && !rebuild_db {
|
||||
return Err(format!(
|
||||
"Data dir already exists at {:?}",
|
||||
client_config.data_dir
|
||||
@ -407,7 +420,9 @@ pub fn create_new_datadir(client_config: &ClientConfig, eth2_config: &Eth2Config
|
||||
($file: ident, $variable: ident) => {
|
||||
let file = client_config.data_dir.join($file);
|
||||
if file.exists() {
|
||||
return Err(format!("Datadir is not clean, {} exists.", $file));
|
||||
if !rebuild_db {
|
||||
return Err(format!("Datadir is not clean, {} exists.", $file));
|
||||
}
|
||||
} else {
|
||||
// Write the onfig to a TOML file in the datadir.
|
||||
write_to_file(client_config.data_dir.join($file), $variable)
|
||||
@ -418,6 +433,7 @@ pub fn create_new_datadir(client_config: &ClientConfig, eth2_config: &Eth2Config
|
||||
|
||||
write_to_file!(CLIENT_CONFIG_FILENAME, client_config);
|
||||
write_to_file!(ETH2_CONFIG_FILENAME, eth2_config);
|
||||
client_config.cleanup_after_purge_db()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user