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 {
34 pub fn next(self: *Iterator) ?struct { key: K, val: V } {
35 if (self.k != null and self.v != null) {
36 const result = .{ .key = self.k.?, .val = self.v.? };
39 self.v = self.cursor.get(&k, V, .Next) catch return null;
49 pub fn iterator(self: Self) !Iterator {
50 var cursor = try self.dbi.cursor();
53 const v = try cursor.get(&k, V, .First);
54 return .{ .cursor = cursor, .k = k, .v = v };
59 pub const Prng = struct {
60 var prng = std.Random.DefaultPrng.init(PRNG_SEED);
62 pub fn gen(dbi: lmdb.Dbi, comptime T: type) !T {
63 var buf: [@sizeOf(T)]u8 = undefined;
67 const t = std.mem.bytesToValue(T, &buf);
68 if (!try dbi.has(t)) {
74 pub fn Set(comptime K: type) type {
79 pub const Index = u64;
80 pub const View = SetView(K);
82 fn open_dbi(txn: lmdb.Txn) !lmdb.Dbi {
83 return try txn.dbi("SetList");
85 pub fn init(txn: lmdb.Txn) !Self {
86 const head = View.Head{};
87 const dbi = try open_dbi(txn);
88 const idx = try Prng.gen(dbi, Index);
89 try dbi.put(idx, head);
90 return .{ .idx = idx };
92 pub fn open(self: Self, txn: lmdb.Txn) !View {
94 if (self.idx == null) {
95 return error.NotInitialized;
98 const dbi = try open_dbi(txn);
99 const head = try dbi.get(self.idx.?, View.Head);
109 pub fn SetView(comptime K: type) type {
111 const Self = @This();
112 const ItemIndex = struct { Set(K).Index, K };
114 pub const Head = struct {
119 pub const Item = struct {
128 fn item_idx(self: Self, k: K) ItemIndex {
129 return .{ self.idx, k };
131 fn item_get(self: Self, k: K) !Item {
132 return try self.dbi.get(self.item_idx(k), Item);
134 fn item_put(self: Self, k: K, item: Item) !void {
135 try self.dbi.put(self.item_idx(k), item);
137 fn head_update(self: Self) !void {
138 try self.dbi.put(self.idx, self.head);
140 pub fn append(self: *Self, k: K) !void {
141 if (self.head.len == 0) {
143 try self.item_put(k, item);
148 try self.head_update();
150 const prev_idx = self.head.last.?;
151 var prev = try self.item_get(prev_idx);
153 const item = Item{ .prev = prev_idx };
154 try self.item_put(k, item);
157 try self.item_put(prev_idx, prev);
161 try self.head_update();
164 pub fn del(self: *Self, k: K) !void {
165 const item = try self.item_get(k);
167 if (item.prev != null) {
168 var prev = try self.item_get(item.prev.?);
169 prev.next = item.next;
170 try self.item_put(item.prev.?, prev);
173 if (item.next != null) {
174 var next = try self.item_get(item.next.?);
175 next.prev = item.prev;
176 try self.item_put(item.next.?, next);
179 if (self.head.first == k) self.head.first = item.next;
180 if (self.head.last == k) self.head.last = item.prev;
182 try self.head_update();
184 try self.dbi.del(self.item_idx(k));
186 pub fn clear(self: *Self) !void {
187 var it = self.iterator();
188 while (it.next()) |i| {
192 pub fn has(self: Self, k: K) !bool {
193 return self.dbi.has(self.item_idx(k));
195 pub fn len(self: Self) usize {
196 return self.head.len;
198 pub const Iterator = struct {
201 dir: enum { Forward, Backward },
203 pub fn next(self: *Iterator) ?K {
204 if (self.idx != null) {
205 const k = self.idx.?;
206 const item = self.sv.item_get(k) catch return null;
207 self.idx = switch (self.dir) {
208 .Forward => item.next,
209 .Backward => item.prev,
217 pub fn iterator(self: Self) Iterator {
220 .idx = self.head.first,
224 pub fn reverse_iterator(self: Self) Iterator {
227 .idx = self.head.last,
233 pub fn List(comptime V: type) type {
237 const Self = @This();
238 pub const Index = u64;
239 pub const View = ListView(V);
241 fn open_dbi(txn: lmdb.Txn) !lmdb.Dbi {
242 return try txn.dbi("SetList");
244 pub fn init(txn: lmdb.Txn) !Self {
245 const head = View.Head{};
246 const dbi = try open_dbi(txn);
247 const idx = try Prng.gen(dbi, Index);
248 try dbi.put(idx, head);
249 return .{ .idx = idx };
251 pub fn open(self: Self, txn: lmdb.Txn) !View {
253 if (self.idx == null) {
254 return error.NotInitialized;
257 const dbi = try open_dbi(txn);
258 const head = try dbi.get(self.idx.?, View.Head);
268 pub fn ListView(comptime V: type) type {
270 const Self = @This();
272 const ItemIndex = struct { List(V).Index, K };
274 pub const Head = struct {
279 pub const Item = struct {
289 fn item_idx(self: Self, k: K) ItemIndex {
290 return .{ self.idx, k };
292 fn item_get(self: Self, k: K) !Item {
293 return try self.dbi.get(self.item_idx(k), Item);
295 fn item_put(self: Self, k: K, item: Item) !void {
296 try self.dbi.put(self.item_idx(k), item);
298 fn head_update(self: Self) !void {
299 try self.dbi.put(self.idx, self.head);
301 fn gen(self: Self) !K {
304 const k = try Prng.gen(self.dbi, K);
305 if (!try self.dbi.has(self.item_idx(k))) {
310 pub fn append(self: *Self, v: V) !K {
311 if (self.head.len == 0) {
312 const k = try self.gen();
313 const item = Item{ .data = v };
314 try self.item_put(k, item);
319 try self.head_update();
323 const prev_idx = self.head.last.?;
324 var prev = try self.item_get(prev_idx);
326 const k = try self.gen();
327 const item = Item{ .prev = prev_idx, .data = v };
328 try self.item_put(k, item);
331 try self.item_put(prev_idx, prev);
335 try self.head_update();
340 pub fn get(self: Self, k: K) !V {
341 const item = try self.item_get(k);
344 pub fn del(self: *Self, k: K) !void {
345 const item = try self.item_get(k);
347 if (item.prev != null) {
348 var prev = try self.item_get(item.prev.?);
349 prev.next = item.next;
350 try self.item_put(item.prev.?, prev);
353 if (item.next != null) {
354 var next = try self.item_get(item.next.?);
355 next.prev = item.prev;
356 try self.item_put(item.next.?, next);
359 if (self.head.first == k) self.head.first = item.next;
360 if (self.head.last == k) self.head.last = item.prev;
362 try self.head_update();
364 try self.dbi.del(self.item_idx(k));
366 pub fn clear(self: *Self) !void {
367 var it = self.iterator();
368 while (it.next()) |kv| {
369 try self.del(kv.key);
372 pub fn len(self: Self) usize {
373 return self.head.len;
375 pub const Iterator = struct {
378 dir: enum { Forward, Backward },
380 pub fn next(self: *Iterator) ?struct { key: K, val: V } {
381 if (self.idx != null) {
382 const k = self.idx.?;
383 const item = self.lv.item_get(k) catch return null;
384 self.idx = switch (self.dir) {
385 .Forward => item.next,
386 .Backward => item.prev,
388 return .{ .key = k, .val = item.data };
394 pub fn iterator(self: Self) Iterator {
397 .idx = self.head.first,
401 pub fn reverse_iterator(self: Self) Iterator {
404 .idx = self.head.last,
411 pub fn SetList(comptime K: type, comptime V: type) type {
415 const Self = @This();
416 pub const Index = u64;
417 pub const View = SetListView(K, V);
419 fn open_dbi(txn: lmdb.Txn) !lmdb.Dbi {
420 return try txn.dbi("SetList");
422 pub fn init(txn: lmdb.Txn) !Self {
423 const head = View.Head{};
424 const dbi = try open_dbi(txn);
425 const idx = try Prng.gen(dbi, Index);
426 try dbi.put(idx, head);
427 return .{ .idx = idx };
429 pub fn open(self: Self, txn: lmdb.Txn) !View {
431 if (self.idx == null) {
432 return error.NotInitialized;
435 const dbi = try open_dbi(txn);
436 const head = try dbi.get(self.idx.?, View.Head);
446 pub fn SetListView(comptime K: type, comptime V: type) type {
448 const Self = @This();
449 const ItemIndex = struct { SetList(K, V).Index, K };
451 pub const Head = struct {
456 pub const Item = struct {
463 idx: SetList(K, V).Index,
466 fn item_idx(self: Self, k: K) ItemIndex {
467 return .{ self.idx, k };
469 fn item_get(self: Self, k: K) !Item {
470 return try self.dbi.get(self.item_idx(k), Item);
472 fn item_put(self: Self, k: K, item: Item) !void {
473 try self.dbi.put(self.item_idx(k), item);
475 fn head_update(self: Self) !void {
476 try self.dbi.put(self.idx, self.head);
478 pub fn append(self: *Self, k: K, v: V) !void {
479 if (self.head.len == 0) {
480 const item = Item{ .data = v };
481 try self.item_put(k, item);
486 try self.head_update();
488 const prev_idx = self.head.last.?;
489 var prev = try self.item_get(prev_idx);
491 const item = Item{ .prev = prev_idx, .data = v };
492 try self.item_put(k, item);
495 try self.item_put(prev_idx, prev);
499 try self.head_update();
502 pub fn get(self: Self, k: K) !V {
503 const item = try self.item_get(k);
506 pub fn del(self: *Self, k: K) !void {
507 const item = try self.item_get(k);
509 if (item.prev != null) {
510 var prev = try self.item_get(item.prev.?);
511 prev.next = item.next;
512 try self.item_put(item.prev.?, prev);
515 if (item.next != null) {
516 var next = try self.item_get(item.next.?);
517 next.prev = item.prev;
518 try self.item_put(item.next.?, next);
521 if (self.head.first == k) self.head.first = item.next;
522 if (self.head.last == k) self.head.last = item.prev;
524 try self.head_update();
526 try self.dbi.del(self.item_idx(k));
528 pub fn clear(self: *Self) !void {
529 var it = self.iterator();
530 while (it.next()) |kv| {
531 try self.del(kv.key);
534 pub fn has(self: Self, k: K) !bool {
535 return self.dbi.has(self.item_idx(k));
537 pub fn len(self: Self) usize {
538 return self.head.len;
540 pub const Iterator = struct {
541 slv: SetListView(K, V),
543 dir: enum { Forward, Backward },
545 pub fn next(self: *Iterator) ?struct { key: K, val: V } {
546 if (self.idx != null) {
547 const k = self.idx.?;
548 const item = self.slv.item_get(k) catch return null;
549 self.idx = switch (self.dir) {
550 .Forward => item.next,
551 .Backward => item.prev,
553 return .{ .key = k, .val = item.data };
559 pub fn iterator(self: Self) Iterator {
562 .idx = self.head.first,
566 pub fn reverse_iterator(self: Self) Iterator {
569 .idx = self.head.last,
576 const DB_SIZE = 1024 * 1024 * 1;
579 const env = try lmdb.Env.open("db", DB_SIZE);
582 const txn = try env.txn();
583 defer txn.commit() catch {};
585 var db = try Db(u32, u32).init(txn, "123");
587 if (try db.has(123)) {
592 std.debug.print("n: {}\n", .{n});
596 // const env = try lmdb.Env.open("db", DB_SIZE);
597 // defer env.close();
599 // const txn = try env.txn();
600 // defer txn.commit();
602 // const db = List.init(txn, "b", u32);
606 var env = try lmdb.Env.open("db", 1024 * 1024 * 1);
610 var txn = try env.txn();
611 defer txn.commit() catch {};
613 var dbi = try txn.dbi("abc");
619 var a: A = undefined;
620 const a_idx: u64 = 27;
621 if (try dbi.has(a_idx)) {
622 a = try dbi.get(a_idx, A);
624 a = A{ .ml = try Set(usize).init(txn) };
625 try dbi.put(a_idx, a);
628 var ml = try a.ml.open(txn);
630 const len = ml.len();
631 std.debug.print("{}\n", .{len});
633 std.debug.print("{}\n", .{try ml.has(len)});
634 var it = ml.iterator();
635 while (it.next()) |i| {
636 std.debug.print("{}\n", .{i});
641 var env = try lmdb.Env.open("db", 1024 * 1024 * 1);
645 var txn = try env.txn();
646 defer txn.commit() catch {};
648 var dbi = try txn.dbi("def");
654 var a: A = undefined;
655 const a_idx: u64 = 27;
656 if (try dbi.has(a_idx)) {
657 a = try dbi.get(a_idx, A);
659 a = A{ .ml = try List(usize).init(txn) };
660 try dbi.put(a_idx, a);
663 var ml = try a.ml.open(txn);
665 const len = ml.len();
666 std.debug.print("{}\n", .{len});
667 const newest = try ml.append(len * 10);
668 std.debug.print("{}: {}\n", .{ newest, try ml.get(newest) });
669 var it = ml.iterator();
670 while (it.next()) |i| {
671 std.debug.print("{}: {}\n", .{ i.key, i.val });
676 var env = try lmdb.Env.open("db", 1024 * 1024 * 1);
680 var txn = try env.txn();
681 defer txn.commit() catch {};
683 var dbi = try txn.dbi("ghi");
686 ml: SetList(usize, usize),
689 var a: A = undefined;
690 const a_idx: u64 = 27;
691 if (try dbi.has(a_idx)) {
692 a = try dbi.get(a_idx, A);
694 a = A{ .ml = try SetList(usize, usize).init(txn) };
695 try dbi.put(a_idx, a);
698 var ml = try a.ml.open(txn);
700 const len = ml.len();
701 std.debug.print("{}\n", .{len});
702 try ml.append(len, len * 10);
703 std.debug.print("{}\n", .{try ml.get(len)});
704 var it = ml.iterator();
705 while (it.next()) |i| {
706 std.debug.print("{}: {}\n", .{ i.key, i.val });