Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,46 @@ pub fn build(b: *std.Build) void {
}
}

// Focused C regressions also run without audio tools or a dataset.
const safety_step = b.step("test-db-safety", "Test fingerprint buffering and LMDB ownership");
const writer_test = b.addExecutable(.{
.name = "olaf_writer_safety",
.root_module = b.createModule(.{ .target = target, .optimize = optimize, .link_libc = true }),
});
writer_test.root_module.addIncludePath(b.path("src"));
writer_test.root_module.addCSourceFiles(.{
.files = &.{ "tests/olaf_fp_db_writer_tests.c", "src/olaf_fp_db_writer.c" },
.flags = &.{ "-std=gnu11", "-UNDEBUG" },
});
const run_writer = b.addRunArtifact(writer_test);
safety_step.dependOn(&run_writer.step);

const db_helper = b.addExecutable(.{
.name = "olaf_db_concurrency",
.root_module = b.createModule(.{ .target = target, .optimize = optimize, .link_libc = true }),
});
db_helper.root_module.addIncludePath(b.path("src"));
db_helper.root_module.addCSourceFiles(.{
.files = &.{ "tests/olaf_db_concurrency_tests.c", "src/olaf_db.c", "src/mdb.c", "src/midl.c" },
.flags = &.{ "-std=gnu11", "-DOLAF_DB_TESTING", "-UNDEBUG" },
});
if (target.result.os.tag != .windows) db_helper.root_module.linkSystemLibrary("pthread", .{});
const db_tests = b.addTest(.{
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
.root_source_file = b.path("tests/olaf_db_safety_tests.zig"),
}),
});
const db_options = b.addOptions();
db_options.addOptionPath("helper", db_helper.getEmittedBin());
db_tests.root_module.addOptions("db_test_options", db_options);
const run_db = b.addRunArtifact(db_tests);
safety_step.dependOn(&run_db.step);

// Test step
const test_step = b.step("test", "Run Olaf tests");
test_step.dependOn(safety_step);

if (!build_core) {
const test_files = [_][]const u8{
Expand Down
13 changes: 6 additions & 7 deletions cli/olaf_cli_session.zig
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,11 @@ pub const StoreResult = struct {
/// expensive part in parallel:
///
/// 1. Extract without a database. A STORE-mode runner opens the LMDB env up
/// front, and a write env holds the process-global writer lock
/// (src/olaf_db.c) until the runner is destroyed, which serialized every
/// worker's FFT and hashing. A CACHE-mode runner never opens the DB; it
/// writes the fingerprints to a temporary .tdb file instead.
/// front, holding LMDB's writer transaction until the runner is destroyed,
/// which would serialize every worker's FFT and hashing. A CACHE-mode
/// runner never opens the DB; it writes to a temporary .tdb file instead.
/// 2. Parse the .tdb into LMDB keys/values, still unlocked.
/// 3. Open the DB (taking the writer lock), store keys, values and meta-data,
/// 3. Begin a write transaction in the shared DB environment, store the data,
/// commit.
///
/// The stored keys, values and meta-data are exactly what the STORE-mode
Expand Down Expand Up @@ -240,8 +239,8 @@ pub fn store(allocator: std.mem.Allocator, raw_audio_path: []const u8, identifie
defer values.deinit(allocator);
try parseCachedFingerprints(allocator, io, tdb_path, internal_id, &keys, &values);

// Phase 3: write. olaf_db_new takes the writer lock, olaf_db_destroy
// commits and releases it.
// Phase 3: writers serialize per database, including LMDB cross-process locking.
// olaf_db_destroy commits before releasing the environment reference.
const db = c.olaf_db_new(session.config.db_folder.ptr, false);
defer c.olaf_db_destroy(db);
writeFingerprints(db, keys.items, values.items, identifier, @floatCast(run_stats.audio_seconds), @intCast(run_stats.fingerprints));
Expand Down
Loading
Loading