From 7205a6bbc93db7ea9b013c73413acaa4bc06dc35 Mon Sep 17 00:00:00 2001 From: annalee <150648636+a-n-n-a-l-e-e@users.noreply.github.com> Date: Sat, 23 Mar 2024 06:41:33 +0000 Subject: [PATCH] enable persistent WAL mode for sqlite db allow processes without write access to the directory containing the db to read the db when all connections are closed. Without this setting and with WAL enabled and no open db connections unprivileged processes will fail to open the db due the WAL files not existing and not able to create them. When the WAL files are persistent unprivileged processeses can read the db when there are no open connections. Additionally, journal_size_limit is set to 2^40, which results in the WAL files being truncated to 0 on exit, as well as limiting the WAL files to 2^40 bytes following a checkpoint. https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlpersistwal https://www.sqlite.org/pragma.html#pragma_journal_size_limit https://github.com/sqlite/sqlite/blob/ed517a708284b6e00b6ae5f1e3f702bbfcbd32ed/src/wal.c#L2518 Fixes https://github.com/NixOS/nix/issues/10300 --- src/libstore/local-store.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 1bbeaa912..e4c4126aa 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -552,6 +552,19 @@ void LocalStore::openDB(State & state, bool create) sqlite3_exec(db, ("pragma main.journal_mode = " + mode + ";").c_str(), 0, 0, 0) != SQLITE_OK) SQLiteError::throw_(db, "setting journal mode"); + if (mode == "wal") { + /* persist the WAL files when the db connection is closed. This allows + for read-only connections without write permissions on the + containing directory to succeed on a closed db. Setting the + journal_size_limit to 2^40 bytes results in the WAL files getting + truncated to 0 on exit and limits the on disk size of the WAL files + to 2^40 bytes following a checkpoint */ + if (sqlite3_exec(db, "pragma main.journal_size_limit = 1099511627776;", 0, 0, 0) == SQLITE_OK) { + int enable = 1; + sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, &enable); + } + } + /* Increase the auto-checkpoint interval to 40000 pages. This seems enough to ensure that instantiating the NixOS system derivation is done in a single fsync(). */