rename project to MultiforaDB
Prose and benchmark tables use MultiforaDB; the binary, the CLI usage line, the log-message prefix and the default database file use multiforadb. Two consequences worth noting: - build.zig.zon's fingerprint is derived from the package name, so it had to change with it (Zig refuses to build otherwise). A consumer pinning this package by fingerprint needs updating. - the default --db path is now multiforadb.log, and getCmdLineOpts reports it as dbpath. An existing mongo-lite.log has to be passed explicitly with --db. The e2e harness abbreviated the old name as ML_; that is now MFDB_, including the documented ML_BIN override (MFDB_BIN) and the scratch file names. MD_ (mongod) is untouched. compare-run.sh spawned the server by absolute path under a sandbox/mongo-lite directory that no longer exists; that block already runs from tests/e2e, so it uses a relative path now. The archived reports under tests/e2e/results/ keep the old name: they record what the old binary measured.
This commit is contained in:
@@ -17,14 +17,14 @@ const std = @import("std");
|
||||
|
||||
/// Panic unless `ok`. Active in every optimize mode; see the module comment.
|
||||
pub fn assert(ok: bool) void {
|
||||
if (!ok) @panic("mongo-lite: assertion failed");
|
||||
if (!ok) @panic("multiforadb: assertion failed");
|
||||
}
|
||||
|
||||
/// Panic unless `ok`, naming the invariant that broke. Prefer this where the
|
||||
/// condition alone does not say what went wrong -- the message lands in the
|
||||
/// crash output, which may be all an operator has to go on.
|
||||
pub fn assert_msg(ok: bool, comptime message: []const u8) void {
|
||||
if (!ok) @panic("mongo-lite: assertion failed: " ++ message);
|
||||
if (!ok) @panic("multiforadb: assertion failed: " ++ message);
|
||||
}
|
||||
|
||||
test "assert passes on true and is callable in every mode" {
|
||||
|
||||
@@ -170,7 +170,7 @@ pub fn dispatch(ctx: *Context, msg: *wire.Message, reply: *wire.Reply) !void {
|
||||
// rather than turning an applied write into an error the client retries.
|
||||
if (ctx.engine.take_compact()) {
|
||||
ctx.engine.compact() catch |err| {
|
||||
std.debug.print("mongo-lite: compaction failed: {s}\n", .{@errorName(err)});
|
||||
std.debug.print("multiforadb: compaction failed: {s}\n", .{@errorName(err)});
|
||||
ctx.engine.request_compact();
|
||||
};
|
||||
}
|
||||
@@ -226,7 +226,7 @@ fn cmd_ping(_: *Context, _: *wire.Message, reply: *wire.Reply) !void {
|
||||
|
||||
fn cmd_build_info(_: *Context, _: *wire.Message, reply: *wire.Reply) !void {
|
||||
try reply.put("version", .{ .string = "4.4.0" });
|
||||
try reply.put("gitVersion", .{ .string = "mongo-lite" });
|
||||
try reply.put("gitVersion", .{ .string = "multiforadb" });
|
||||
try reply.put("versionArray", .{ .array = try int_array(reply, &.{ 4, 4, 0, 0 }) });
|
||||
try reply.put("openssl", .{ .doc = &.{} });
|
||||
try reply.put("loaderFlags", .{ .string = "" });
|
||||
@@ -283,7 +283,7 @@ fn cmd_host_info(ctx: *Context, _: *wire.Message, reply: *wire.Reply) !void {
|
||||
|
||||
fn cmd_get_cmd_line_opts(_: *Context, _: *wire.Message, reply: *wire.Reply) !void {
|
||||
const argv = try reply.arena_alloc().alloc(bson.Pair, 2);
|
||||
argv[0] = .{ .key = "dbpath", .value = .{ .string = "mongo-lite.log" } };
|
||||
argv[0] = .{ .key = "dbpath", .value = .{ .string = "multiforadb.log" } };
|
||||
argv[1] = .{ .key = "port", .value = .{ .int32 = 27017 } };
|
||||
try reply.put("argv", .{ .array = &.{} });
|
||||
try reply.put("parsed", .{ .doc = argv });
|
||||
|
||||
10
src/db.zig
10
src/db.zig
@@ -986,7 +986,7 @@ pub const Engine = struct {
|
||||
// epilogue called us.
|
||||
self.request_compact();
|
||||
std.debug.print(
|
||||
"mongo-lite: compaction gave up after {d} attempts (concurrent writes); will retry\n",
|
||||
"multiforadb: compaction gave up after {d} attempts (concurrent writes); will retry\n",
|
||||
.{attempt_max},
|
||||
);
|
||||
}
|
||||
@@ -1045,7 +1045,7 @@ pub const Engine = struct {
|
||||
while (doc_it.next()) |doc_entry| {
|
||||
ix.append_doc_entries(self.gpa, coll.doc_bytes(doc_entry.value_ptr.*), doc_entry.key_ptr.*) catch |err| switch (err) {
|
||||
error.ParallelArrays => {
|
||||
std.debug.print("mongo-lite: WARNING: index '{s}' cannot index an existing document; entry skipped\n", .{ix.name});
|
||||
std.debug.print("multiforadb: WARNING: index '{s}' cannot index an existing document; entry skipped\n", .{ix.name});
|
||||
continue;
|
||||
},
|
||||
else => return err,
|
||||
@@ -1053,7 +1053,7 @@ pub const Engine = struct {
|
||||
}
|
||||
// Tolerated, not enforced: the database must always open.
|
||||
if (try ix.finish_bulk(self.gpa, false)) {
|
||||
std.debug.print("mongo-lite: WARNING: unique index '{s}' has duplicate keys in existing data; duplicates not enforced for existing documents\n", .{ix.name});
|
||||
std.debug.print("multiforadb: WARNING: unique index '{s}' has duplicate keys in existing data; duplicates not enforced for existing documents\n", .{ix.name});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1103,7 +1103,7 @@ fn apply_record(ctx: *anyopaque, record: storage.Record, doc: *bson.Document) an
|
||||
switch (record.type) {
|
||||
storage.record_type_index_create => {
|
||||
self.register_index_from_spec(coll, doc) catch |err| {
|
||||
std.debug.print("mongo-lite: index create record failed to apply: {s}\n", .{@errorName(err)});
|
||||
std.debug.print("multiforadb: index create record failed to apply: {s}\n", .{@errorName(err)});
|
||||
return;
|
||||
};
|
||||
return;
|
||||
@@ -1121,7 +1121,7 @@ fn apply_record(ctx: *anyopaque, record: storage.Record, doc: *bson.Document) an
|
||||
}
|
||||
|
||||
const id_value = doc.get("_id") orelse {
|
||||
std.debug.print("mongo-lite: log record without _id, skipping\n", .{});
|
||||
std.debug.print("multiforadb: log record without _id, skipping\n", .{});
|
||||
return;
|
||||
};
|
||||
const id_key = try bson.serialize_value(self.gpa, id_value);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// mongo-lite core library. Public entry point for tests and the server.
|
||||
// multiforadb core library. Public entry point for tests and the server.
|
||||
|
||||
pub const assert = @import("assert.zig");
|
||||
pub const bson = @import("bson.zig");
|
||||
|
||||
20
src/main.zig
20
src/main.zig
@@ -2,12 +2,12 @@ const std = @import("std");
|
||||
const mongo = @import("mongo");
|
||||
|
||||
const usage =
|
||||
\\mongo-lite — lightweight MongoDB-compatible document database
|
||||
\\MultiforaDB — lightweight MongoDB-compatible document database
|
||||
\\
|
||||
\\usage: mongo-lite [options]
|
||||
\\usage: multiforadb [options]
|
||||
\\ --port <n> listen port (default 27017)
|
||||
\\ --bind <ip> bind address (default 127.0.0.1)
|
||||
\\ --db <path> database file (default mongo-lite.log)
|
||||
\\ --db <path> database file (default multiforadb.log)
|
||||
\\ --ttl-sweep-secs <n>
|
||||
\\ seconds between TTL index sweeps (default 60, 0 disables)
|
||||
\\ --compact-threshold <bytes>
|
||||
@@ -47,7 +47,7 @@ fn parse_size_suffix(v: []const u8) ?u64 {
|
||||
pub fn main(init: std.process.Init) !void {
|
||||
var port: u16 = 27017;
|
||||
var bind_ip: []const u8 = "127.0.0.1";
|
||||
var db_path: []const u8 = "mongo-lite.log";
|
||||
var db_path: []const u8 = "multiforadb.log";
|
||||
var ttl_sweep_secs: i64 = 60;
|
||||
var compact_threshold: u64 = 16 * 1024 * 1024;
|
||||
|
||||
@@ -58,7 +58,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
if (std.mem.eql(u8, arg, "--port")) {
|
||||
const v = it.next() orelse return error.MissingValue;
|
||||
port = std.fmt.parseInt(u16, v, 10) catch {
|
||||
std.debug.print("mongo-lite: invalid port '{s}'\n", .{v});
|
||||
std.debug.print("multiforadb: invalid port '{s}'\n", .{v});
|
||||
return error.InvalidPort;
|
||||
};
|
||||
} else if (std.mem.eql(u8, arg, "--bind")) {
|
||||
@@ -72,17 +72,17 @@ pub fn main(init: std.process.Init) !void {
|
||||
// only thing parseInt would otherwise let through.
|
||||
ttl_sweep_secs = std.fmt.parseInt(i64, v, 10) catch -1;
|
||||
if (ttl_sweep_secs < 0) {
|
||||
std.debug.print("mongo-lite: invalid ttl sweep interval '{s}'\n", .{v});
|
||||
std.debug.print("multiforadb: invalid ttl sweep interval '{s}'\n", .{v});
|
||||
return error.InvalidTtlSweepSecs;
|
||||
}
|
||||
} else if (std.mem.eql(u8, arg, "--compact-threshold")) {
|
||||
const v = it.next() orelse return error.MissingValue;
|
||||
const parsed = parse_size_suffix(v) orelse {
|
||||
std.debug.print("mongo-lite: invalid compact threshold '{s}'\n", .{v});
|
||||
std.debug.print("multiforadb: invalid compact threshold '{s}'\n", .{v});
|
||||
return error.InvalidCompactThreshold;
|
||||
};
|
||||
if (parsed < 1024 * 1024) {
|
||||
std.debug.print("mongo-lite: compact threshold must be at least 1m\n", .{});
|
||||
std.debug.print("multiforadb: compact threshold must be at least 1m\n", .{});
|
||||
return error.InvalidCompactThreshold;
|
||||
}
|
||||
compact_threshold = parsed;
|
||||
@@ -90,7 +90,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
try std.Io.File.writeStreamingAll(.stdout(), init.io, usage);
|
||||
return;
|
||||
} else {
|
||||
std.debug.print("mongo-lite: unknown option '{s}'\n{s}", .{ arg, usage });
|
||||
std.debug.print("multiforadb: unknown option '{s}'\n{s}", .{ arg, usage });
|
||||
return error.UnknownOption;
|
||||
}
|
||||
}
|
||||
@@ -99,7 +99,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
var engine = try mongo.db.Engine.open(init.gpa, init.io, db_path);
|
||||
defer engine.deinit();
|
||||
engine.compact_threshold = compact_threshold;
|
||||
std.debug.print("mongo-lite: opened database '{s}' (compact threshold {d})\n", .{ db_path, compact_threshold });
|
||||
std.debug.print("multiforadb: opened database '{s}' (compact threshold {d})\n", .{ db_path, compact_threshold });
|
||||
|
||||
var server = mongo.server.Server{
|
||||
.gpa = init.gpa,
|
||||
|
||||
@@ -35,7 +35,7 @@ pub const Server = struct {
|
||||
var listener = try addr.listen(io, .{ .reuse_address = true });
|
||||
defer listener.deinit(io);
|
||||
|
||||
std.debug.print("mongo-lite: listening on {s}:{d}\n", .{ self.bind_ip, self.port });
|
||||
std.debug.print("multiforadb: listening on {s}:{d}\n", .{ self.bind_ip, self.port });
|
||||
|
||||
var group: std.Io.Group = .init;
|
||||
defer group.cancel(io);
|
||||
@@ -48,7 +48,7 @@ pub const Server = struct {
|
||||
const stream = listener.accept(io) catch |err| switch (err) {
|
||||
error.Canceled => return,
|
||||
else => {
|
||||
std.debug.print("mongo-lite: accept error: {s}\n", .{@errorName(err)});
|
||||
std.debug.print("multiforadb: accept error: {s}\n", .{@errorName(err)});
|
||||
continue;
|
||||
},
|
||||
};
|
||||
@@ -70,12 +70,12 @@ fn ttl_monitor(io: std.Io, server: *Server) error{Canceled}!void {
|
||||
try std.Io.sleep(io, interval, .awake);
|
||||
const now_ms = std.Io.Timestamp.now(io, .real).toMilliseconds();
|
||||
_ = server.engine.ttl_sweep(now_ms) catch |err| {
|
||||
std.debug.print("mongo-lite: TTL sweep failed: {s}\n", .{@errorName(err)});
|
||||
std.debug.print("multiforadb: TTL sweep failed: {s}\n", .{@errorName(err)});
|
||||
continue;
|
||||
};
|
||||
if (server.engine.take_compact()) {
|
||||
server.engine.compact() catch |err| {
|
||||
std.debug.print("mongo-lite: compaction failed: {s}\n", .{@errorName(err)});
|
||||
std.debug.print("multiforadb: compaction failed: {s}\n", .{@errorName(err)});
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -120,7 +120,7 @@ fn handle_connection_inner(io: std.Io, stream: std.Io.net.Stream, server: *Serve
|
||||
reader.interface.readSliceAll(&len_bytes) catch return; // clean client disconnect (EOF or RST)
|
||||
const total: u32 = std.mem.readInt(u32, &len_bytes, .little);
|
||||
if (total < 16 or total > wire.max_message_size) {
|
||||
std.debug.print("mongo-lite: bad message length {d} on conn {d}\n", .{ total, connection_id });
|
||||
std.debug.print("multiforadb: bad message length {d} on conn {d}\n", .{ total, connection_id });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -129,14 +129,14 @@ fn handle_connection_inner(io: std.Io, stream: std.Io.net.Stream, server: *Serve
|
||||
msg_buf.items.len = total;
|
||||
std.mem.writeInt(u32, msg_buf.items[0..4], total, .little);
|
||||
reader.interface.readSliceAll(msg_buf.items[4..]) catch |err| {
|
||||
std.debug.print("mongo-lite: read error on conn {d}: {s} (body, len {d})\n", .{ connection_id, @errorName(err), total });
|
||||
std.debug.print("multiforadb: read error on conn {d}: {s} (body, len {d})\n", .{ connection_id, @errorName(err), total });
|
||||
return;
|
||||
};
|
||||
|
||||
var msg = wire.Message.parse(server.gpa, msg_buf.items) catch |err| {
|
||||
// Unparseable request: close the connection.
|
||||
const op: i32 = if (msg_buf.items.len >= 16) std.mem.readInt(i32, msg_buf.items[12..16], .little) else 0;
|
||||
std.debug.print("mongo-lite: bad message on conn {d}: {s} (opCode {d})\n", .{ connection_id, @errorName(err), op });
|
||||
std.debug.print("multiforadb: bad message on conn {d}: {s} (opCode {d})\n", .{ connection_id, @errorName(err), op });
|
||||
return;
|
||||
};
|
||||
defer msg.deinit();
|
||||
@@ -146,7 +146,7 @@ fn handle_connection_inner(io: std.Io, stream: std.Io.net.Stream, server: *Serve
|
||||
commands.dispatch(&ctx, &msg, &reply) catch |err| {
|
||||
// Discard any partial reply (the client would read the first
|
||||
// ok field, which may already say 1) and send a clean error.
|
||||
std.debug.print("mongo-lite: dispatch error on conn {d} cmd {s}: {s}\n", .{ connection_id, msg.command_name(), @errorName(err) });
|
||||
std.debug.print("multiforadb: dispatch error on conn {d} cmd {s}: {s}\n", .{ connection_id, msg.command_name(), @errorName(err) });
|
||||
reply.pairs.clearRetainingCapacity();
|
||||
reply.put_error(
|
||||
@intFromEnum(commands.ErrorCode.internal_error),
|
||||
@@ -161,16 +161,16 @@ fn handle_connection_inner(io: std.Io, stream: std.Io.net.Stream, server: *Serve
|
||||
else
|
||||
reply.build(server.gpa, reply_request_id, msg.request_id, &out_buf);
|
||||
built catch |err| {
|
||||
std.debug.print("mongo-lite: reply build error on conn {d}: {s}\n", .{ connection_id, @errorName(err) });
|
||||
std.debug.print("multiforadb: reply build error on conn {d}: {s}\n", .{ connection_id, @errorName(err) });
|
||||
return;
|
||||
};
|
||||
reply_request_id +%= 1;
|
||||
writer.interface.writeAll(out_buf.items) catch |err| {
|
||||
std.debug.print("mongo-lite: write error on conn {d}: {s}\n", .{ connection_id, @errorName(err) });
|
||||
std.debug.print("multiforadb: write error on conn {d}: {s}\n", .{ connection_id, @errorName(err) });
|
||||
return;
|
||||
};
|
||||
writer.interface.flush() catch |err| {
|
||||
std.debug.print("mongo-lite: flush error on conn {d}: {s}\n", .{ connection_id, @errorName(err) });
|
||||
std.debug.print("multiforadb: flush error on conn {d}: {s}\n", .{ connection_id, @errorName(err) });
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -227,14 +227,14 @@ pub const Log = struct {
|
||||
while (true) {
|
||||
var hdr: [block_header_len]u8 = undefined;
|
||||
const n = self.file.readPositionalAll(self.io, &hdr, pos) catch |err| {
|
||||
std.debug.print("mongo-lite: log read error at {d}: {s}\n", .{ pos, @errorName(err) });
|
||||
std.debug.print("multiforadb: log read error at {d}: {s}\n", .{ pos, @errorName(err) });
|
||||
return error.InvalidLog;
|
||||
};
|
||||
if (n == 0) return; // clean end
|
||||
if (n < block_header_len) return; // torn tail: partial block header
|
||||
const total: u32 = std.mem.readInt(u32, hdr[0..4], .little);
|
||||
if (total < block_header_len or total - block_header_len > max_block_payload) {
|
||||
std.debug.print("mongo-lite: corrupt block length {d} at {d}\n", .{ total, pos });
|
||||
std.debug.print("multiforadb: corrupt block length {d} at {d}\n", .{ total, pos });
|
||||
return; // torn tail: impossible length, nothing to validate
|
||||
}
|
||||
const payload_len: usize = total - block_header_len;
|
||||
@@ -262,7 +262,7 @@ pub const Log = struct {
|
||||
codec_raw => try decomp.appendSlice(self.gpa, payload),
|
||||
codec_lz4 => try lz4_decompress(self.gpa, payload, &decomp),
|
||||
else => {
|
||||
std.debug.print("mongo-lite: unknown block codec {d} at {d}\n", .{ codec, pos });
|
||||
std.debug.print("multiforadb: unknown block codec {d} at {d}\n", .{ codec, pos });
|
||||
return error.InvalidLog;
|
||||
},
|
||||
}
|
||||
@@ -284,12 +284,12 @@ pub const Log = struct {
|
||||
if (bytes.len < 4) return error.InvalidLog;
|
||||
const total: u32 = std.mem.readInt(u32, bytes[0..4], .little);
|
||||
if (total < header_len) {
|
||||
std.debug.print("mongo-lite: corrupt record length {d} at {d}\n", .{ total, pos });
|
||||
std.debug.print("multiforadb: corrupt record length {d} at {d}\n", .{ total, pos });
|
||||
return error.InvalidLog;
|
||||
}
|
||||
const payload_len: usize = total - 4;
|
||||
if (payload_len > max_record_payload) {
|
||||
std.debug.print("mongo-lite: record too large at {d}\n", .{pos});
|
||||
std.debug.print("multiforadb: record too large at {d}\n", .{pos});
|
||||
return error.InvalidLog;
|
||||
}
|
||||
if (bytes.len < total) return error.InvalidLog; // record crosses the block end
|
||||
@@ -309,7 +309,7 @@ pub const Log = struct {
|
||||
const doc = try self.gpa.create(bson.Document);
|
||||
doc.* = bson.Document.parse(self.gpa, doc_bytes) catch {
|
||||
self.gpa.destroy(doc);
|
||||
std.debug.print("mongo-lite: unparseable doc in log at {d}\n", .{pos});
|
||||
std.debug.print("multiforadb: unparseable doc in log at {d}\n", .{pos});
|
||||
return error.InvalidLog;
|
||||
};
|
||||
try callback(ctx, .{
|
||||
|
||||
Reference in New Issue
Block a user