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)) {
75 fn SetListBase(comptime K: type, comptime V: type) type {
78 pub const Index = u64;
81 pub const View = SetListViewBase(K, V);
85 fn open_dbi(txn: lmdb.Txn) !lmdb.Dbi {
86 return try txn.dbi("SetList");
88 pub fn init(txn: lmdb.Txn) !Self {
89 const head = View.Head{};
90 const dbi = try open_dbi(txn);
91 const idx = try Prng.gen(dbi, Index);
92 try dbi.put(idx, head);
93 return .{ .idx = idx };
95 pub fn open(self: Self, txn: lmdb.Txn) !View {
97 if (self.idx == null) {
98 return error.NotInitialized;
101 const dbi = try open_dbi(txn);
102 const head = try dbi.get(self.idx.?, View.Head);
112 fn SetListViewBase(comptime K: type, comptime V: type) type {
114 const Self = @This();
115 pub const ItemIndex = struct { SetListBase(K, V).Index, Key };
119 pub const Head = struct {
124 pub const Item = struct {
131 idx: SetListBase(K, V).Index,
134 fn item_idx(self: Self, k: K) ItemIndex {
135 return .{ self.idx, k };
137 fn item_get(self: Self, k: K) !Item {
138 return try self.dbi.get(self.item_idx(k), Item);
140 fn item_put(self: Self, k: K, item: Item) !void {
141 try self.dbi.put(self.item_idx(k), item);
143 fn head_update(self: Self) !void {
144 try self.dbi.put(self.idx, self.head);
146 pub fn del(self: *Self, k: K) !void {
147 const item = try self.item_get(k);
149 if (item.prev != null) {
150 var prev = try self.item_get(item.prev.?);
151 prev.next = item.next;
152 try self.item_put(item.prev.?, prev);
155 if (item.next != null) {
156 var next = try self.item_get(item.next.?);
157 next.prev = item.prev;
158 try self.item_put(item.next.?, next);
161 if (self.head.first == k) self.head.first = item.next;
162 if (self.head.last == k) self.head.last = item.prev;
164 try self.head_update();
166 try self.dbi.del(self.item_idx(k));
168 pub fn clear(self: *Self) !void {
169 var it = self.iterator();
170 while (it.next()) |kv| {
171 try self.del(kv.key);
174 pub fn len(self: Self) usize {
175 return self.head.len;
177 pub fn append(self: *Self, key: Key, val: Val) !void {
178 if (self.head.len == 0) {
179 const item = Item{ .data = val };
180 try self.item_put(key, item);
183 self.head.first = key;
184 self.head.last = key;
185 try self.head_update();
187 const prev_idx = self.head.last.?;
188 var prev = try self.item_get(prev_idx);
190 const item = Item{ .prev = prev_idx, .data = val };
191 try self.item_put(key, item);
194 try self.item_put(prev_idx, prev);
196 self.head.last = key;
198 try self.head_update();
201 pub fn get(self: Self, key: Key) !Val {
202 const item = try self.item_get(key);
205 pub fn has(self: Self, key: Key) !bool {
206 return self.dbi.has(self.item_idx(key));
208 pub const Iterator = struct {
209 pub const Result = ?struct { key: K, val: V };
211 slv: SetListViewBase(K, V),
213 dir: enum { Forward, Backward },
215 pub fn next(self: *Iterator) Result {
216 if (self.idx != null) {
217 const k = self.idx.?;
218 const item = self.slv.item_get(k) catch return null;
219 self.idx = switch (self.dir) {
220 .Forward => item.next,
221 .Backward => item.prev,
223 return .{ .key = k, .val = item.data };
229 pub fn iterator(self: Self) Iterator {
232 .idx = self.head.first,
236 pub fn reverse_iterator(self: Self) Iterator {
239 .idx = self.head.last,
246 pub fn Set(comptime K: type) type {
249 pub const Val = void;
251 pub const Base = SetListBase(Key, Val);
252 pub const View = struct {
253 const ViewBase = SetListViewBase(Key, Val);
257 pub fn del(self: *@This(), key: Key) !void {
258 try self.base.del(key);
260 pub fn clear(self: *@This()) !void {
261 try self.base.clear();
263 pub fn len(self: @This()) usize {
264 return self.base.len();
266 pub fn append(self: *@This(), key: Key) !void {
267 try self.base.append(key, {});
269 pub fn has(self: @This(), key: Key) !bool {
270 return try self.base.has(key);
272 pub fn iterator(self: @This()) ViewBase.Iterator {
273 return self.base.iterator();
275 pub fn reverse_iterator(self: @This()) ViewBase.Iterator {
276 return self.base.reverse_iterator();
282 pub fn init(txn: lmdb.Txn) !@This() {
283 return .{ .base = try Base.init(txn) };
285 pub fn open(self: @This(), txn: lmdb.Txn) !View {
286 return .{ .base = try self.base.open(txn) };
291 pub fn List(comptime V: type) type {
296 pub const Base = SetListBase(Key, Val);
297 pub const View = struct {
298 const ViewBase = SetListViewBase(Key, Val);
302 fn gen(self: @This()) !Key {
305 const key = try Prng.gen(self.base.dbi, Key);
306 if (!try self.base.dbi.has(self.base.item_idx(key))) {
311 pub fn del(self: *@This(), key: Key) !void {
312 try self.base.del(key);
314 pub fn clear(self: *@This()) !void {
315 try self.base.clear();
317 pub fn len(self: @This()) usize {
318 return self.base.len();
320 pub fn append(self: *@This(), val: Val) !Key {
321 const key = try self.gen();
322 try self.base.append(key, val);
325 pub fn get(self: @This(), key: Key) !Val {
326 return try self.base.get(key);
328 pub fn has(self: @This(), key: Key) !bool {
329 return try self.base.has(key);
331 pub fn iterator(self: @This()) ViewBase.Iterator {
332 return self.base.iterator();
334 pub fn reverse_iterator(self: @This()) ViewBase.Iterator {
335 return self.base.reverse_iterator();
341 pub fn init(txn: lmdb.Txn) !@This() {
342 return .{ .base = try Base.init(txn) };
344 pub fn open(self: @This(), txn: lmdb.Txn) !View {
345 return .{ .base = try self.base.open(txn) };
350 pub fn SetList(comptime K: type, comptime V: type) type {
355 pub const Base = SetListBase(Key, Val);
356 pub const View = struct {
357 const ViewBase = SetListViewBase(Key, Val);
361 pub fn del(self: *@This(), key: Key) !void {
362 try self.base.del(key);
364 pub fn clear(self: *@This()) !void {
365 try self.base.clear();
367 pub fn len(self: @This()) usize {
368 return self.base.len();
370 pub fn append(self: *@This(), key: Key, val: Val) !void {
371 try self.base.append(key, val);
373 pub fn get(self: @This(), key: Key) !Val {
374 return try self.base.get(key);
376 pub fn has(self: @This(), key: Key) !bool {
377 return try self.base.has(key);
379 pub fn iterator(self: @This()) ViewBase.Iterator {
380 return self.base.iterator();
382 pub fn reverse_iterator(self: @This()) ViewBase.Iterator {
383 return self.base.reverse_iterator();
389 pub fn init(txn: lmdb.Txn) !@This() {
390 return .{ .base = try Base.init(txn) };
392 pub fn open(self: @This(), txn: lmdb.Txn) !View {
393 return .{ .base = try self.base.open(txn) };
398 const DB_SIZE = 1024 * 1024 * 1;
401 const env = try lmdb.Env.open("db", DB_SIZE);
404 const txn = try env.txn();
405 defer txn.commit() catch {};
407 var db = try Db(u32, u32).init(txn, "123");
409 if (try db.has(123)) {
414 std.debug.print("n: {}\n", .{n});
418 // const env = try lmdb.Env.open("db", DB_SIZE);
419 // defer env.close();
421 // const txn = try env.txn();
422 // defer txn.commit();
424 // const db = List.init(txn, "b", u32);
428 var env = try lmdb.Env.open("db", 1024 * 1024 * 1);
432 var txn = try env.txn();
433 defer txn.commit() catch {};
435 var dbi = try txn.dbi("abc");
441 var a: A = undefined;
442 const a_idx: u64 = 27;
443 if (try dbi.has(a_idx)) {
444 a = try dbi.get(a_idx, A);
446 a = A{ .ml = try Set(usize).init(txn) };
447 try dbi.put(a_idx, a);
450 var ml = try a.ml.open(txn);
452 const len = ml.len();
453 std.debug.print("{}\n", .{len});
455 std.debug.print("{}\n", .{try ml.has(len)});
456 var it = ml.iterator();
457 while (it.next()) |i| {
458 std.debug.print("{}\n", .{i});
463 var env = try lmdb.Env.open("db", 1024 * 1024 * 1);
467 var txn = try env.txn();
468 defer txn.commit() catch {};
470 var dbi = try txn.dbi("def");
476 var a: A = undefined;
477 const a_idx: u64 = 27;
478 if (try dbi.has(a_idx)) {
479 a = try dbi.get(a_idx, A);
481 a = A{ .ml = try List(usize).init(txn) };
482 try dbi.put(a_idx, a);
485 var ml = try a.ml.open(txn);
487 const len = ml.len();
488 std.debug.print("{}\n", .{len});
489 const newest = try ml.append(len * 10);
490 std.debug.print("{}: {}\n", .{ newest, try ml.get(newest) });
491 var it = ml.iterator();
492 while (it.next()) |i| {
493 std.debug.print("{}: {}\n", .{ i.key, i.val });
498 var env = try lmdb.Env.open("db", 1024 * 1024 * 1);
502 var txn = try env.txn();
503 defer txn.commit() catch {};
505 var dbi = try txn.dbi("ghi");
508 ml: SetList(usize, usize),
511 var a: A = undefined;
512 const a_idx: u64 = 27;
513 if (try dbi.has(a_idx)) {
514 a = try dbi.get(a_idx, A);
516 a = A{ .ml = try SetList(usize, usize).init(txn) };
517 try dbi.put(a_idx, a);
520 var ml = try a.ml.open(txn);
522 const len = ml.len();
523 std.debug.print("{}\n", .{len});
524 try ml.append(len, len * 10);
525 std.debug.print("{}\n", .{try ml.get(len)});
526 var it = ml.iterator();
527 while (it.next()) |i| {
528 std.debug.print("{}: {}\n", .{ i.key, i.val });