diff --git a/Cargo.lock b/Cargo.lock index 5ed30e2c5e..c7118ed9ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1085,6 +1085,17 @@ dependencies = [ "ieee754", ] +[[package]] +name = "fd-lock" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15bec795244d49f5ee3024bdc6c3883fb035f7f6601d4a4821c3d5d60784454" +dependencies = [ + "failure", + "libc", + "winapi 0.3.8", +] + [[package]] name = "feature-probe" version = "0.1.1" @@ -5096,6 +5107,7 @@ dependencies = [ "chrono", "clap", "console", + "fd-lock", "indicatif", "libc", "log 0.4.11", diff --git a/install/Cargo.toml b/install/Cargo.toml index 80d63cd1d5..f5e83c56f1 100644 --- a/install/Cargo.toml +++ b/install/Cargo.toml @@ -39,13 +39,5 @@ url = "2.1.1" winapi = "0.3.8" winreg = "0.7" -[[bin]] -name = "solana-install" -path = "src/main-install.rs" - -[[bin]] -name = "solana-install-init" -path = "src/main-install-init.rs" - [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/install/src/main-install-init.rs b/install/src/bin/solana-install-init.rs similarity index 100% rename from install/src/main-install-init.rs rename to install/src/bin/solana-install-init.rs diff --git a/install/src/main-install.rs b/install/src/main.rs similarity index 100% rename from install/src/main-install.rs rename to install/src/main.rs diff --git a/validator/Cargo.toml b/validator/Cargo.toml index af5e001398..6df49f32e6 100644 --- a/validator/Cargo.toml +++ b/validator/Cargo.toml @@ -14,6 +14,7 @@ base64 = "0.12.3" clap = "2.33.1" chrono = { version = "0.4.11", features = ["serde"] } console = "0.11.3" +fd-lock = "1.1.1" indicatif = "0.15.0" log = "0.4.11" rand = "0.7.0" diff --git a/validator/src/bin/solana-test-validator.rs b/validator/src/bin/solana-test-validator.rs index a57b07c83f..e0baaf215e 100644 --- a/validator/src/bin/solana-test-validator.rs +++ b/validator/src/bin/solana-test-validator.rs @@ -1,6 +1,7 @@ use { clap::{value_t_or_exit, App, Arg}, console::style, + fd_lock::FdLock, indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle}, solana_clap_utils::{input_parsers::pubkey_of, input_validators::is_pubkey}, solana_client::{client_error, rpc_client::RpcClient}, @@ -18,9 +19,9 @@ use { }, solana_validator::{start_logger, test_validator::*}, std::{ - fs, + fs, io, net::{IpAddr, Ipv4Addr, SocketAddr}, - path::PathBuf, + path::{Path, PathBuf}, process::exit, sync::mpsc::channel, thread, @@ -90,6 +91,16 @@ fn main() { .default_value("test-ledger") .help("Use DIR as ledger location"), ) + .arg( + Arg::with_name("reset") + .short("r") + .long("reset") + .takes_value(false) + .help( + "Reset the ledger to genesis if it exists. \ + By default the validator will resume an existing ledger (if present)", + ), + ) .arg( Arg::with_name("quiet") .short("q") @@ -144,6 +155,7 @@ fn main() { }); let ledger_path = value_t_or_exit!(matches, "ledger_path", PathBuf); + let reset_ledger = matches.is_present("reset"); let output = if matches.is_present("quiet") { Output::None } else if matches.is_present("log") { @@ -188,19 +200,35 @@ fn main() { } } + if !ledger_path.exists() { + fs::create_dir(&ledger_path).unwrap_or_else(|err| { + eprintln!( + "Error: Unable to create directory {}: {}", + ledger_path.display(), + err + ); + exit(1); + }); + } + + let mut ledger_fd_lock = FdLock::new(fs::File::open(&ledger_path).unwrap()); + let _ledger_lock = ledger_fd_lock.try_lock().unwrap_or_else(|_| { + eprintln!( + "Error: Unable to lock {} directory. Check if another solana-test-validator is running", + ledger_path.display() + ); + exit(1); + }); + + if reset_ledger { + remove_directory_contents(&ledger_path).unwrap_or_else(|err| { + eprintln!("Error: Unable to remove {}: {}", ledger_path.display(), err); + exit(1); + }) + } + let validator_log_symlink = ledger_path.join("validator.log"); let logfile = if output != Output::Log { - if !ledger_path.exists() { - fs::create_dir(&ledger_path).unwrap_or_else(|err| { - eprintln!( - "Error: Unable to create directory {}: {}", - ledger_path.display(), - err - ); - exit(1); - }) - } - let validator_log_with_timestamp = format!( "validator-{}.log", SystemTime::now() @@ -330,3 +358,16 @@ fn main() { std::thread::park(); } + +fn remove_directory_contents(ledger_path: &Path) -> Result<(), io::Error> { + for entry in fs::read_dir(&ledger_path)? { + let entry = entry?; + println!("emove {}:", entry.path().display()); + if entry.metadata()?.is_file() { + fs::remove_file(&entry.path())? + } else { + fs::remove_dir_all(&entry.path())? + } + } + Ok(()) +}