consciousness/src/bin/dump-table.rs
Kent Overstreet ba4e01b6f3 store: add weight to index, index-only key matching
- KEY_TO_UUID now stores weight (30 bytes: uuid+type+ts+deleted+weight)
- UUID_OFFSETS changed to composite key for O(log n) max-offset lookup
- Add NODES_BY_TYPE index for efficient type+date range queries
- Add for_each_key_weight() to StoreView for index-only iteration
- match_seeds uses index-only path when content not needed
- Fix transaction consistency in ops (single txn for related updates)
- rebuild() now records all uuid→offset mappings for version history
- Backwards compatible: old index formats decoded with default weight

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2026-04-15 05:14:04 -04:00

105 lines
4.5 KiB
Rust

// Dump a redb table in text form
// Usage: dump-table <table-name>
// Tables: key_to_uuid, uuid_offsets, nodes_by_provenance, nodes_by_type, rels
use consciousness::store::{
memory_dir,
KEY_TO_UUID, UUID_OFFSETS, NODES_BY_PROVENANCE, NODES_BY_TYPE, RELS,
unpack_node_meta, unpack_provenance_value, unpack_rel,
};
use redb::{Database, ReadableDatabase, ReadableTable, ReadableMultimapTable};
fn format_uuid(uuid: &[u8; 16]) -> String {
format!("{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15])
}
fn main() {
let args: Vec<String> = std::env::args().collect();
if args.len() != 2 {
eprintln!("usage: dump-table <table-name>");
eprintln!("tables: key_to_uuid, uuid_offsets, nodes_by_provenance, nodes_by_type, rels");
std::process::exit(1);
}
let table_name = &args[1];
let db_path = memory_dir().join("index.redb");
let db = Database::open(&db_path).expect("open db");
let txn = db.begin_read().expect("begin read");
match table_name.as_str() {
"key_to_uuid" => {
let table = txn.open_table(KEY_TO_UUID).expect("open");
for entry in table.iter().expect("iter") {
let (key, data) = entry.expect("entry");
let (uuid, node_type, ts, deleted, weight) = unpack_node_meta(data.value());
println!("{}\t{}\ttype={}\tts={}\tdel={}\tw={:.3}", key.value(), format_uuid(&uuid), node_type, ts, deleted, weight);
}
}
"uuid_offsets" => {
// Key: [uuid:16][offset:8 BE], Value: ()
let table = txn.open_table(UUID_OFFSETS).expect("open");
for entry in table.iter().expect("iter") {
let (key_bytes, _) = entry.expect("entry");
let key = key_bytes.value();
if key.len() >= 24 {
let mut uuid = [0u8; 16];
uuid.copy_from_slice(&key[0..16]);
let offset = u64::from_be_bytes([
key[16], key[17], key[18], key[19],
key[20], key[21], key[22], key[23],
]);
println!("{}\t{}", format_uuid(&uuid), offset);
}
}
}
"nodes_by_provenance" => {
let table = txn.open_multimap_table(NODES_BY_PROVENANCE).expect("open");
for entry in table.iter().expect("iter") {
let (prov, values) = entry.expect("entry");
for val in values {
let (ts, uuid) = unpack_provenance_value(val.expect("val").value());
println!("{}\t{}\t{}", prov.value(), ts, format_uuid(&uuid));
}
}
}
"nodes_by_type" => {
// Key: [type:1][neg_timestamp:8], Value: uuid
let table = txn.open_table(NODES_BY_TYPE).expect("open");
for entry in table.iter().expect("iter") {
let (key_bytes, uuid_bytes) = entry.expect("entry");
let key = key_bytes.value();
let node_type = key[0];
let neg_ts = i64::from_be_bytes([key[1], key[2], key[3], key[4], key[5], key[6], key[7], key[8]]);
let ts = !neg_ts;
let mut uuid = [0u8; 16];
uuid.copy_from_slice(uuid_bytes.value());
println!("type={}\tts={}\t{}", node_type, ts, format_uuid(&uuid));
}
}
"rels" => {
let table = txn.open_multimap_table(RELS).expect("open");
for entry in table.iter().expect("iter") {
let (uuid_bytes, values) = entry.expect("entry");
let uuid = uuid_bytes.value();
let uuid_str = if uuid.len() >= 16 {
let mut arr = [0u8; 16];
arr.copy_from_slice(&uuid[..16]);
format_uuid(&arr)
} else {
format!("{:02x?}", uuid)
};
for val in values {
let (other, strength, rel_type, is_out) = unpack_rel(val.expect("val").value());
println!("{}\t{}\tstr={:.3}\ttype={}\tout={}",
uuid_str, format_uuid(&other), strength, rel_type, is_out);
}
}
}
_ => {
eprintln!("unknown table: {}", table_name);
std::process::exit(1);
}
}
}