forked from kent/consciousness
store: index ops take WriteTransaction, mutations batch properly
Index functions now take &WriteTransaction instead of &Database, allowing callers to batch multiple index operations in a single transaction. Store mutations (upsert, delete, rename, etc.) now begin_write/commit their own transactions, ensuring atomicity. - replay_relations uses single txn for all relation indexing - Store::db() exposes Database for callers needing txn control - Convenience wrappers open their own txn for simple cases Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
2548ca059d
commit
4696bb8b7d
5 changed files with 151 additions and 144 deletions
|
|
@ -16,7 +16,7 @@
|
|||
// To get key from uuid: UUID_OFFSETS → read_node_at_offset() → node.key
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use redb::{Database, MultimapTableDefinition, ReadableDatabase, ReadableTable, TableDefinition};
|
||||
use redb::{Database, MultimapTableDefinition, ReadableDatabase, ReadableTable, TableDefinition, WriteTransaction};
|
||||
use std::path::Path;
|
||||
|
||||
// Node tables
|
||||
|
|
@ -55,18 +55,14 @@ pub fn open_db(path: &Path) -> Result<Database> {
|
|||
}
|
||||
|
||||
/// Record a node's location in the index.
|
||||
pub fn index_node(db: &Database, key: &str, offset: u64, uuid: &[u8; 16]) -> Result<()> {
|
||||
let txn = db.begin_write()?;
|
||||
{
|
||||
let mut nodes_table = txn.open_table(NODES)?;
|
||||
let mut key_uuid_table = txn.open_table(KEY_TO_UUID)?;
|
||||
let mut uuid_offsets = txn.open_multimap_table(UUID_OFFSETS)?;
|
||||
pub fn index_node(txn: &WriteTransaction, key: &str, offset: u64, uuid: &[u8; 16]) -> Result<()> {
|
||||
let mut nodes_table = txn.open_table(NODES)?;
|
||||
let mut key_uuid_table = txn.open_table(KEY_TO_UUID)?;
|
||||
let mut uuid_offsets = txn.open_multimap_table(UUID_OFFSETS)?;
|
||||
|
||||
nodes_table.insert(key, offset)?;
|
||||
key_uuid_table.insert(key, uuid.as_slice())?;
|
||||
uuid_offsets.insert(uuid.as_slice(), offset)?;
|
||||
}
|
||||
txn.commit()?;
|
||||
nodes_table.insert(key, offset)?;
|
||||
key_uuid_table.insert(key, uuid.as_slice())?;
|
||||
uuid_offsets.insert(uuid.as_slice(), offset)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -113,17 +109,13 @@ pub fn get_offsets_for_uuid(db: &Database, uuid: &[u8; 16]) -> Result<Vec<u64>>
|
|||
}
|
||||
|
||||
/// Remove a node from the index (key mappings only; UUID history preserved).
|
||||
pub fn remove_node(db: &Database, key: &str, _uuid: &[u8; 16]) -> Result<()> {
|
||||
let txn = db.begin_write()?;
|
||||
{
|
||||
let mut nodes_table = txn.open_table(NODES)?;
|
||||
let mut key_uuid_table = txn.open_table(KEY_TO_UUID)?;
|
||||
// Note: UUID_OFFSETS is not cleared - preserves version history
|
||||
pub fn remove_node(txn: &WriteTransaction, key: &str) -> Result<()> {
|
||||
let mut nodes_table = txn.open_table(NODES)?;
|
||||
let mut key_uuid_table = txn.open_table(KEY_TO_UUID)?;
|
||||
// Note: UUID_OFFSETS is not cleared - preserves version history
|
||||
|
||||
nodes_table.remove(key)?;
|
||||
key_uuid_table.remove(key)?;
|
||||
}
|
||||
txn.commit()?;
|
||||
nodes_table.remove(key)?;
|
||||
key_uuid_table.remove(key)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -165,47 +157,39 @@ pub fn unpack_rel(data: &[u8]) -> ([u8; 16], f32, u8, bool) {
|
|||
|
||||
/// Index a relation: store twice (once per endpoint).
|
||||
pub fn index_relation(
|
||||
db: &Database,
|
||||
txn: &WriteTransaction,
|
||||
source_uuid: &[u8; 16],
|
||||
target_uuid: &[u8; 16],
|
||||
strength: f32,
|
||||
rel_type: u8,
|
||||
) -> Result<()> {
|
||||
let txn = db.begin_write()?;
|
||||
{
|
||||
let mut rels = txn.open_multimap_table(RELS)?;
|
||||
let mut rels = txn.open_multimap_table(RELS)?;
|
||||
|
||||
// Store outgoing: source → (target, strength, type, true)
|
||||
let outgoing = pack_rel(target_uuid, strength, rel_type, true);
|
||||
rels.insert(source_uuid.as_slice(), outgoing.as_slice())?;
|
||||
// Store outgoing: source → (target, strength, type, true)
|
||||
let outgoing = pack_rel(target_uuid, strength, rel_type, true);
|
||||
rels.insert(source_uuid.as_slice(), outgoing.as_slice())?;
|
||||
|
||||
// Store incoming: target → (source, strength, type, false)
|
||||
let incoming = pack_rel(source_uuid, strength, rel_type, false);
|
||||
rels.insert(target_uuid.as_slice(), incoming.as_slice())?;
|
||||
}
|
||||
txn.commit()?;
|
||||
// Store incoming: target → (source, strength, type, false)
|
||||
let incoming = pack_rel(source_uuid, strength, rel_type, false);
|
||||
rels.insert(target_uuid.as_slice(), incoming.as_slice())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove a relation from the index.
|
||||
pub fn remove_relation(
|
||||
db: &Database,
|
||||
txn: &WriteTransaction,
|
||||
source_uuid: &[u8; 16],
|
||||
target_uuid: &[u8; 16],
|
||||
strength: f32,
|
||||
rel_type: u8,
|
||||
) -> Result<()> {
|
||||
let txn = db.begin_write()?;
|
||||
{
|
||||
let mut rels = txn.open_multimap_table(RELS)?;
|
||||
let mut rels = txn.open_multimap_table(RELS)?;
|
||||
|
||||
let outgoing = pack_rel(target_uuid, strength, rel_type, true);
|
||||
rels.remove(source_uuid.as_slice(), outgoing.as_slice())?;
|
||||
let outgoing = pack_rel(target_uuid, strength, rel_type, true);
|
||||
rels.remove(source_uuid.as_slice(), outgoing.as_slice())?;
|
||||
|
||||
let incoming = pack_rel(source_uuid, strength, rel_type, false);
|
||||
rels.remove(target_uuid.as_slice(), incoming.as_slice())?;
|
||||
}
|
||||
txn.commit()?;
|
||||
let incoming = pack_rel(source_uuid, strength, rel_type, false);
|
||||
rels.remove(target_uuid.as_slice(), incoming.as_slice())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue