use crate::stores::Registry;
use clap::ValueHint::FilePath;
use clap::{Args, Parser, Subcommand};
use log::debug;
use std::fs::read_to_string;
use std::sync::mpsc::channel;
#[derive(Args, Debug)]
struct BenchArgs {
#[arg(short = 's')]
#[arg(value_hint = FilePath)]
#[arg(help = "Path to the key-value store's TOML config file")]
store_config: String,
#[arg(short = 'b')]
#[arg(value_hint = FilePath)]
#[arg(help = "Path to the benchmark's TOML config file")]
benchmark_config: String,
}
#[derive(Args, Debug)]
struct ServerArgs {
#[arg(short = 'a', default_value = "0.0.0.0")]
#[arg(help = "Bind address")]
host: String,
#[arg(short = 'p', default_value = "9000")]
#[arg(help = "Bind port")]
port: String,
#[arg(short = 's')]
#[arg(value_hint = FilePath)]
#[arg(help = "Path to the key-value store's TOML config file")]
store_config: String,
#[arg(short = 'n', default_value_t = 1)]
#[arg(help = "Number of worker threads")]
workers: usize,
}
#[derive(Parser, Debug)]
#[command(version, about)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand, Debug)]
enum Commands {
#[command(about = "Run a benchmark")]
Bench(BenchArgs),
#[command(about = "Start a key-value server")]
Server(ServerArgs),
#[command(about = "List all registered key-value stores")]
List,
}
fn bench_cli(args: &BenchArgs) {
let opt: String = {
let s = args.store_config.clone();
let b = args.benchmark_config.clone();
read_to_string(s.as_str()).unwrap() + "\n" + &read_to_string(b.as_str()).unwrap()
};
let (map, phases) = crate::bench::init(&opt);
map.bench(&phases);
}
fn server_cli(args: &ServerArgs) {
let host = &args.host;
let port = &args.port;
let nr_workers = args.workers;
let opt: String = read_to_string(args.store_config.as_str()).unwrap();
let map = crate::server::init(&opt);
let (stop_tx, stop_rx) = channel();
let (grace_tx, grace_rx) = channel();
ctrlc::set_handler(move || {
assert!(stop_tx.send(()).is_ok());
debug!("SIGINT received and stop message sent to server");
})
.expect("Error setting Ctrl-C handler for server");
map.server(&host, &port, nr_workers, stop_rx, grace_tx);
assert!(grace_rx.recv().is_ok());
debug!("All server threads have been shut down gracefully, exit");
}
fn list_cli() {
for r in inventory::iter::<Registry> {
println!("Registered map: {}", r.name);
}
}
pub fn cmdline() {
env_logger::init();
let cli = Cli::parse();
debug!("Starting kvbench with args: {:?}", cli);
match cli.command {
Commands::Bench(args) => bench_cli(&args),
Commands::Server(args) => server_cli(&args),
Commands::List => list_cli(),
}
}