]> gitweb.ps.run Git - ziglmdb/commitdiff
update
authorpatrick-scho <patrick.schoenberger@posteo.de>
Wed, 13 Nov 2024 21:02:51 +0000 (22:02 +0100)
committerpatrick-scho <patrick.schoenberger@posteo.de>
Wed, 13 Nov 2024 21:02:51 +0000 (22:02 +0100)
src/lmdb.zig [new file with mode: 0644]
src/main.zig [deleted file]

diff --git a/src/lmdb.zig b/src/lmdb.zig
new file mode 100644 (file)
index 0000000..8cc91f4
--- /dev/null
@@ -0,0 +1,360 @@
+const std = @import("std");
+const lmdb = @cImport(@cInclude("lmdb.h"));
+
+pub usingnamespace lmdb;
+
+pub fn Cursor(comptime K: type, comptime V: type) type {
+    return struct {
+        const Self = @This();
+
+        pub const Flags = enum(c_uint) {
+            First = lmdb.MDB_FIRST,
+            FirstDup = lmdb.MDB_FIRST_DUP,
+            GetBoth = lmdb.MDB_GET_BOTH,
+            GetBothRange = lmdb.MDB_GET_BOTH_RANGE,
+            GetCurrent = lmdb.MDB_GET_CURRENT,
+            GetMultiple = lmdb.MDB_GET_MULTIPLE,
+            Last = lmdb.MDB_LAST,
+            LastDup = lmdb.MDB_LAST_DUP,
+            Next = lmdb.MDB_NEXT,
+            NextDup = lmdb.MDB_NEXT_DUP,
+            NextMultiple = lmdb.MDB_NEXT_MULTIPLE,
+            NextNodup = lmdb.MDB_NEXT_NODUP,
+            Prev = lmdb.MDB_PREV,
+            PrevDup = lmdb.MDB_PREV_DUP,
+            PrevNodup = lmdb.MDB_PREV_NODUP,
+            Set = lmdb.MDB_SET,
+            SetKey = lmdb.MDB_SET_KEY,
+            SetRange = lmdb.MDB_SET_RANGE,
+        };
+
+        ptr: ?*lmdb.MDB_cursor = undefined,
+
+        pub fn close(self: *Self) void {
+            _ = lmdb.mdb_cursor_close(self.ptr);
+        }
+
+        pub fn put(self: *Self, k: K, v: V) void {
+            var key = lmdb.MDB_val{
+                .mv_size = @sizeOf(@TypeOf(k)),
+                .mv_data = @constCast(@ptrCast(&k)),
+            };
+            var val = lmdb.MDB_val{
+                .mv_size = @sizeOf(@TypeOf(v)),
+                .mv_data = @constCast(@ptrCast(&v)),
+            };
+            switch (lmdb.mdb_cursor_put(self.ptr, &key, &val, 0)) {
+                0 => {},
+                else => |err| {
+                    std.debug.print("put err: {}\n", .{err});
+                },
+            }
+        }
+
+        pub fn get(self: *Self, k: *K, flags: Flags) ?V {
+            var key = lmdb.MDB_val{
+                .mv_size = @sizeOf(K),
+                .mv_data = @constCast(@ptrCast(k)),
+            };
+            var val: lmdb.MDB_val = undefined;
+            return switch (lmdb.mdb_cursor_get(self.ptr, &key, &val, @intFromEnum(flags))) {
+                0 => {
+                    k.* = @as(*align(1) K, @ptrCast(key.mv_data)).*;
+                    return @as(?*align(1) V, @ptrCast(val.mv_data)).?.*;
+                },
+                lmdb.MDB_NOTFOUND => null,
+                else => |err| {
+                    std.debug.print("get err: {}\n", .{err});
+                    return null;
+                },
+            };
+        }
+
+        pub fn del(self: *Self, k: K) void {
+            var key = lmdb.MDB_val{
+                .mv_size = @sizeOf(@TypeOf(k)),
+                .mv_data = @constCast(@ptrCast(&k)),
+            };
+            switch (lmdb.mdb_cursor_del(self.ptr, &key, 0)) {
+                0 => {},
+                else => |err| {
+                    std.debug.print("del err: {}\n", .{err});
+                },
+            }
+        }
+
+        pub fn has(self: *Dbi, k: K, flags: Flags) bool {
+            return self.get(k, flags) != null;
+        }
+    };
+}
+
+pub fn Dbi(comptime K: type, comptime V: type) type {
+    return struct {
+        const Self = @This();
+
+        ptr: lmdb.MDB_dbi = undefined,
+        txn: *const Txn = undefined,
+        env: *const Env = undefined,
+
+        pub fn close(self: Self) void {
+
+            // TODO: necessary?
+            lmdb.mdb_dbi_close(self.env.ptr, self.ptr);
+        }
+
+        pub fn cursor(self: Self) !Cursor(K, V) {
+            var result = Cursor(K, V){};
+
+            return switch (lmdb.mdb_cursor_open(self.txn.ptr, self.ptr, &result.ptr)) {
+                0 => result,
+                else => error.CursorOpen,
+            };
+        }
+
+        pub fn put(self: Self, k: K, v: V) void {
+            var key = lmdb.MDB_val{
+                .mv_size = @sizeOf(@TypeOf(k)),
+                .mv_data = @constCast(@ptrCast(&k)),
+            };
+            var val = lmdb.MDB_val{
+                .mv_size = @sizeOf(@TypeOf(v)),
+                .mv_data = @constCast(@ptrCast(&v)),
+            };
+            switch (lmdb.mdb_put(self.txn.ptr, self.ptr, &key, &val, 0)) {
+                0 => {},
+                else => |err| {
+                    std.debug.print("put err: {}\n", .{err});
+                },
+            }
+        }
+
+        pub fn get(self: Self, k: K) ?V {
+            var key = lmdb.MDB_val{
+                .mv_size = @sizeOf(@TypeOf(k)),
+                .mv_data = @constCast(@ptrCast(&k)),
+            };
+            var val: lmdb.MDB_val = undefined;
+            return switch (lmdb.mdb_get(self.txn.ptr, self.ptr, &key, &val)) {
+                0 => @as(?*align(1) V, @ptrCast(val.mv_data)).?.*,
+                else => |err| {
+                    std.debug.print("get err: {}\n", .{err});
+                    return null;
+                },
+            };
+        }
+
+        pub fn del(self: Self, k: K) void {
+            var key = lmdb.MDB_val{
+                .mv_size = @sizeOf(@TypeOf(k)),
+                .mv_data = @constCast(@ptrCast(&k)),
+            };
+            switch (lmdb.mdb_del(self.txn.ptr, self.ptr, &key, null)) {
+                0 => {},
+                else => |err| {
+                    std.debug.print("del err: {}\n", .{err});
+                },
+            }
+        }
+
+        pub fn has(self: Self, k: K) bool {
+            return self.get(k) != null;
+        }
+    };
+}
+
+pub const Txn = struct {
+    ptr: ?*lmdb.MDB_txn = undefined,
+    env: *const Env = undefined,
+
+    pub fn dbi(self: *const Txn, name: [*c]const u8, comptime K: type, comptime V: type) !Dbi(K, V) {
+        var result = Dbi(K, V){ .env = self.env, .txn = self };
+        // TODO: lmdb.MDB_INTEGERKEY?
+        switch (lmdb.mdb_dbi_open(self.ptr, name, lmdb.MDB_CREATE, &result.ptr)) {
+            0 => return result,
+            else => |err| {
+                std.debug.print("dbi err: {}\n", .{err});
+                return error.DbiOpen;
+            },
+        }
+    }
+
+    pub fn commit(self: Txn) void {
+        switch (lmdb.mdb_txn_commit(self.ptr)) {
+            0 => {},
+            lmdb.MDB_MAP_FULL => {
+                std.debug.print("resize\n", .{});
+                _ = lmdb.mdb_env_set_mapsize(self.env.ptr, 0);
+            },
+            else => |err| {
+                std.debug.print("commit err: {}\n", .{err});
+            },
+        }
+    }
+
+    pub fn abort(self: Txn) void {
+        lmdb.mdb_txn_abort(self.ptr);
+    }
+};
+
+pub const Env = struct {
+    ptr: ?*lmdb.MDB_env = undefined,
+
+    pub fn open(name: [*c]const u8, size: lmdb.mdb_size_t) Env {
+        var result = Env{};
+
+        _ = lmdb.mdb_env_create(&result.ptr);
+        _ = lmdb.mdb_env_set_maxdbs(result.ptr, 10);
+        _ = lmdb.mdb_env_set_mapsize(result.ptr, size);
+        _ = lmdb.mdb_env_open(result.ptr, name, lmdb.MDB_WRITEMAP, 0o664);
+        // _ = lmdb.mdb_env_open(result.ptr, name, lmdb.MDB_NOSYNC | lmdb.MDB_WRITEMAP, 0o664);
+
+        return result;
+    }
+
+    pub fn close(self: Env) void {
+        lmdb.mdb_env_close(self.ptr);
+    }
+
+    pub fn txn(self: *const Env) !Txn {
+        var result = Txn{ .env = self };
+        switch (lmdb.mdb_txn_begin(self.ptr, null, 0, &result.ptr)) {
+            0 => return result,
+            else => |err| {
+                std.debug.print("txn err: {}\n", .{err});
+                return error.TxnOpen;
+            },
+        }
+    }
+
+    pub fn sync(self: *Env) void {
+        switch (lmdb.mdb_env_sync(self.ptr, 1)) {
+            0 => {},
+            else => |err| {
+                std.debug.print("sync err: {}\n", .{err});
+            },
+        }
+    }
+};
+
+test "basic" {
+    var env = Env.open("db", 1024 * 1024 * 1);
+
+    var txn = try env.txn();
+
+    const Value = struct {
+        i: i64 = 123,
+        s: [16]u8 = undefined,
+    };
+
+    var dbi = try txn.dbi("abc", u64, Value);
+
+    var val = dbi.get(1) orelse Value{ .i = 5 };
+    std.debug.print("{}\n", .{val});
+
+    val.i += 1;
+
+    dbi.put(1, val);
+
+    txn.commit();
+    dbi.close();
+    env.sync();
+    env.close();
+}
+
+test "cursor" {
+    var env = Env.open("db", 1024 * 1024 * 1);
+
+    var txn = try env.txn();
+
+    const Value = struct {
+        i: i64 = 123,
+        s: [16]u8 = undefined,
+    };
+
+    var dbi = try txn.dbi("def", u64, Value);
+
+    for (0..10) |i| {
+        dbi.put(i, Value{ .i = @intCast(i + 23) });
+    }
+
+    var cursor = try dbi.cursor();
+
+    var key: u64 = undefined;
+    {
+        const val = cursor.get(&key, .First);
+        std.debug.print("{}: {?}\n", .{ key, val });
+    }
+
+    while (cursor.get(&key, .Next)) |val| {
+        std.debug.print("{}: {?}\n", .{ key, val });
+    }
+
+    cursor.close();
+
+    txn.commit();
+    dbi.close();
+    env.sync();
+    env.close();
+}
+
+// pub fn get(txn: ?*lmdb.MDB_txn, dbi: lmdb.MDB_dbi, k: anytype, comptime T: type) ?T {
+//     var key = lmdb.MDB_val{
+//         .mv_size = @sizeOf(@TypeOf(k)),
+//         .mv_data = @constCast(@ptrCast(&k)),
+//     };
+//     var val: lmdb.MDB_val = undefined;
+//     return switch (lmdb.mdb_get(txn, dbi, &key, &val)) {
+//         0 => @as(?*align(1) T, @alignCast(@ptrCast(val.mv_data))).?.*,
+//         else => |err| {
+//             std.debug.print("get err: {}\n", .{err});
+//             return null;
+//         },
+//     };
+// }
+
+// pub fn put(txn: ?*lmdb.MDB_txn, dbi: lmdb.MDB_dbi, k: anytype, v: anytype) void {
+//     var key = lmdb.MDB_val{
+//         .mv_size = @sizeOf(@TypeOf(k)),
+//         .mv_data = @constCast(@ptrCast(&k)),
+//     };
+//     var val = lmdb.MDB_val{
+//         .mv_size = @sizeOf(@TypeOf(v)),
+//         .mv_data = @constCast(@ptrCast(&v)),
+//     };
+//     switch (lmdb.mdb_put(txn, dbi, &key, &val, 0)) {
+//         0 => {},
+//         else => |err| {
+//             std.debug.print("put err: {}\n", .{err});
+//         },
+//     }
+// }
+
+// pub fn del(txn: ?*lmdb.MDB_txn, dbi: lmdb.MDB_dbi, k: anytype) void {
+//     var key = lmdb.MDB_val{
+//         .mv_size = @sizeOf(@TypeOf(k)),
+//         .mv_data = @constCast(@ptrCast(&k)),
+//     };
+//     switch (lmdb.mdb_del(txn, dbi, &key, null)) {
+//         0 => {},
+//         else => |err| {
+//             std.debug.print("del err: {}\n", .{err});
+//         },
+//     }
+// }
+
+// pub fn has(txn: ?*lmdb.MDB_txn, dbi: lmdb.MDB_dbi, k: anytype) bool {
+//     var key = lmdb.MDB_val{
+//         .mv_size = @sizeOf(@TypeOf(k)),
+//         .mv_data = @constCast(@ptrCast(&k)),
+//     };
+//     var val: lmdb.MDB_val = undefined;
+//     return switch (lmdb.mdb_get(txn, dbi, &key, &val)) {
+//         0 => true,
+//         lmdb.MDB_NOTFOUND => false,
+//         else => |err| {
+//             std.debug.print("has err: {}\n", .{err});
+//             return false;
+//         },
+//     };
+// }
diff --git a/src/main.zig b/src/main.zig
deleted file mode 100644 (file)
index a9ad1ba..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-const std = @import("std");
-const lmdb = @cImport(@cInclude("lmdb.h"));
-
-const print = std.debug.print;
-
-fn get(txn: ?*lmdb.MDB_txn, dbi: lmdb.MDB_dbi, k: anytype, comptime T: type) ?T {
-    var key = lmdb.MDB_val{
-        .mv_size = @sizeOf(@TypeOf(k)),
-        .mv_data = @constCast(@ptrCast(&k)),
-    };
-    var val: lmdb.MDB_val = undefined;
-    return switch (lmdb.mdb_get(txn, dbi, &key, &val)) {
-        0 => @as(*T, @ptrFromInt(@intFromPtr(val.mv_data))).*,
-        else => |err| {
-            _ = err;
-            // print("get err: {}\n", .{err});
-            return null;
-        },
-    };
-}
-
-fn put(txn: ?*lmdb.MDB_txn, dbi: lmdb.MDB_dbi, k: anytype, v: anytype) void {
-    var key = lmdb.MDB_val{
-        .mv_size = @sizeOf(@TypeOf(k)),
-        .mv_data = @constCast(@ptrCast(&k)),
-    };
-    var val = lmdb.MDB_val{
-        .mv_size = @sizeOf(@TypeOf(v)),
-        .mv_data = @constCast(@ptrCast(&v)),
-    };
-    switch (lmdb.mdb_put(txn, dbi, &key, &val, 0)) {
-        0 => {},
-        else => |err| {
-            print("put err: {}\n", .{err});
-        },
-    }
-}
-
-pub fn main() void {
-    var env: ?*lmdb.MDB_env = undefined;
-    _ = lmdb.mdb_env_create(&env);
-    _ = lmdb.mdb_env_set_maxdbs(env, 10);
-    _ = lmdb.mdb_env_set_mapsize(env, 1024 * 1024 * 120);
-    _ = lmdb.mdb_env_open(env, "./db1", lmdb.MDB_NOSYNC | lmdb.MDB_WRITEMAP, 0o664);
-    defer lmdb.mdb_env_close(env);
-
-    for (0..1000000) |i| {
-        var txn: ?*lmdb.MDB_txn = undefined;
-        switch (lmdb.mdb_txn_begin(env, null, 0, &txn)) {
-            0 => {},
-            else => |err| {
-                print("txn err: {}\n", .{err});
-            },
-        }
-
-        var db: lmdb.MDB_dbi = undefined;
-        _ = lmdb.mdb_dbi_open(txn, "subdb2", lmdb.MDB_CREATE | lmdb.MDB_INTEGERKEY, &db);
-        if (i == 0) {
-            var db_stat: lmdb.MDB_stat = undefined;
-            _ = lmdb.mdb_stat(txn, db, &db_stat);
-            // print("{}\n", .{db_stat});
-        }
-        defer lmdb.mdb_dbi_close(env, db);
-
-        const Val = struct {
-            a: u64,
-            b: i64,
-            c: [16]u8,
-        };
-
-        var new_val = Val{
-            .a = 123,
-            .b = -123,
-            .c = undefined,
-        };
-        std.mem.copyForwards(u8, &new_val.c, "a c efghabcdefgh");
-
-        const key: u64 = i + 1000;
-        if (get(txn, db, key, Val)) |val| {
-            if (i % 100000 == 0) {
-                print("{}: {}\n", .{ i, val });
-            }
-            new_val = val;
-            new_val.a += 1;
-            new_val.b -= 1;
-            std.mem.copyForwards(u8, &new_val.c, "a c efghabcdefgh");
-        } else {
-            if (i % 100000 == 0) {
-                print("not found\n", .{});
-            }
-        }
-
-        put(txn, db, key, new_val);
-
-        switch (lmdb.mdb_txn_commit(txn)) {
-            0 => {},
-            lmdb.MDB_MAP_FULL => {
-                print("resize\n", .{});
-                _ = lmdb.mdb_env_set_mapsize(env, 0);
-            },
-            else => |err| {
-                print("commit err: {}\n", .{err});
-            },
-        }
-    }
-
-    switch (lmdb.mdb_env_sync(env, 1)) {
-        0 => {},
-        else => |err| {
-            print("sync err: {}\n", .{err});
-        },
-    }
-
-    // var env_info: lmdb.MDB_envinfo = undefined;
-    // _ = lmdb.mdb_env_info(env, &env_info);
-
-    // var env_stat: lmdb.MDB_stat = undefined;
-    // _ = lmdb.mdb_env_stat(env, &env_stat);
-
-    // print("{}\n", .{env_info});
-    // print("{}\n", .{env_stat});
-
-    print("done!\n", .{});
-}
-
-test "hash" {
-    const pw = "affeaffe";
-
-    var hash_buffer: [128]u8 = undefined;
-
-    var buffer: [1024 * 1024]u8 = undefined;
-    var alloc = std.heap.FixedBufferAllocator.init(&buffer);
-
-    const result = try std.crypto.pwhash.argon2.strHash(pw, .{
-        .allocator = alloc.allocator(),
-        .params = std.crypto.pwhash.argon2.Params.fromLimits(1000, 1024 * 10),
-    }, &hash_buffer);
-
-    print("{s}\n", .{result});
-
-    if (std.crypto.pwhash.argon2.strVerify(result, "affeaffe", .{
-        .allocator = alloc.allocator(),
-    })) {
-        print("verified\n", .{});
-    } else |err| {
-        print("not verified: {}\n", .{err});
-    }
-}