1 const std = @import("std");
2 const lmdb = @import("lmdb");
6 pub fn Db(comptime K: type, comptime V: type) type {
12 pub fn init(txn: lmdb.Txn, name: [:0]const u8) !Self {
14 .dbi = try txn.dbi(name),
17 pub fn put(self: Self, k: K, v: V) !void {
18 try self.dbi.put(k, v);
20 pub fn get(self: Self, k: K) !V {
21 return try self.dbi.get(k, V);
23 pub fn del(self: Self, k: K) !void {
26 pub fn has(self: Self, k: K) !bool {
27 return try self.dbi.has(k);
29 pub const Iterator = struct {
30 pub const Result = struct { key: K, val: V };
35 pub fn next(self: *Iterator) ?Result {
36 if (self.k != null and self.v != null) {
37 const result = Result{ .key = self.k.?, .val = self.v.? };
40 self.v = self.cursor.get(&k, V, .Next) catch return null;
50 pub fn iterator(self: Self) !Iterator {
51 var cursor = try self.dbi.cursor();
54 const v = try cursor.get(&k, V, .First);
55 return .{ .cursor = cursor, .k = k, .v = v };
60 pub const Prng = struct {
61 var prng = std.Random.DefaultPrng.init(PRNG_SEED);
63 pub fn gen(dbi: lmdb.Dbi, comptime T: type) !T {
64 var buf: [@sizeOf(T)]u8 = undefined;
68 const t = std.mem.bytesToValue(T, &buf);
69 if (!try dbi.has(t)) {
76 fn SetListBase(comptime K: type, comptime V: type) type {
79 pub const Index = u64;
82 pub const View = SetListViewBase(K, V);
86 fn open_dbi(txn: lmdb.Txn) !lmdb.Dbi {
87 return try txn.dbi("SetList");
89 pub fn init(txn: lmdb.Txn) !Self {
90 const head = View.Head{};
91 const dbi = try open_dbi(txn);
92 const idx = try Prng.gen(dbi, Index);
93 try dbi.put(idx, head);
94 return .{ .idx = idx };
96 pub fn open(self: Self, txn: lmdb.Txn) !View {
98 if (self.idx == null) {
99 return error.NotInitialized;
102 const dbi = try open_dbi(txn);
103 const head = try dbi.get(self.idx.?, View.Head);
113 fn SetListViewBase(comptime K: type, comptime V: type) type {
115 const Self = @This();
116 pub const ItemIndex = struct { SetListBase(K, V).Index, Key };
120 pub const Head = struct {
125 pub const Item = struct {
132 idx: SetListBase(K, V).Index,
135 fn item_idx(self: Self, k: K) ItemIndex {
136 return .{ self.idx, k };
138 fn item_get(self: Self, k: K) !Item {
139 return try self.dbi.get(self.item_idx(k), Item);
141 fn item_put(self: Self, k: K, item: Item) !void {
142 try self.dbi.put(self.item_idx(k), item);
144 fn head_update(self: Self) !void {
145 try self.dbi.put(self.idx, self.head);
147 pub fn del(self: *Self, k: K) !void {
148 const item = try self.item_get(k);
150 if (item.prev != null) {
151 var prev = try self.item_get(item.prev.?);
152 prev.next = item.next;
153 try self.item_put(item.prev.?, prev);
156 if (item.next != null) {
157 var next = try self.item_get(item.next.?);
158 next.prev = item.prev;
159 try self.item_put(item.next.?, next);
162 if (self.head.first == k) self.head.first = item.next;
163 if (self.head.last == k) self.head.last = item.prev;
165 try self.head_update();
167 try self.dbi.del(self.item_idx(k));
169 pub fn clear(self: *Self) !void {
170 var it = self.iterator();
171 while (it.next()) |kv| {
172 try self.del(kv.key);
175 pub fn len(self: Self) usize {
176 return self.head.len;
178 pub fn append(self: *Self, key: Key, val: Val) !void {
179 if (self.head.len == 0) {
180 const item = Item{ .data = val };
181 try self.item_put(key, item);
184 self.head.first = key;
185 self.head.last = key;
186 try self.head_update();
188 const prev_idx = self.head.last.?;
189 var prev = try self.item_get(prev_idx);
191 const item = Item{ .prev = prev_idx, .data = val };
192 try self.item_put(key, item);
195 try self.item_put(prev_idx, prev);
197 self.head.last = key;
199 try self.head_update();
202 pub fn get(self: Self, key: Key) !Val {
203 const item = try self.item_get(key);
206 pub fn has(self: Self, key: Key) !bool {
207 return self.dbi.has(self.item_idx(key));
209 pub const Iterator = struct {
210 pub const Result = struct { key: K, val: V };
212 slv: SetListViewBase(K, V),
214 dir: enum { Forward, Backward },
216 pub fn next(self: *Iterator) ?Result {
217 if (self.idx != null) {
218 const k = self.idx.?;
219 const item = self.slv.item_get(k) catch return null;
220 self.idx = switch (self.dir) {
221 .Forward => item.next,
222 .Backward => item.prev,
224 return .{ .key = k, .val = item.data };
230 pub fn iterator(self: Self) Iterator {
233 .idx = self.head.first,
237 pub fn reverse_iterator(self: Self) Iterator {
240 .idx = self.head.last,
247 pub fn Set(comptime K: type) type {
250 pub const Val = void;
252 pub const Base = SetListBase(Key, Val);
253 pub const View = struct {
254 const ViewBase = SetListViewBase(Key, Val);
258 pub fn del(self: *@This(), key: Key) !void {
259 try self.base.del(key);
261 pub fn clear(self: *@This()) !void {
262 try self.base.clear();
264 pub fn len(self: @This()) usize {
265 return self.base.len();
267 pub fn append(self: *@This(), key: Key) !void {
268 try self.base.append(key, {});
270 pub fn has(self: @This(), key: Key) !bool {
271 return try self.base.has(key);
273 pub fn iterator(self: @This()) ViewBase.Iterator {
274 return self.base.iterator();
276 pub fn reverse_iterator(self: @This()) ViewBase.Iterator {
277 return self.base.reverse_iterator();
283 pub fn init(txn: lmdb.Txn) !@This() {
284 return .{ .base = try Base.init(txn) };
286 pub fn open(self: @This(), txn: lmdb.Txn) !View {
287 return .{ .base = try self.base.open(txn) };
292 pub fn List(comptime V: type) type {
297 pub const Base = SetListBase(Key, Val);
298 pub const View = struct {
299 const ViewBase = SetListViewBase(Key, Val);
303 fn gen(self: @This()) !Key {
306 const key = try Prng.gen(self.base.dbi, Key);
307 if (!try self.base.dbi.has(self.base.item_idx(key))) {
312 pub fn del(self: *@This(), key: Key) !void {
313 try self.base.del(key);
315 pub fn clear(self: *@This()) !void {
316 try self.base.clear();
318 pub fn len(self: @This()) usize {
319 return self.base.len();
321 pub fn append(self: *@This(), val: Val) !Key {
322 const key = try self.gen();
323 try self.base.append(key, val);
326 pub fn get(self: @This(), key: Key) !Val {
327 return try self.base.get(key);
329 pub fn has(self: @This(), key: Key) !bool {
330 return try self.base.has(key);
332 pub fn iterator(self: @This()) ViewBase.Iterator {
333 return self.base.iterator();
335 pub fn reverse_iterator(self: @This()) ViewBase.Iterator {
336 return self.base.reverse_iterator();
342 pub fn init(txn: lmdb.Txn) !@This() {
343 return .{ .base = try Base.init(txn) };
345 pub fn open(self: @This(), txn: lmdb.Txn) !View {
346 return .{ .base = try self.base.open(txn) };
351 pub fn SetList(comptime K: type, comptime V: type) type {
356 pub const Base = SetListBase(Key, Val);
357 pub const View = struct {
358 const ViewBase = SetListViewBase(Key, Val);
362 pub fn del(self: *@This(), key: Key) !void {
363 try self.base.del(key);
365 pub fn clear(self: *@This()) !void {
366 try self.base.clear();
368 pub fn len(self: @This()) usize {
369 return self.base.len();
371 pub fn append(self: *@This(), key: Key, val: Val) !void {
372 try self.base.append(key, val);
374 pub fn get(self: @This(), key: Key) !Val {
375 return try self.base.get(key);
377 pub fn has(self: @This(), key: Key) !bool {
378 return try self.base.has(key);
380 pub fn iterator(self: @This()) ViewBase.Iterator {
381 return self.base.iterator();
383 pub fn reverse_iterator(self: @This()) ViewBase.Iterator {
384 return self.base.reverse_iterator();
390 pub fn init(txn: lmdb.Txn) !@This() {
391 return .{ .base = try Base.init(txn) };
393 pub fn open(self: @This(), txn: lmdb.Txn) !View {
394 return .{ .base = try self.base.open(txn) };
399 const DB_SIZE = 1024 * 1024 * 1;
402 const env = try lmdb.Env.open("db", DB_SIZE);
405 const txn = try env.txn();
406 defer txn.commit() catch {};
408 var db = try Db(u32, u32).init(txn, "123");
410 if (try db.has(123)) {
415 std.debug.print("n: {}\n", .{n});
419 // const env = try lmdb.Env.open("db", DB_SIZE);
420 // defer env.close();
422 // const txn = try env.txn();
423 // defer txn.commit();
425 // const db = List.init(txn, "b", u32);
429 var env = try lmdb.Env.open("db", 1024 * 1024 * 1);
433 var txn = try env.txn();
434 defer txn.commit() catch {};
436 var dbi = try txn.dbi("abc");
442 var a: A = undefined;
443 const a_idx: u64 = 27;
444 if (try dbi.has(a_idx)) {
445 a = try dbi.get(a_idx, A);
447 a = A{ .ml = try Set(usize).init(txn) };
448 try dbi.put(a_idx, a);
451 var ml = try a.ml.open(txn);
453 const len = ml.len();
454 std.debug.print("{}\n", .{len});
456 std.debug.print("{}\n", .{try ml.has(len)});
457 var it = ml.iterator();
458 while (it.next()) |i| {
459 std.debug.print("{}\n", .{i});
464 var env = try lmdb.Env.open("db", 1024 * 1024 * 1);
468 var txn = try env.txn();
469 defer txn.commit() catch {};
471 var dbi = try txn.dbi("def");
477 var a: A = undefined;
478 const a_idx: u64 = 27;
479 if (try dbi.has(a_idx)) {
480 a = try dbi.get(a_idx, A);
482 a = A{ .ml = try List(usize).init(txn) };
483 try dbi.put(a_idx, a);
486 var ml = try a.ml.open(txn);
488 const len = ml.len();
489 std.debug.print("{}\n", .{len});
490 const newest = try ml.append(len * 10);
491 std.debug.print("{}: {}\n", .{ newest, try ml.get(newest) });
492 var it = ml.iterator();
493 while (it.next()) |i| {
494 std.debug.print("{}: {}\n", .{ i.key, i.val });
499 var env = try lmdb.Env.open("db", 1024 * 1024 * 1);
503 var txn = try env.txn();
504 defer txn.commit() catch {};
506 var dbi = try txn.dbi("ghi");
509 ml: SetList(usize, usize),
512 var a: A = undefined;
513 const a_idx: u64 = 27;
514 if (try dbi.has(a_idx)) {
515 a = try dbi.get(a_idx, A);
517 a = A{ .ml = try SetList(usize, usize).init(txn) };
518 try dbi.put(a_idx, a);
521 var ml = try a.ml.open(txn);
523 const len = ml.len();
524 std.debug.print("{}\n", .{len});
525 try ml.append(len, len * 10);
526 std.debug.print("{}\n", .{try ml.get(len)});
527 var it = ml.iterator();
528 while (it.next()) |i| {
529 std.debug.print("{}: {}\n", .{ i.key, i.val });