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 {
80 pub const Index = u64;
81 pub const View = SetView(K);
83 fn open_dbi(txn: lmdb.Txn) !lmdb.Dbi {
84 return try txn.dbi("SetList");
86 pub fn init(txn: lmdb.Txn) !Self {
87 const head = View.Head{};
88 const dbi = try open_dbi(txn);
89 const idx = try Prng.gen(dbi, Index);
90 try dbi.put(idx, head);
91 return .{ .idx = idx };
93 pub fn open(self: Self, txn: lmdb.Txn) !View {
95 if (self.idx == null) {
96 return error.NotInitialized;
99 const dbi = try open_dbi(txn);
100 const head = try dbi.get(self.idx.?, View.Head);
110 pub fn SetView(comptime K: type) type {
112 const Self = @This();
113 const ItemIndex = struct { Set(K).Index, K };
115 pub const Head = struct {
120 pub const Item = struct {
129 fn item_idx(self: Self, k: K) ItemIndex {
130 return .{ self.idx, k };
132 fn item_get(self: Self, k: K) !Item {
133 return try self.dbi.get(self.item_idx(k), Item);
135 fn item_put(self: Self, k: K, item: Item) !void {
136 try self.dbi.put(self.item_idx(k), item);
138 fn head_update(self: Self) !void {
139 try self.dbi.put(self.idx, self.head);
141 pub fn append(self: *Self, k: K) !void {
142 if (self.head.len == 0) {
144 try self.item_put(k, item);
149 try self.head_update();
151 const prev_idx = self.head.last.?;
152 var prev = try self.item_get(prev_idx);
154 const item = Item{ .prev = prev_idx };
155 try self.item_put(k, item);
158 try self.item_put(prev_idx, prev);
162 try self.head_update();
165 pub fn del(self: *Self, k: K) !void {
166 const item = try self.item_get(k);
168 if (item.prev != null) {
169 var prev = try self.item_get(item.prev.?);
170 prev.next = item.next;
171 try self.item_put(item.prev.?, prev);
174 if (item.next != null) {
175 var next = try self.item_get(item.next.?);
176 next.prev = item.prev;
177 try self.item_put(item.next.?, next);
180 if (self.head.first == k) self.head.first = item.next;
181 if (self.head.last == k) self.head.last = item.prev;
183 try self.head_update();
185 try self.dbi.del(self.item_idx(k));
187 pub fn clear(self: *Self) !void {
188 var it = self.iterator();
189 while (it.next()) |i| {
193 pub fn has(self: Self, k: K) !bool {
194 return self.dbi.has(self.item_idx(k));
196 pub fn len(self: Self) usize {
197 return self.head.len;
199 pub const Iterator = struct {
202 dir: enum { Forward, Backward },
204 pub fn next(self: *Iterator) ?struct { key: K } {
205 if (self.idx != null) {
206 const k = self.idx.?;
207 const item = self.sv.item_get(k) catch return null;
208 self.idx = switch (self.dir) {
209 .Forward => item.next,
210 .Backward => item.prev,
212 return .{ .key = k };
218 pub fn iterator(self: Self) Iterator {
221 .idx = self.head.first,
225 pub fn reverse_iterator(self: Self) Iterator {
228 .idx = self.head.last,
234 pub fn List(comptime V: type) type {
238 const Self = @This();
239 pub const Index = u64;
242 pub const View = ListView(V);
244 fn open_dbi(txn: lmdb.Txn) !lmdb.Dbi {
245 return try txn.dbi("SetList");
247 pub fn init(txn: lmdb.Txn) !Self {
248 const head = View.Head{};
249 const dbi = try open_dbi(txn);
250 const idx = try Prng.gen(dbi, Index);
251 try dbi.put(idx, head);
252 return .{ .idx = idx };
254 pub fn open(self: Self, txn: lmdb.Txn) !View {
256 if (self.idx == null) {
257 return error.NotInitialized;
260 const dbi = try open_dbi(txn);
261 const head = try dbi.get(self.idx.?, View.Head);
271 pub fn ListView(comptime V: type) type {
273 const Self = @This();
275 const ItemIndex = struct { List(V).Index, K };
277 pub const Head = struct {
282 pub const Item = struct {
292 fn item_idx(self: Self, k: K) ItemIndex {
293 return .{ self.idx, k };
295 fn item_get(self: Self, k: K) !Item {
296 return try self.dbi.get(self.item_idx(k), Item);
298 fn item_put(self: Self, k: K, item: Item) !void {
299 try self.dbi.put(self.item_idx(k), item);
301 fn head_update(self: Self) !void {
302 try self.dbi.put(self.idx, self.head);
304 fn gen(self: Self) !K {
307 const k = try Prng.gen(self.dbi, K);
308 if (!try self.dbi.has(self.item_idx(k))) {
313 pub fn append(self: *Self, v: V) !K {
314 if (self.head.len == 0) {
315 const k = try self.gen();
316 const item = Item{ .data = v };
317 try self.item_put(k, item);
322 try self.head_update();
326 const prev_idx = self.head.last.?;
327 var prev = try self.item_get(prev_idx);
329 const k = try self.gen();
330 const item = Item{ .prev = prev_idx, .data = v };
331 try self.item_put(k, item);
334 try self.item_put(prev_idx, prev);
338 try self.head_update();
343 pub fn get(self: Self, k: K) !V {
344 const item = try self.item_get(k);
347 pub fn del(self: *Self, k: K) !void {
348 const item = try self.item_get(k);
350 if (item.prev != null) {
351 var prev = try self.item_get(item.prev.?);
352 prev.next = item.next;
353 try self.item_put(item.prev.?, prev);
356 if (item.next != null) {
357 var next = try self.item_get(item.next.?);
358 next.prev = item.prev;
359 try self.item_put(item.next.?, next);
362 if (self.head.first == k) self.head.first = item.next;
363 if (self.head.last == k) self.head.last = item.prev;
365 try self.head_update();
367 try self.dbi.del(self.item_idx(k));
369 pub fn clear(self: *Self) !void {
370 var it = self.iterator();
371 while (it.next()) |kv| {
372 try self.del(kv.key);
375 pub fn len(self: Self) usize {
376 return self.head.len;
378 pub const Iterator = struct {
381 dir: enum { Forward, Backward },
383 pub fn next(self: *Iterator) ?struct { key: K, val: V } {
384 if (self.idx != null) {
385 const k = self.idx.?;
386 const item = self.lv.item_get(k) catch return null;
387 self.idx = switch (self.dir) {
388 .Forward => item.next,
389 .Backward => item.prev,
391 return .{ .key = k, .val = item.data };
397 pub fn iterator(self: Self) Iterator {
400 .idx = self.head.first,
404 pub fn reverse_iterator(self: Self) Iterator {
407 .idx = self.head.last,
414 pub fn SetList(comptime K: type, comptime V: type) type {
416 const Self = @This();
417 pub const Index = u64;
420 pub const View = SetListView(K, V);
424 fn open_dbi(txn: lmdb.Txn) !lmdb.Dbi {
425 return try txn.dbi("SetList");
427 pub fn init(txn: lmdb.Txn) !Self {
428 const head = View.Head{};
429 const dbi = try open_dbi(txn);
430 const idx = try Prng.gen(dbi, Index);
431 try dbi.put(idx, head);
432 return .{ .idx = idx };
434 pub fn open(self: Self, txn: lmdb.Txn) !View {
436 if (self.idx == null) {
437 return error.NotInitialized;
440 const dbi = try open_dbi(txn);
441 const head = try dbi.get(self.idx.?, View.Head);
451 pub fn SetListView(comptime K: type, comptime V: type) type {
453 const Self = @This();
454 const ItemIndex = struct { SetList(K, V).Index, K };
456 pub const Head = struct {
461 pub const Item = struct {
468 idx: SetList(K, V).Index,
471 fn item_idx(self: Self, k: K) ItemIndex {
472 return .{ self.idx, k };
474 fn item_get(self: Self, k: K) !Item {
475 return try self.dbi.get(self.item_idx(k), Item);
477 fn item_put(self: Self, k: K, item: Item) !void {
478 try self.dbi.put(self.item_idx(k), item);
480 fn head_update(self: Self) !void {
481 try self.dbi.put(self.idx, self.head);
483 pub fn append(self: *Self, k: K, v: V) !void {
484 if (self.head.len == 0) {
485 const item = Item{ .data = v };
486 try self.item_put(k, item);
491 try self.head_update();
493 const prev_idx = self.head.last.?;
494 var prev = try self.item_get(prev_idx);
496 const item = Item{ .prev = prev_idx, .data = v };
497 try self.item_put(k, item);
500 try self.item_put(prev_idx, prev);
504 try self.head_update();
507 pub fn get(self: Self, k: K) !V {
508 const item = try self.item_get(k);
511 pub fn del(self: *Self, k: K) !void {
512 const item = try self.item_get(k);
514 if (item.prev != null) {
515 var prev = try self.item_get(item.prev.?);
516 prev.next = item.next;
517 try self.item_put(item.prev.?, prev);
520 if (item.next != null) {
521 var next = try self.item_get(item.next.?);
522 next.prev = item.prev;
523 try self.item_put(item.next.?, next);
526 if (self.head.first == k) self.head.first = item.next;
527 if (self.head.last == k) self.head.last = item.prev;
529 try self.head_update();
531 try self.dbi.del(self.item_idx(k));
533 pub fn clear(self: *Self) !void {
534 var it = self.iterator();
535 while (it.next()) |kv| {
536 try self.del(kv.key);
539 pub fn has(self: Self, k: K) !bool {
540 return self.dbi.has(self.item_idx(k));
542 pub fn len(self: Self) usize {
543 return self.head.len;
545 pub const Iterator = struct {
546 slv: SetListView(K, V),
548 dir: enum { Forward, Backward },
550 pub fn next(self: *Iterator) ?struct { key: K, val: V } {
551 if (self.idx != null) {
552 const k = self.idx.?;
553 const item = self.slv.item_get(k) catch return null;
554 self.idx = switch (self.dir) {
555 .Forward => item.next,
556 .Backward => item.prev,
558 return .{ .key = k, .val = item.data };
564 pub fn iterator(self: Self) Iterator {
567 .idx = self.head.first,
571 pub fn reverse_iterator(self: Self) Iterator {
574 .idx = self.head.last,
581 const DB_SIZE = 1024 * 1024 * 1;
584 const env = try lmdb.Env.open("db", DB_SIZE);
587 const txn = try env.txn();
588 defer txn.commit() catch {};
590 var db = try Db(u32, u32).init(txn, "123");
592 if (try db.has(123)) {
597 std.debug.print("n: {}\n", .{n});
601 // const env = try lmdb.Env.open("db", DB_SIZE);
602 // defer env.close();
604 // const txn = try env.txn();
605 // defer txn.commit();
607 // const db = List.init(txn, "b", u32);
611 var env = try lmdb.Env.open("db", 1024 * 1024 * 1);
615 var txn = try env.txn();
616 defer txn.commit() catch {};
618 var dbi = try txn.dbi("abc");
624 var a: A = undefined;
625 const a_idx: u64 = 27;
626 if (try dbi.has(a_idx)) {
627 a = try dbi.get(a_idx, A);
629 a = A{ .ml = try Set(usize).init(txn) };
630 try dbi.put(a_idx, a);
633 var ml = try a.ml.open(txn);
635 const len = ml.len();
636 std.debug.print("{}\n", .{len});
638 std.debug.print("{}\n", .{try ml.has(len)});
639 var it = ml.iterator();
640 while (it.next()) |i| {
641 std.debug.print("{}\n", .{i});
646 var env = try lmdb.Env.open("db", 1024 * 1024 * 1);
650 var txn = try env.txn();
651 defer txn.commit() catch {};
653 var dbi = try txn.dbi("def");
659 var a: A = undefined;
660 const a_idx: u64 = 27;
661 if (try dbi.has(a_idx)) {
662 a = try dbi.get(a_idx, A);
664 a = A{ .ml = try List(usize).init(txn) };
665 try dbi.put(a_idx, a);
668 var ml = try a.ml.open(txn);
670 const len = ml.len();
671 std.debug.print("{}\n", .{len});
672 const newest = try ml.append(len * 10);
673 std.debug.print("{}: {}\n", .{ newest, try ml.get(newest) });
674 var it = ml.iterator();
675 while (it.next()) |i| {
676 std.debug.print("{}: {}\n", .{ i.key, i.val });
681 var env = try lmdb.Env.open("db", 1024 * 1024 * 1);
685 var txn = try env.txn();
686 defer txn.commit() catch {};
688 var dbi = try txn.dbi("ghi");
691 ml: SetList(usize, usize),
694 var a: A = undefined;
695 const a_idx: u64 = 27;
696 if (try dbi.has(a_idx)) {
697 a = try dbi.get(a_idx, A);
699 a = A{ .ml = try SetList(usize, usize).init(txn) };
700 try dbi.put(a_idx, a);
703 var ml = try a.ml.open(txn);
705 const len = ml.len();
706 std.debug.print("{}\n", .{len});
707 try ml.append(len, len * 10);
708 std.debug.print("{}\n", .{try ml.get(len)});
709 var it = ml.iterator();
710 while (it.next()) |i| {
711 std.debug.print("{}: {}\n", .{ i.key, i.val });