datastore: add new Lookup for operations tracking
We sometimes need to do some in-memory only stuff, e.g., to check if GC is already running for a datastore, which is a try_lock on a mutex that is in-memory. Actually the whole thing would be nicer if we could guarantee to hold the correct contract statically, e.g., like https://docs.rust-embedded.org/book/static-guarantees/design-contracts.html Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
parent
d4d730e589
commit
0408f60b58
|
@ -20,8 +20,17 @@ pub const MAINTENANCE_MESSAGE_SCHEMA: Schema =
|
|||
#[derive(Clone, Copy, Debug)]
|
||||
/// Operation requirements, used when checking for maintenance mode.
|
||||
pub enum Operation {
|
||||
/// for any read operation like backup restore or RRD metric collection
|
||||
Read,
|
||||
/// for any write/delete operation, like backup create or GC
|
||||
Write,
|
||||
/// for any purely logical operation on the in-memory state of the datastore, e.g., to check if
|
||||
/// some mutex could be locked (e.g., GC already running?)
|
||||
///
|
||||
/// NOTE: one must *not* do any IO operations when only helding this Op state
|
||||
Lookup,
|
||||
|
||||
// GarbageCollect or Delete?
|
||||
}
|
||||
|
||||
#[api]
|
||||
|
@ -29,6 +38,12 @@ pub enum Operation {
|
|||
#[serde(rename_all = "kebab-case")]
|
||||
/// Maintenance type.
|
||||
pub enum MaintenanceType {
|
||||
// TODO:
|
||||
// - Add "unmounting" once we got pluggable datastores
|
||||
// - Add "GarbageCollection" or "DeleteOnly" as type and track GC (or all deletes) as separate
|
||||
// operation, so that one can enable a mode where nothing new can be added but stuff can be
|
||||
// cleaned
|
||||
|
||||
/// Only read operations are allowed on the datastore.
|
||||
ReadOnly,
|
||||
/// Neither read nor write operations are allowed on the datastore.
|
||||
|
@ -65,7 +80,9 @@ impl MaintenanceMode {
|
|||
.decode_utf8()
|
||||
.unwrap_or(Cow::Borrowed(""));
|
||||
|
||||
if self.ty == MaintenanceType::Offline {
|
||||
if let Some(Operation::Lookup) = operation {
|
||||
return Ok(());
|
||||
} else if self.ty == MaintenanceType::Offline {
|
||||
bail!("offline maintenance mode: {}", message);
|
||||
} else if self.ty == MaintenanceType::ReadOnly {
|
||||
if let Some(Operation::Write) = operation {
|
||||
|
|
|
@ -133,7 +133,7 @@ impl DataStore {
|
|||
|
||||
if let Some(maintenance_mode) = config.get_maintenance_mode() {
|
||||
if let Err(error) = maintenance_mode.check(operation) {
|
||||
bail!("datastore '{}' is in {}", name, error);
|
||||
bail!("datastore '{name}' is in {error}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ pub fn update_active_operations(name: &str, operation: Operation, count: i64) ->
|
|||
match operation {
|
||||
Operation::Read => task.active_operations.read += count,
|
||||
Operation::Write => task.active_operations.write += count,
|
||||
Operation::Lookup => (), // no IO must happen there
|
||||
};
|
||||
}
|
||||
Some(task.clone())
|
||||
|
@ -98,6 +99,7 @@ pub fn update_active_operations(name: &str, operation: Operation, count: i64) ->
|
|||
active_operations: match operation {
|
||||
Operation::Read => ActiveOperationStats { read: 1, write: 0 },
|
||||
Operation::Write => ActiveOperationStats { read: 0, write: 1 },
|
||||
Operation::Lookup => ActiveOperationStats { read: 0, write: 0 },
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue