bg var operation on all nodes at once

This commit is contained in:
Alex Auvolat 2023-01-04 13:25:57 +01:00
parent f3f27293df
commit 29dbcb8278
No known key found for this signature in database
GPG key ID: 0E496D15096376BE
4 changed files with 117 additions and 23 deletions

View file

@ -59,7 +59,7 @@ pub enum AdminRpc {
HashMap<usize, garage_util::background::WorkerInfo>, HashMap<usize, garage_util::background::WorkerInfo>,
WorkerListOpt, WorkerListOpt,
), ),
WorkerVars(Vec<(String, String)>), WorkerVars(Vec<(Uuid, String, String)>),
WorkerInfo(usize, garage_util::background::WorkerInfo), WorkerInfo(usize, garage_util::background::WorkerInfo),
BlockErrorList(Vec<BlockResyncErrorInfo>), BlockErrorList(Vec<BlockResyncErrorInfo>),
BlockInfo { BlockInfo {
@ -943,27 +943,101 @@ impl AdminRpcHandler {
.clone(); .clone();
Ok(AdminRpc::WorkerInfo(*tid, info)) Ok(AdminRpc::WorkerInfo(*tid, info))
} }
WorkerOperation::Get { variable } => { WorkerOperation::Get {
all_nodes,
variable,
} => self.handle_get_var(*all_nodes, variable).await,
WorkerOperation::Set {
all_nodes,
variable,
value,
} => self.handle_set_var(*all_nodes, variable, value).await,
}
}
async fn handle_get_var(
&self,
all_nodes: bool,
variable: &Option<String>,
) -> Result<AdminRpc, Error> {
if all_nodes {
let mut ret = vec![];
let ring = self.garage.system.ring.borrow().clone();
for node in ring.layout.node_ids().iter() {
let node = (*node).into();
match self
.endpoint
.call(
&node,
AdminRpc::Worker(WorkerOperation::Get {
all_nodes: false,
variable: variable.clone(),
}),
PRIO_NORMAL,
)
.await??
{
AdminRpc::WorkerVars(v) => ret.extend(v),
m => return Err(GarageError::unexpected_rpc_message(m).into()),
}
}
Ok(AdminRpc::WorkerVars(ret))
} else {
#[allow(clippy::collapsible_else_if)]
if let Some(v) = variable { if let Some(v) = variable {
Ok(AdminRpc::WorkerVars(vec![( Ok(AdminRpc::WorkerVars(vec![(
self.garage.system.id,
v.clone(), v.clone(),
self.garage.bg_vars.get(&v)?, self.garage.bg_vars.get(v)?,
)])) )]))
} else { } else {
let mut vars = self.garage.bg_vars.get_all();
vars.sort();
Ok(AdminRpc::WorkerVars( Ok(AdminRpc::WorkerVars(
self.garage vars.into_iter()
.bg_vars .map(|(k, v)| (self.garage.system.id, k.to_string(), v))
.get_all()
.into_iter()
.map(|(k, v)| (k.to_string(), v))
.collect(), .collect(),
)) ))
} }
} }
WorkerOperation::Set { variable, value } => {
self.garage.bg_vars.set(&variable, &value)?;
Ok(AdminRpc::Ok(format!("{} was set to {}", variable, value)))
} }
async fn handle_set_var(
&self,
all_nodes: bool,
variable: &str,
value: &str,
) -> Result<AdminRpc, Error> {
if all_nodes {
let mut ret = vec![];
let ring = self.garage.system.ring.borrow().clone();
for node in ring.layout.node_ids().iter() {
let node = (*node).into();
match self
.endpoint
.call(
&node,
AdminRpc::Worker(WorkerOperation::Set {
all_nodes: false,
variable: variable.to_string(),
value: value.to_string(),
}),
PRIO_NORMAL,
)
.await??
{
AdminRpc::WorkerVars(v) => ret.extend(v),
m => return Err(GarageError::unexpected_rpc_message(m).into()),
}
}
Ok(AdminRpc::WorkerVars(ret))
} else {
self.garage.bg_vars.set(variable, value)?;
Ok(AdminRpc::WorkerVars(vec![(
self.garage.system.id,
variable.to_string(),
value.to_string(),
)]))
} }
} }

View file

@ -519,10 +519,24 @@ pub enum WorkerOperation {
Info { tid: usize }, Info { tid: usize },
/// Get worker parameter /// Get worker parameter
#[structopt(name = "get", version = garage_version())] #[structopt(name = "get", version = garage_version())]
Get { variable: Option<String> }, Get {
/// Gather variable values from all nodes
#[structopt(short = "a", long = "all-nodes")]
all_nodes: bool,
/// Variable name to get, or none to get all variables
variable: Option<String>,
},
/// Set worker parameter /// Set worker parameter
#[structopt(name = "set", version = garage_version())] #[structopt(name = "set", version = garage_version())]
Set { variable: String, value: String }, Set {
/// Set variable values on all nodes
#[structopt(short = "a", long = "all-nodes")]
all_nodes: bool,
/// Variable node to set
variable: String,
/// Value to set the variable to
value: String,
},
} }
#[derive(Serialize, Deserialize, StructOpt, Debug, Eq, PartialEq, Clone, Copy)] #[derive(Serialize, Deserialize, StructOpt, Debug, Eq, PartialEq, Clone, Copy)]

View file

@ -357,10 +357,10 @@ pub fn print_worker_info(tid: usize, info: WorkerInfo) {
format_table(table); format_table(table);
} }
pub fn print_worker_vars(wv: Vec<(String, String)>) { pub fn print_worker_vars(wv: Vec<(Uuid, String, String)>) {
let table = wv let table = wv
.into_iter() .into_iter()
.map(|(k, v)| format!("{}\t{}", k, v)) .map(|(n, k, v)| format!("{:?}\t{}\t{}", n, k, v))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
format_table(table); format_table(table);
} }

View file

@ -71,6 +71,12 @@ impl BgVars {
} }
} }
impl Default for BgVars {
fn default() -> Self {
Self::new()
}
}
// ---- // ----
trait BgVarTrait: Send + Sync + 'static { trait BgVarTrait: Send + Sync + 'static {