Files
deusdata--codebase-memory-mcp/src/graph_buffer/graph_buffer.h
T
wehub-resource-sync 41cb1c0170
OpenSSF Scorecard / scorecard (push) Failing after 0s
DCO / dco (push) Failing after 0s
CodeQL SAST / analyze (push) Failing after 1s
Deploy Pages / deploy (push) Failing after 1s
chore: import upstream snapshot with attribution
2026-07-13 12:28:05 +08:00

179 lines
8.3 KiB
C

/*
* graph_buffer.h — In-memory graph buffer for pipeline indexing.
*
* Holds all nodes and edges in RAM during indexing, then dumps to SQLite.
* Provides O(1) node lookup by qualified name and edge dedup by key.
*
* Depends on: foundation (hash_table, dyn_array), store (data structs)
*/
#ifndef CBM_GRAPH_BUFFER_H
#define CBM_GRAPH_BUFFER_H
#include <stdbool.h>
#include <stdint.h>
#include <stdatomic.h>
/* ── Opaque handle ──────────────────────────────────────────────── */
typedef struct cbm_gbuf cbm_gbuf_t;
/* Forward declare store for dump path */
typedef struct cbm_store cbm_store_t;
/* ── Node / Edge structs (owned by the buffer) ───────────────────── */
typedef struct {
int64_t id; /* temp ID (sequential from 1) */
char *label; /* heap-owned */
char *name; /* heap-owned */
char *qualified_name; /* heap-owned */
char *file_path; /* heap-owned */
int start_line;
int end_line;
char *properties_json; /* heap-owned JSON string, "{}" default */
} cbm_gbuf_node_t;
typedef struct {
int64_t id; /* temp ID */
int64_t source_id; /* temp node ID */
int64_t target_id; /* temp node ID */
char *type; /* heap-owned */
char *properties_json; /* heap-owned JSON string, "{}" default */
} cbm_gbuf_edge_t;
/* ── Lifecycle ──────────────────────────────────────────────────── */
/* Create a new graph buffer for a project. */
cbm_gbuf_t *cbm_gbuf_new(const char *project, const char *root_path);
/* Create a graph buffer with a shared atomic ID source.
* IDs are allocated via atomic_fetch_add on *id_source.
* Used for parallel extraction where multiple gbufs need unique IDs.
* If id_source is NULL, behaves like cbm_gbuf_new(). */
cbm_gbuf_t *cbm_gbuf_new_shared_ids(const char *project, const char *root_path,
_Atomic int64_t *id_source);
/* Free the graph buffer and all owned data. NULL-safe. */
void cbm_gbuf_free(cbm_gbuf_t *gb);
/* Merge all nodes and edges from src into dst.
* Nodes are merged by QN: on collision, src wins (updates dst node fields).
* New nodes are inserted with their original IDs (from shared ID source).
* Edges are remapped for any QN-colliding nodes, then inserted with dedup.
* After merge, src can be safely freed (all data is copied).
* Returns 0 on success, -1 on error. */
int cbm_gbuf_merge(cbm_gbuf_t *dst, cbm_gbuf_t *src);
/* ── Node operations ─────────────────────────────────────────────── */
/* Upsert a node by qualified name. Returns the temp ID.
* All string fields are copied (buffer owns the copies).
* Returns 0 on error. */
int64_t cbm_gbuf_upsert_node(cbm_gbuf_t *gb, const char *label, const char *name,
const char *qualified_name, const char *file_path, int start_line,
int end_line, const char *properties_json);
/* Find a node by qualified name. Returns NULL if not found. */
const cbm_gbuf_node_t *cbm_gbuf_find_by_qn(const cbm_gbuf_t *gb, const char *qn);
/* Find a node by temp ID. Returns NULL if not found. */
const cbm_gbuf_node_t *cbm_gbuf_find_by_id(const cbm_gbuf_t *gb, int64_t id);
/* Find nodes by label. Sets *out and *count. Caller does NOT free.
* Returns 0 on success, -1 on error. */
int cbm_gbuf_find_by_label(const cbm_gbuf_t *gb, const char *label, const cbm_gbuf_node_t ***out,
int *count);
/* Find nodes by name (exact). Sets *out and *count. Caller does NOT free. */
int cbm_gbuf_find_by_name(const cbm_gbuf_t *gb, const char *name, const cbm_gbuf_node_t ***out,
int *count);
/* Count total nodes in buffer. */
int cbm_gbuf_node_count(const cbm_gbuf_t *gb);
/* Get the next ID that would be assigned. Used to initialize shared atomic counters. */
int64_t cbm_gbuf_next_id(const cbm_gbuf_t *gb);
/* Set the next ID counter. Used after merging worker gbufs to sync the main counter. */
void cbm_gbuf_set_next_id(cbm_gbuf_t *gb, int64_t next_id);
/* Delete all nodes with a label. Cascade-deletes referencing edges. */
int cbm_gbuf_delete_by_label(cbm_gbuf_t *gb, const char *label);
/* Delete all nodes for a given file path. Cascade-deletes referencing edges.
* Used by incremental indexing to remove stale nodes before re-extraction. */
int cbm_gbuf_delete_by_file(cbm_gbuf_t *gb, const char *file_path);
/* Bulk-load all nodes and edges for a project from an existing SQLite DB
* into this graph buffer. Returns 0 on success. */
int cbm_gbuf_load_from_db(cbm_gbuf_t *gb, const char *db_path, const char *project);
/* Iterate all live nodes (not deleted from QN index). */
typedef void (*cbm_gbuf_node_visitor_fn)(const cbm_gbuf_node_t *node, void *userdata);
void cbm_gbuf_foreach_node(const cbm_gbuf_t *gb, cbm_gbuf_node_visitor_fn fn, void *userdata);
/* Iterate all edges. */
typedef void (*cbm_gbuf_edge_visitor_fn)(const cbm_gbuf_edge_t *edge, void *userdata);
void cbm_gbuf_foreach_edge(const cbm_gbuf_t *gb, cbm_gbuf_edge_visitor_fn fn, void *userdata);
/* ── Edge operations ─────────────────────────────────────────────── */
/* Insert an edge. Deduplicates by (source_id, target_id, type).
* On duplicate, merges properties (later wins). Returns edge temp ID.
* Returns 0 on error. */
int64_t cbm_gbuf_insert_edge(cbm_gbuf_t *gb, int64_t source_id, int64_t target_id, const char *type,
const char *properties_json);
/* Find edges from source_id with given type.
* Sets *out and *count. Caller does NOT free. */
int cbm_gbuf_find_edges_by_source_type(const cbm_gbuf_t *gb, int64_t source_id, const char *type,
const cbm_gbuf_edge_t ***out, int *count);
/* Find edges to target_id with given type. */
int cbm_gbuf_find_edges_by_target_type(const cbm_gbuf_t *gb, int64_t target_id, const char *type,
const cbm_gbuf_edge_t ***out, int *count);
/* Find all edges of a given type. */
int cbm_gbuf_find_edges_by_type(const cbm_gbuf_t *gb, const char *type,
const cbm_gbuf_edge_t ***out, int *count);
/* Count total edges. */
int cbm_gbuf_edge_count(const cbm_gbuf_t *gb);
/* Count edges of a given type. */
int cbm_gbuf_edge_count_by_type(const cbm_gbuf_t *gb, const char *type);
/* Delete all edges of a type. */
int cbm_gbuf_delete_edges_by_type(cbm_gbuf_t *gb, const char *type);
/* ── Vector storage (for semantic embeddings) ───────────────────── */
/* Store an int8-quantized vector for a node. The vector data is copied.
* Called by pass_semantic_edges after computing RI vectors.
* Vectors are carried through to cbm_write_db during the dump phase. */
int cbm_gbuf_store_vector(cbm_gbuf_t *gb, int64_t node_id, const uint8_t *vector, int vector_len);
/* Store an enriched token vector for query-time lookup.
* Called by pass_semantic_edges after corpus finalization.
* Token string and vector data are copied. */
int cbm_gbuf_store_token_vector(cbm_gbuf_t *gb, const char *token, const uint8_t *vector,
int vector_len, float idf);
/* ── Dump to SQLite ──────────────────────────────────────────────── */
/* Dump the entire buffer to a SQLite file using the direct page writer.
* Assigns sequential final IDs and remaps edge references.
* Returns 0 on success, -1 on error. */
int cbm_gbuf_dump_to_sqlite(cbm_gbuf_t *gb, const char *path);
/* Flush the buffer to an existing store via the store API.
* Deletes existing project data first. Returns 0 on success. */
int cbm_gbuf_flush_to_store(cbm_gbuf_t *gb, cbm_store_t *store);
/* Merge the buffer into an existing store WITHOUT deleting existing data.
* Upserts nodes, inserts edges. Used for incremental indexing.
* Returns 0 on success. */
int cbm_gbuf_merge_into_store(cbm_gbuf_t *gb, cbm_store_t *store);
#endif /* CBM_GRAPH_BUFFER_H */