120 lines
3.7 KiB
Zig
120 lines
3.7 KiB
Zig
//! QVL Storage Layer - Stub Implementation
|
|
//!
|
|
//! This is a stub/mock implementation for testing without libmdbx.
|
|
//! Replace with real libmdbx implementation when available.
|
|
|
|
const std = @import("std");
|
|
const types = @import("types.zig");
|
|
|
|
const NodeId = types.NodeId;
|
|
const RiskEdge = types.RiskEdge;
|
|
const RiskGraph = types.RiskGraph;
|
|
|
|
/// Mock persistent storage using in-memory HashMap
|
|
pub const PersistentGraph = struct {
|
|
allocator: std.mem.Allocator,
|
|
nodes: std.AutoHashMap(NodeId, void),
|
|
edges: std.AutoHashMap(EdgeKey, RiskEdge),
|
|
adjacency: std.AutoHashMap(NodeId, std.ArrayList(NodeId)),
|
|
path: []const u8,
|
|
|
|
const EdgeKey = struct {
|
|
from: NodeId,
|
|
to: NodeId,
|
|
|
|
pub fn hash(self: EdgeKey) u64 {
|
|
return @as(u64, self.from) << 32 | self.to;
|
|
}
|
|
|
|
pub fn eql(self: EdgeKey, other: EdgeKey) bool {
|
|
return self.from == other.from and self.to == other.to;
|
|
}
|
|
};
|
|
|
|
const Self = @This();
|
|
|
|
/// Open or create persistent graph (mock: in-memory)
|
|
pub fn open(path: []const u8, config: DBConfig, allocator: std.mem.Allocator) !Self {
|
|
_ = config;
|
|
return Self{
|
|
.allocator = allocator,
|
|
.nodes = std.AutoHashMap(NodeId, void).init(allocator),
|
|
.edges = std.AutoHashMap(EdgeKey, RiskEdge).init(allocator),
|
|
.adjacency = std.AutoHashMap(NodeId, std.ArrayList(NodeId)).init(allocator),
|
|
.path = try allocator.dupe(u8, path),
|
|
};
|
|
}
|
|
|
|
/// Close database
|
|
pub fn close(self: *Self) void {
|
|
// Clean up adjacency lists
|
|
var it = self.adjacency.valueIterator();
|
|
while (it.next()) |list| {
|
|
list.deinit(self.allocator);
|
|
}
|
|
self.adjacency.deinit();
|
|
self.edges.deinit();
|
|
self.nodes.deinit();
|
|
self.allocator.free(self.path);
|
|
}
|
|
|
|
/// Add node
|
|
pub fn addNode(self: *Self, node: NodeId) !void {
|
|
try self.nodes.put(node, {});
|
|
}
|
|
|
|
/// Add edge
|
|
pub fn addEdge(self: *Self, edge: RiskEdge) !void {
|
|
const key = EdgeKey{ .from = edge.from, .to = edge.to };
|
|
try self.edges.put(key, edge);
|
|
|
|
// Update adjacency
|
|
const entry = try self.adjacency.getOrPut(edge.from);
|
|
if (!entry.found_existing) {
|
|
entry.value_ptr.* = .{}; // Empty ArrayList, allocator passed on append
|
|
}
|
|
try entry.value_ptr.append(self.allocator, edge.to);
|
|
}
|
|
|
|
/// Get outgoing neighbors
|
|
pub fn getOutgoing(self: *Self, node: NodeId, allocator: std.mem.Allocator) ![]NodeId {
|
|
if (self.adjacency.get(node)) |list| {
|
|
// Copy to new slice with provided allocator
|
|
return allocator.dupe(NodeId, list.items);
|
|
}
|
|
return allocator.dupe(NodeId, &[_]NodeId{});
|
|
}
|
|
|
|
/// Get specific edge
|
|
pub fn getEdge(self: *Self, from: NodeId, to: NodeId) !?RiskEdge {
|
|
const key = EdgeKey{ .from = from, .to = to };
|
|
return self.edges.get(key);
|
|
}
|
|
|
|
/// Load in-memory RiskGraph
|
|
pub fn toRiskGraph(self: *Self, allocator: std.mem.Allocator) !RiskGraph {
|
|
var graph = RiskGraph.init(allocator);
|
|
errdefer graph.deinit();
|
|
|
|
var it = self.edges.valueIterator();
|
|
while (it.next()) |edge| {
|
|
try graph.addEdge(edge.*);
|
|
}
|
|
|
|
return graph;
|
|
}
|
|
};
|
|
|
|
/// Database configuration (mock accepts same config for API compatibility)
|
|
pub const DBConfig = struct {
|
|
max_readers: u32 = 64,
|
|
max_dbs: u32 = 8,
|
|
map_size: usize = 10 * 1024 * 1024,
|
|
page_size: u32 = 4096,
|
|
};
|
|
|
|
// Re-export for integration.zig
|
|
pub const lmdb = struct {
|
|
// Stub exports
|
|
};
|