57 lines
2 KiB
Rust
57 lines
2 KiB
Rust
|
|
// Find all deleted nodes that have no subsequent non-deleted version
|
||
|
|
// (i.e., nodes that are currently dead).
|
||
|
|
//
|
||
|
|
// Also checks: is there a live node under the same key with a different UUID?
|
||
|
|
// If not, the deletion was terminal — the node is gone.
|
||
|
|
|
||
|
|
use std::collections::HashMap;
|
||
|
|
use std::io::BufReader;
|
||
|
|
use std::fs;
|
||
|
|
use capnp::{message, serialize};
|
||
|
|
use poc_memory::memory_capnp;
|
||
|
|
use poc_memory::store::Node;
|
||
|
|
|
||
|
|
fn main() {
|
||
|
|
let path = std::env::args().nth(1)
|
||
|
|
.unwrap_or_else(|| {
|
||
|
|
let dir = poc_memory::store::nodes_path();
|
||
|
|
dir.to_string_lossy().to_string()
|
||
|
|
});
|
||
|
|
|
||
|
|
let file = fs::File::open(&path).unwrap();
|
||
|
|
let mut reader = BufReader::new(file);
|
||
|
|
|
||
|
|
// Collect ALL entries, tracking latest version per key
|
||
|
|
let mut latest_by_key: HashMap<String, Node> = HashMap::new();
|
||
|
|
let mut all_entries = 0u64;
|
||
|
|
|
||
|
|
while let Ok(msg) = serialize::read_message(&mut reader, message::ReaderOptions::new()) {
|
||
|
|
let log = msg.get_root::<memory_capnp::node_log::Reader>().unwrap();
|
||
|
|
for node_reader in log.get_nodes().unwrap() {
|
||
|
|
all_entries += 1;
|
||
|
|
let node = Node::from_capnp_migrate(node_reader).unwrap();
|
||
|
|
let dominated = latest_by_key.get(&node.key)
|
||
|
|
.map(|n| node.version >= n.version)
|
||
|
|
.unwrap_or(true);
|
||
|
|
if dominated {
|
||
|
|
latest_by_key.insert(node.key.clone(), node);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Find keys where the latest version is deleted
|
||
|
|
let mut dead: Vec<&Node> = latest_by_key.values()
|
||
|
|
.filter(|n| n.deleted)
|
||
|
|
.collect();
|
||
|
|
dead.sort_by(|a, b| a.key.cmp(&b.key));
|
||
|
|
|
||
|
|
eprintln!("Scanned {} entries, {} unique keys", all_entries, latest_by_key.len());
|
||
|
|
eprintln!("{} live nodes, {} deleted (terminal tombstones)\n",
|
||
|
|
latest_by_key.len() - dead.len(), dead.len());
|
||
|
|
|
||
|
|
for node in &dead {
|
||
|
|
println!("{:<60} v{:<4} {}b prov={}",
|
||
|
|
node.key, node.version, node.content.len(), node.provenance);
|
||
|
|
}
|
||
|
|
}
|