[70608] trunk/base/src

jmr at macports.org jmr at macports.org
Sat Aug 14 21:24:09 PDT 2010


Revision: 70608
          http://trac.macports.org/changeset/70608
Author:   jmr at macports.org
Date:     2010-08-14 21:24:06 -0700 (Sat, 14 Aug 2010)
Log Message:
-----------
vacuum registry database before closing if any entries have been deleted

Modified Paths:
--------------
    trunk/base/src/cregistry/registry.c
    trunk/base/src/cregistry/registry.h
    trunk/base/src/macports1.0/macports.tcl
    trunk/base/src/port/port.tcl
    trunk/base/src/registry2.0/entry.c
    trunk/base/src/registry2.0/registry.c

Modified: trunk/base/src/cregistry/registry.c
===================================================================
--- trunk/base/src/cregistry/registry.c	2010-08-15 03:22:13 UTC (rev 70607)
+++ trunk/base/src/cregistry/registry.c	2010-08-15 04:24:06 UTC (rev 70608)
@@ -401,3 +401,44 @@
         return 0;
     }
 }
+
+/**
+ * Runs VACUUM (compact/defragment) on the given db file.
+ * Works on a path rather than an open db pointer because you can't vacuum an
+ * attached db, which is what the rest of the registry uses for some reason.
+ *
+ * @param [in] db_path path to db file to vacuum
+ * @return             true if success; false if failure
+ */
+int reg_vacuum(char *db_path) {
+    sqlite3* db;
+    sqlite3_stmt* stmt = NULL;
+    int result = 0;
+    reg_error err;
+
+    if (sqlite3_open(db_path, &db) == SQLITE_OK) {
+        if (!init_db(db, &err)) {
+            sqlite3_close(db);
+            return 0;
+        }
+    } else {
+        return 0;
+    }
+
+    if (sqlite3_prepare(db, "VACUUM", -1, &stmt, NULL) == SQLITE_OK) {
+        int r;
+        /* XXX: Busy waiting, consider using sqlite3_busy_handler/timeout */
+        do {
+            sqlite3_step(stmt);
+            r = sqlite3_reset(stmt);
+            if (r == SQLITE_OK) {
+                result = 1;
+            }
+        } while (r == SQLITE_BUSY);
+    }
+    if (stmt) {
+        sqlite3_finalize(stmt);
+    }
+    sqlite3_close(db);
+    return result;
+}

Modified: trunk/base/src/cregistry/registry.h
===================================================================
--- trunk/base/src/cregistry/registry.h	2010-08-15 03:22:13 UTC (rev 70607)
+++ trunk/base/src/cregistry/registry.h	2010-08-15 04:24:06 UTC (rev 70608)
@@ -83,4 +83,6 @@
 int reg_commit(reg_registry* reg, reg_error* errPtr);
 int reg_rollback(reg_registry* reg, reg_error* errPtr);
 
+int reg_vacuum(char* db_path);
+
 #endif /* _CREG_H */

Modified: trunk/base/src/macports1.0/macports.tcl
===================================================================
--- trunk/base/src/macports1.0/macports.tcl	2010-08-15 03:22:13 UTC (rev 70607)
+++ trunk/base/src/macports1.0/macports.tcl	2010-08-15 04:24:06 UTC (rev 70608)
@@ -975,6 +975,15 @@
     }
 }
 
+# call this just before you exit
+proc mportshutdown {} {
+    global macports::registry.format
+    if {${registry.format} == "receipt_sqlite"} {
+        # close it down so the cleanup stuff is called, e.g. vacuuming the db
+        registry::close
+    }
+}
+
 proc macports::worker_init {workername portpath porturl portbuildpath options variations} {
     global macports::portinterp_options macports::portinterp_deferred_options registry.installtype
 

Modified: trunk/base/src/port/port.tcl
===================================================================
--- trunk/base/src/port/port.tcl	2010-08-15 03:22:13 UTC (rev 70607)
+++ trunk/base/src/port/port.tcl	2010-08-15 04:24:06 UTC (rev 70608)
@@ -4466,5 +4466,8 @@
     set exit_status [process_command_files $ui_options(ports_commandfiles)]
 }
 
+# shut down macports1.0
+mportshutdown
+
 # Return with exit_status
 exit $exit_status

Modified: trunk/base/src/registry2.0/entry.c
===================================================================
--- trunk/base/src/registry2.0/entry.c	2010-08-15 03:22:13 UTC (rev 70607)
+++ trunk/base/src/registry2.0/entry.c	2010-08-15 04:24:06 UTC (rev 70608)
@@ -162,6 +162,8 @@
             reg_entry_free(entry);
         }
         Tcl_DeleteCommand(interp, Tcl_GetString(objv[2]));
+        /* set flag so that the db will be vacuumed when we close it */
+        Tcl_SetAssocData(interp, "registry::needs_vacuum", NULL, (ClientData)1);
         return TCL_OK;
     }
 }

Modified: trunk/base/src/registry2.0/registry.c
===================================================================
--- trunk/base/src/registry2.0/registry.c	2010-08-15 03:22:13 UTC (rev 70607)
+++ trunk/base/src/registry2.0/registry.c	2010-08-15 04:24:06 UTC (rev 70608)
@@ -32,6 +32,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #include <tcl.h>
 
@@ -106,9 +107,13 @@
  *
  * Then it will leak memory :(
  */
-static void delete_reg(ClientData reg, Tcl_Interp* interp UNUSED) {
+static void delete_reg(ClientData reg, Tcl_Interp* interp) {
     reg_error error;
     if (((reg_registry*)reg)->status & reg_attached) {
+        if (Tcl_GetAssocData(interp, "registry::needs_vacuum", NULL) != NULL) {
+            reg_vacuum(Tcl_GetAssocData(interp, "registry::db_path", NULL));
+            Tcl_DeleteAssocData(interp, "registry::needs_vacuum");
+        }
         if (!registry_tcl_detach(interp, (reg_registry*)reg, &error)) {
             fprintf(stderr, "%s", error.description);
             reg_error_destruct(&error);
@@ -120,6 +125,11 @@
     }
 }
 
+/* simple destructor for malloc()ed assoc data */
+static void free_assoc_data(ClientData ptr, Tcl_Interp* interp UNUSED) {
+    free(ptr);
+}
+
 /**
  * Returns the sqlite3 DB associated with interp.
  *
@@ -168,6 +178,10 @@
         char* path = Tcl_GetString(objv[1]);
         reg_registry* reg = registry_for(interp, 0);
         reg_error error;
+        if (Tcl_GetAssocData(interp, "registry::db_path", NULL) == NULL) {
+            char *pathCopy = strdup(path);
+            Tcl_SetAssocData(interp, "registry::db_path", free_assoc_data, pathCopy);
+        }
         if (reg == NULL) {
             return TCL_ERROR;
         } else if (reg_attach(reg, path, &error)) {
@@ -189,6 +203,10 @@
             return TCL_ERROR;
         } else {
             reg_error error;
+            if (Tcl_GetAssocData(interp, "registry::needs_vacuum", NULL) != NULL) {
+                reg_vacuum(Tcl_GetAssocData(interp, "registry::db_path", NULL));
+                Tcl_DeleteAssocData(interp, "registry::needs_vacuum");
+            }
             if (registry_tcl_detach(interp, reg, &error)) {
                 return TCL_OK;
             }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20100814/00886279/attachment.html>


More information about the macports-changes mailing list