<pre style='margin:0'>
Joshua Root (jmroot) pushed a commit to branch master
in repository macports-base.

</pre>
<p><a href="https://github.com/macports/macports-base/commit/5779dbc66da9acb3e77df1ef1996772a925dd928">https://github.com/macports/macports-base/commit/5779dbc66da9acb3e77df1ef1996772a925dd928</a></p>
<pre style="white-space: pre; background: #F8F8F8">The following commit(s) were added to refs/heads/master by this push:
<span style='display:block; white-space:pre;color:#404040;'>     new 5779dbc6 Enable fullfsync and WAL (if possible) for registry
</span>5779dbc6 is described below

<span style='display:block; white-space:pre;color:#808000;'>commit 5779dbc66da9acb3e77df1ef1996772a925dd928
</span>Author: Joshua Root <jmr@macports.org>
AuthorDate: Mon Apr 12 04:57:56 2021 +1000

<span style='display:block; white-space:pre;color:#404040;'>    Enable fullfsync and WAL (if possible) for registry
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Using fullfsync should make the registry much less likely to experience
</span><span style='display:block; white-space:pre;color:#404040;'>    corruption in scenarios like writing to it when power fails.
</span><span style='display:block; white-space:pre;color:#404040;'>    Write-ahead logging (WAL) should reduce the window in which syncing
</span><span style='display:block; white-space:pre;color:#404040;'>    needs to occur, hopefully improving reliability further as well as
</span><span style='display:block; white-space:pre;color:#404040;'>    improving performance. However, WAL is only practical for us to use
</span><span style='display:block; white-space:pre;color:#404040;'>    with SQLite versions 3.22.0 and newer, because older versions didn't
</span><span style='display:block; white-space:pre;color:#404040;'>    allow read-only access to the database, which would mean commands like
</span><span style='display:block; white-space:pre;color:#404040;'>    'port installed' run with normal privileges would not work with a
</span><span style='display:block; white-space:pre;color:#404040;'>    root-owned installation.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Closes: https://trac.macports.org/ticket/61154
</span>---
 src/cregistry/registry.c   | 20 ++++++++++++++++++++
 src/cregistry/registry.h   |  1 +
 src/cregistry/sql.c        | 41 +++++++++++++++++++++++++++++++++++++++--
 src/registry2.0/registry.c |  4 ++++
 4 files changed, 64 insertions(+), 2 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/cregistry/registry.c b/src/cregistry/registry.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 8a8b5b38..af91ee25 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/cregistry/registry.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/cregistry/registry.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -474,6 +474,26 @@ int reg_vacuum(char *db_path) {
</span>     return result;
 }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Checkpoints a registry database if WAL mode is available.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @param [in] reg     registry to checkpoint
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @param [out] errPtr on error, a description of the error that occurred
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * @return             true if success; false if failure
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int reg_checkpoint(reg_registry* reg, reg_error* errPtr) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#if SQLITE_VERSION_NUMBER >= 3022000
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (sqlite3_db_readonly(reg->db, "registry") == 0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            && sqlite3_wal_checkpoint_v2(reg->db, "registry",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            SQLITE_CHECKPOINT_PASSIVE, NULL, NULL) != SQLITE_OK) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        reg_sqlite_error(reg->db, errPtr, NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> /**
  * Functions for access to the metadata table
  */
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/cregistry/registry.h b/src/cregistry/registry.h
</span><span style='display:block; white-space:pre;color:#808080;'>index 762a52bd..52570701 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/cregistry/registry.h
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/cregistry/registry.h
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -95,6 +95,7 @@ int reg_commit(reg_registry* reg, reg_error* errPtr);
</span> int reg_rollback(reg_registry* reg, reg_error* errPtr);
 
 int reg_vacuum(char* db_path);
<span style='display:block; white-space:pre;background:#e0ffe0;'>+int reg_checkpoint(reg_registry* reg, reg_error* errPtr);
</span> 
 int reg_get_metadata(reg_registry* reg, const char* key, char** value, reg_error* errPtr);
 int reg_set_metadata(reg_registry* reg, const char* key, const char* value, reg_error* errPtr);
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/cregistry/sql.c b/src/cregistry/sql.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 72319185..193a4f3d 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/cregistry/sql.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/cregistry/sql.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -130,11 +130,24 @@ static void sql_regexp(sqlite3_context* context, int argc UNUSED,
</span>  */
 int create_tables(sqlite3* db, reg_error* errPtr) {
     static char* queries[] = {
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* settings (can't be set inside a transaction) */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        "PRAGMA fullfsync = 1",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* WAL was added in 3.7.0, but read-only access when using it only
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           became possible in 3.22.0. It might be possible to use WAL on
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           3.7.7 and later since that version added the ability to open a DB
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           read-only as long as there is an existing read/write connection.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           But the DB would need to be changed back to a non-WAL journal_mode
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           after doing a SQLITE_CHECKPOINT_RESTART whenever the last writer
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           closes it. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#if SQLITE_VERSION_NUMBER >= 3022000
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        "PRAGMA journal_mode=WAL",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>         "BEGIN",
 
         /* metadata table */
         "CREATE TABLE registry.metadata (key UNIQUE, value)",
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        "INSERT INTO registry.metadata (key, value) VALUES ('version', '1.204')",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        "INSERT INTO registry.metadata (key, value) VALUES ('version', '1.205')",
</span>         "INSERT INTO registry.metadata (key, value) VALUES ('created', strftime('%s', 'now'))",
 
         /* ports table */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -709,6 +722,30 @@ int update_db(sqlite3* db, reg_error* errPtr) {
</span>             continue;
         }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (sql_version(NULL, -1, version, -1, "1.205") < 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            /* enable fullfsync and possibly WAL */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            static char* version_1_205_queries[] = {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                "UPDATE registry.metadata SET value = '1.205' WHERE key = 'version'",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                "COMMIT",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                "PRAGMA fullfsync = 1",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#if SQLITE_VERSION_NUMBER >= 3022000
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                "PRAGMA journal_mode=WAL",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                NULL
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            sqlite3_finalize(stmt);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            stmt = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if (!do_queries(db, version_1_205_queries, errPtr)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                rollback_db(db);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            did_update = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            continue;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>         /* add new versions here, but remember to:
          *  - finalize the version query statement and set stmt to NULL
          *  - do _not_ use "BEGIN" in your query list, since a transaction has
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -718,7 +755,7 @@ int update_db(sqlite3* db, reg_error* errPtr) {
</span>          *  - update the current version number below
          */
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if (sql_version(NULL, -1, version, -1, "1.204") > 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (sql_version(NULL, -1, version, -1, "1.205") > 0) {
</span>             /* the registry was already upgraded to a newer version and cannot be used anymore */
             reg_throw(errPtr, REG_INVALID, "Version number in metadata table is newer than expected.");
             sqlite3_finalize(stmt);
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/registry2.0/registry.c b/src/registry2.0/registry.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 40a860c1..f67973e9 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/registry2.0/registry.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/registry2.0/registry.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -224,6 +224,10 @@ static int registry_close(ClientData clientData UNUSED, Tcl_Interp* interp,
</span>                 reg_vacuum(Tcl_GetAssocData(interp, "registry::db_path", NULL));
                 Tcl_DeleteAssocData(interp, "registry::needs_vacuum");
             }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+            /* Not really anything we can do if this fails. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if (reg_checkpoint(reg, &error) == 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                fprintf(stderr, "%s\n", error.description);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span>             if (registry_tcl_detach(interp, reg, &error)) {
                 return TCL_OK;
             }
</pre><pre style='margin:0'>

</pre>