store: read nodes via index instead of HashMap

- Add get_node() and contains_key() methods that read via redb index
- Migrate all store/ reads to use index lookup
- Remove HashMap cache updates from mutations (write-through to capnp+index only)
- Remove replay_nodes() - load no longer builds HashMap
- Update db_is_healthy to validate by spot-checking offsets
- Fix set_weight bug: now persists weight changes to capnp

Store.nodes HashMap still exists for code outside store/ module,
but store/ itself no longer uses it.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
Kent Overstreet 2026-04-13 19:31:28 -04:00
commit 7eb86656d4
4 changed files with 167 additions and 112 deletions

View file

@ -1,6 +1,6 @@
// Read-only access abstraction for the memory store
use super::types::*;
use super::{capnp, index, types::*};
use super::Store;
// ---------------------------------------------------------------------------
@ -19,21 +19,42 @@ pub trait StoreView {
/// Node weight by key, or the default weight if missing.
fn node_weight(&self, key: &str) -> f64;
/// Node content by key.
fn node_content(&self, key: &str) -> Option<&str>;
}
impl StoreView for Store {
fn for_each_node<F: FnMut(&str, &str, f32)>(&self, mut f: F) {
for (key, node) in &self.nodes {
f(key, &node.content, node.weight);
let db = match self.db.as_ref() {
Some(db) => db,
None => return,
};
let keys = match index::all_keys(db) {
Ok(keys) => keys,
Err(_) => return,
};
for key in keys {
if let Ok(Some(offset)) = index::get_offset(db, &key) {
if let Ok(node) = capnp::read_node_at_offset(offset) {
f(&key, &node.content, node.weight);
}
}
}
}
fn for_each_node_meta<F: FnMut(&str, NodeType, i64)>(&self, mut f: F) {
for (key, node) in &self.nodes {
f(key, node.node_type, node.timestamp);
let db = match self.db.as_ref() {
Some(db) => db,
None => return,
};
let keys = match index::all_keys(db) {
Ok(keys) => keys,
Err(_) => return,
};
for key in keys {
if let Ok(Some(offset)) = index::get_offset(db, &key) {
if let Ok(node) = capnp::read_node_at_offset(offset) {
f(&key, node.node_type, node.timestamp);
}
}
}
}
@ -46,10 +67,10 @@ impl StoreView for Store {
fn node_weight(&self, key: &str) -> f64 {
let cfg = crate::config::get();
self.nodes.get(key).map(|n| n.weight as f64).unwrap_or(cfg.default_node_weight)
}
fn node_content(&self, key: &str) -> Option<&str> {
self.nodes.get(key).map(|n| n.content.as_str())
self.get_node(key)
.ok()
.flatten()
.map(|n| n.weight as f64)
.unwrap_or(cfg.default_node_weight)
}
}