///|
pub fn retention_plan(request : Value) -> Value raise {
let snapshots = arr(get(request, "snapshots"))
let by_id : Map[String, Value] = Map([])
let objects : Map[String, Value] = Map([])
for entry in snapshots {
let id = str(get(entry, "id"))
if id == "" || by_id.contains(id) {
raise InputError("duplicate or empty snapshot identity")
}
let snapshot = get(entry, "snapshot")
if get(audit_snapshot(snapshot), "valid") != Bool(true) {
raise InputError("retention refuses a corrupt snapshot")
}
for hash, raw in obj(get(snapshot, "objects")) {
if digest(decode_bytes(raw)) != hash {
raise InputError("retention refuses corrupt unreferenced content")
}
match objects.get(hash) {
Some(existing) =>
if existing != raw {
raise InputError("inconsistent shared content")
}
None => objects[hash] = raw
}
}
by_id[id] = snapshot
}
let retained = if get(request, "keep") == Null {
by_id.keys().collect()
} else {
string_list(get(request, "keep"))
}
let selected : Map[String, Bool] = Map([])
let reachable : Map[String, Bool] = Map([])
for id in retained {
if selected.contains(id) || !by_id.contains(id) {
raise InputError("duplicate or unknown retained snapshot")
}
selected[id] = true
for file in manifest(by_id[id]) {
reachable[str(get(file, "digest"))] = true
}
}
let kept : Array[String] = []
let collectible : Array[String] = []
let mut live_bytes = 0.0
let mut collectible_bytes = 0.0
for hash, bytes in objects {
let size = arr(bytes).length().to_double()
if reachable.contains(hash) {
kept.push(hash)
live_bytes += size
} else {
collectible.push(hash)
collectible_bytes += size
}
}
kept.sort()
collectible.sort()
let kept_snapshots = selected.keys().collect()
kept_snapshots.sort()
let dropped = by_id.keys().filter(fn(id) { !selected.contains(id) }).collect()
dropped.sort()
record([
("keep_snapshots", strings(kept_snapshots)),
("drop_snapshots", strings(dropped)),
("reachable_objects", strings(kept)),
("collectible_objects", strings(collectible)),
("live_bytes", Number(live_bytes)),
("collectible_bytes", Number(collectible_bytes)),
("plan_only", Bool(true)),
(
"scope",
String(
"objects supplied by these self-contained snapshots; no files are deleted",
),
),
])
}