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 has(self: Self, k: K) !bool {
187 return self.dbi.has(self.item_idx(k));
189 pub fn len(self: Self) usize {
190 return self.head.len;
192 pub const Iterator = struct {
195 dir: enum { Forward, Backward },
197 pub fn next(self: *Iterator) ?K {
198 if (self.idx != null) {
199 const k = self.idx.?;
200 const item = self.sv.item_get(k) catch return null;
201 self.idx = switch (self.dir) {
202 .Forward => item.next,
203 .Backward => item.prev,
211 pub fn iterator(self: Self) Iterator {
214 .idx = self.head.first,
218 pub fn reverse_iterator(self: Self) Iterator {
221 .idx = self.head.last,
227 pub fn List(comptime V: type) type {
231 const Self = @This();
232 pub const Index = u64;
233 pub const View = ListView(V);
235 fn open_dbi(txn: lmdb.Txn) !lmdb.Dbi {
236 return try txn.dbi("SetList");
238 pub fn init(txn: lmdb.Txn) !Self {
239 const head = View.Head{};
240 const dbi = try open_dbi(txn);
241 const idx = try Prng.gen(dbi, Index);
242 try dbi.put(idx, head);
243 return .{ .idx = idx };
245 pub fn open(self: Self, txn: lmdb.Txn) !View {
247 if (self.idx == null) {
248 return error.NotInitialized;
251 const dbi = try open_dbi(txn);
252 const head = try dbi.get(self.idx.?, View.Head);
262 pub fn ListView(comptime V: type) type {
264 const Self = @This();
266 const ItemIndex = struct { List(V).Index, K };
268 pub const Head = struct {
273 pub const Item = struct {
283 fn item_idx(self: Self, k: K) ItemIndex {
284 return .{ self.idx, k };
286 fn item_get(self: Self, k: K) !Item {
287 return try self.dbi.get(self.item_idx(k), Item);
289 fn item_put(self: Self, k: K, item: Item) !void {
290 try self.dbi.put(self.item_idx(k), item);
292 fn head_update(self: Self) !void {
293 try self.dbi.put(self.idx, self.head);
295 fn gen(self: Self) !K {
298 const k = try Prng.gen(self.dbi, K);
299 if (!try self.dbi.has(self.item_idx(k))) {
304 pub fn append(self: *Self, v: V) !K {
305 if (self.head.len == 0) {
306 const k = try self.gen();
307 const item = Item{ .data = v };
308 try self.item_put(k, item);
313 try self.head_update();
317 const prev_idx = self.head.last.?;
318 var prev = try self.item_get(prev_idx);
320 const k = try self.gen();
321 const item = Item{ .prev = prev_idx, .data = v };
322 try self.item_put(k, item);
325 try self.item_put(prev_idx, prev);
329 try self.head_update();
334 pub fn get(self: Self, k: K) !V {
335 const item = try self.item_get(k);
338 pub fn del(self: *Self, k: K) !void {
339 const item = try self.item_get(k);
341 if (item.prev != null) {
342 var prev = try self.item_get(item.prev.?);
343 prev.next = item.next;
344 try self.item_put(item.prev.?, prev);
347 if (item.next != null) {
348 var next = try self.item_get(item.next.?);
349 next.prev = item.prev;
350 try self.item_put(item.next.?, next);
353 if (self.head.first == k) self.head.first = item.next;
354 if (self.head.last == k) self.head.last = item.prev;
356 try self.head_update();
358 try self.dbi.del(self.item_idx(k));
360 pub fn len(self: Self) usize {
361 return self.head.len;
363 pub const Iterator = struct {
366 dir: enum { Forward, Backward },
368 pub fn next(self: *Iterator) ?struct { key: K, val: V } {
369 if (self.idx != null) {
370 const k = self.idx.?;
371 const item = self.lv.item_get(k) catch return null;
372 self.idx = switch (self.dir) {
373 .Forward => item.next,
374 .Backward => item.prev,
376 return .{ .key = k, .val = item.data };
382 pub fn iterator(self: Self) Iterator {
385 .idx = self.head.first,
389 pub fn reverse_iterator(self: Self) Iterator {
392 .idx = self.head.last,
399 pub fn SetList(comptime K: type, comptime V: type) type {
403 const Self = @This();
404 pub const Index = u64;
405 pub const View = SetListView(K, V);
407 fn open_dbi(txn: lmdb.Txn) !lmdb.Dbi {
408 return try txn.dbi("SetList");
410 pub fn init(txn: lmdb.Txn) !Self {
411 const head = View.Head{};
412 const dbi = try open_dbi(txn);
413 const idx = try Prng.gen(dbi, Index);
414 try dbi.put(idx, head);
415 return .{ .idx = idx };
417 pub fn open(self: Self, txn: lmdb.Txn) !View {
419 if (self.idx == null) {
420 return error.NotInitialized;
423 const dbi = try open_dbi(txn);
424 const head = try dbi.get(self.idx.?, View.Head);
434 pub fn SetListView(comptime K: type, comptime V: type) type {
436 const Self = @This();
437 const ItemIndex = struct { SetList(K, V).Index, K };
439 pub const Head = struct {
444 pub const Item = struct {
451 idx: SetList(K, V).Index,
454 fn item_idx(self: Self, k: K) ItemIndex {
455 return .{ self.idx, k };
457 fn item_get(self: Self, k: K) !Item {
458 return try self.dbi.get(self.item_idx(k), Item);
460 fn item_put(self: Self, k: K, item: Item) !void {
461 try self.dbi.put(self.item_idx(k), item);
463 fn head_update(self: Self) !void {
464 try self.dbi.put(self.idx, self.head);
466 pub fn append(self: *Self, k: K, v: V) !void {
467 if (self.head.len == 0) {
468 const item = Item{ .data = v };
469 try self.item_put(k, item);
474 try self.head_update();
476 const prev_idx = self.head.last.?;
477 var prev = try self.item_get(prev_idx);
479 const item = Item{ .prev = prev_idx, .data = v };
480 try self.item_put(k, item);
483 try self.item_put(prev_idx, prev);
487 try self.head_update();
490 pub fn get(self: Self, k: K) !V {
491 const item = try self.item_get(k);
494 pub fn del(self: *Self, k: K) !void {
495 const item = try self.item_get(k);
497 if (item.prev != null) {
498 var prev = try self.item_get(item.prev.?);
499 prev.next = item.next;
500 try self.item_put(item.prev.?, prev);
503 if (item.next != null) {
504 var next = try self.item_get(item.next.?);
505 next.prev = item.prev;
506 try self.item_put(item.next.?, next);
509 if (self.head.first == k) self.head.first = item.next;
510 if (self.head.last == k) self.head.last = item.prev;
512 try self.head_update();
514 try self.dbi.del(self.item_idx(k));
516 pub fn has(self: Self, k: K) !bool {
517 return self.dbi.has(self.item_idx(k));
519 pub fn len(self: Self) usize {
520 return self.head.len;
522 pub const Iterator = struct {
523 slv: SetListView(K, V),
525 dir: enum { Forward, Backward },
527 pub fn next(self: *Iterator) ?struct { key: K, val: V } {
528 if (self.idx != null) {
529 const k = self.idx.?;
530 const item = self.slv.item_get(k) catch return null;
531 self.idx = switch (self.dir) {
532 .Forward => item.next,
533 .Backward => item.prev,
535 return .{ .key = k, .val = item.data };
541 pub fn iterator(self: Self) Iterator {
544 .idx = self.head.first,
548 pub fn reverse_iterator(self: Self) Iterator {
551 .idx = self.head.last,
558 const DB_SIZE = 1024 * 1024 * 1;
561 const env = try lmdb.Env.open("db", DB_SIZE);
564 const txn = try env.txn();
565 defer txn.commit() catch {};
567 var db = try Db(u32, u32).init(txn, "123");
569 if (try db.has(123)) {
574 std.debug.print("n: {}\n", .{n});
578 // const env = try lmdb.Env.open("db", DB_SIZE);
579 // defer env.close();
581 // const txn = try env.txn();
582 // defer txn.commit();
584 // const db = List.init(txn, "b", u32);
588 var env = try lmdb.Env.open("db", 1024 * 1024 * 1);
592 var txn = try env.txn();
593 defer txn.commit() catch {};
595 var dbi = try txn.dbi("abc");
601 var a: A = undefined;
602 const a_idx: u64 = 27;
603 if (try dbi.has(a_idx)) {
604 a = try dbi.get(a_idx, A);
606 a = A{ .ml = try Set(usize).init(txn) };
607 try dbi.put(a_idx, a);
610 var ml = try a.ml.open(txn);
612 const len = ml.len();
613 std.debug.print("{}\n", .{len});
615 std.debug.print("{}\n", .{try ml.has(len)});
616 var it = ml.iterator();
617 while (it.next()) |i| {
618 std.debug.print("{}\n", .{i});
623 var env = try lmdb.Env.open("db", 1024 * 1024 * 1);
627 var txn = try env.txn();
628 defer txn.commit() catch {};
630 var dbi = try txn.dbi("def");
636 var a: A = undefined;
637 const a_idx: u64 = 27;
638 if (try dbi.has(a_idx)) {
639 a = try dbi.get(a_idx, A);
641 a = A{ .ml = try List(usize).init(txn) };
642 try dbi.put(a_idx, a);
645 var ml = try a.ml.open(txn);
647 const len = ml.len();
648 std.debug.print("{}\n", .{len});
649 const newest = try ml.append(len * 10);
650 std.debug.print("{}: {}\n", .{ newest, try ml.get(newest) });
651 var it = ml.iterator();
652 while (it.next()) |i| {
653 std.debug.print("{}: {}\n", .{ i.key, i.val });
658 var env = try lmdb.Env.open("db", 1024 * 1024 * 1);
662 var txn = try env.txn();
663 defer txn.commit() catch {};
665 var dbi = try txn.dbi("ghi");
668 ml: SetList(usize, usize),
671 var a: A = undefined;
672 const a_idx: u64 = 27;
673 if (try dbi.has(a_idx)) {
674 a = try dbi.get(a_idx, A);
676 a = A{ .ml = try SetList(usize, usize).init(txn) };
677 try dbi.put(a_idx, a);
680 var ml = try a.ml.open(txn);
682 const len = ml.len();
683 std.debug.print("{}\n", .{len});
684 try ml.append(len, len * 10);
685 std.debug.print("{}\n", .{try ml.get(len)});
686 var it = ml.iterator();
687 while (it.next()) |i| {
688 std.debug.print("{}: {}\n", .{ i.key, i.val });