]> arthur.barton.de Git - netatalk.git/commitdiff
database versioning
authorFrank Lahm <franklahm@googlemail.com>
Mon, 22 Nov 2010 13:30:12 +0000 (14:30 +0100)
committerFrank Lahm <franklahm@googlemail.com>
Mon, 22 Nov 2010 13:30:12 +0000 (14:30 +0100)
etc/cnid_dbd/cmd_dbd.c
etc/cnid_dbd/dbif.c
etc/cnid_dbd/dbif.h
etc/cnid_dbd/main.c
include/atalk/cnid_private.h

index dc4c3923d90eeb1a0e47c3c24bb4b4df32d4333f..a08b92c07a6c573dbde6068407b9b80d2d2b4c52 100644 (file)
@@ -412,7 +412,7 @@ int main(int argc, char **argv)
 
     /* Prepare upgrade ? */
     if (prep_upgrade) {
-        if (dbif_prep_upgrade(dbpath))
+        if (dbif_env_remove(dbpath))
             goto exit_failure;
         goto exit_success;
     }        
index a24f75f3fc9a0346211c0247cb3029c8f9802a26..6a11d359e250269402a17f24a4fbaa206abc5fd8 100644 (file)
@@ -77,6 +77,33 @@ exit:
     return (ret < 0 ? ret : found);
 }
 
+/*!
+ * Upgrade CNID database versions
+ *
+ * For now this does nothing, as upgrading from ver. 0 to 1 is done in dbif_open
+ */
+static int dbif_upgrade(DBD *dbd)
+{
+    int version;
+
+    if ((version = dbif_getversion(dbd)) == -1)
+        return -1;
+
+    /* 
+     * Do upgrade stuff ...
+     */
+
+    /* Write current version to database */
+    if (version != CNID_VERSION) {
+        if (dbif_setversion(dbd, CNID_VERSION) != 0)
+            return -1;
+    }
+
+    LOG(log_debug, logtype_cnid, "Finished CNID database version upgrade check");
+
+    return 0;
+}
+
 /* --------------- */
 static int dbif_openlog(DBD *dbd)
 {
@@ -411,7 +438,7 @@ int dbif_open(DBD *dbd, struct db_param *dbp, int reindex)
                 LOG(log_error, logtype_cnid, "error forcing checkpoint: %s", db_strerror(ret));
                 return -1;
             }
-            LOG(log_debug, logtype_cnid, "Finished CNID database upgrade check");
+            LOG(log_debug, logtype_cnid, "Finished BerkeleyBD upgrade check");
         }
         
         if ((fchdir(cwd)) != 0) {
@@ -507,13 +534,20 @@ int dbif_open(DBD *dbd, struct db_param *dbp, int reindex)
                                               dbd->db_txn,
                                               dbd->db_table[DBIF_IDX_NAME].db, 
                                               idxname,
-                                              DB_CREATE))
-        != 0) {
-        LOG(log_error, logtype_cnid, "Failed to associate name index: %s",db_strerror(ret));
+                                              (reindex
+                                               || 
+                                               ((CNID_VERSION == CNID_VERSION_1) && (dbif_getversion(dbd) == CNID_VERSION_0)))
+                                              ? DB_CREATE : 0)) != 0) {
+        LOG(log_error, logtype_cnid, "Failed to associate name index: %s", db_strerror(ret));
         return -1;
     }
     if (reindex)
         LOG(log_info, logtype_cnid, "... done.");
+
+    if ((ret = dbif_upgrade(dbd)) != 0) {
+        LOG(log_error, logtype_cnid, "Error upgrading CNID database to version %d", CNID_VERSION);
+        return -1;
+    }
     
     return 0;
 }
@@ -567,7 +601,7 @@ int dbif_close(DBD *dbd)
    In order to support silent database upgrades:
    destroy env at cnid_dbd shutdown.
  */
-int dbif_prep_upgrade(const char *path)
+int dbif_env_remove(const char *path)
 {
     int ret;
     DBD *dbd;
@@ -744,6 +778,67 @@ int dbif_del(DBD *dbd, const int dbi, DBT *key, u_int32_t flags)
         return 1;
 }
 
+/*!
+ * Return CNID database version number
+ * @returns -1 on error, version number otherwise
+ */
+int dbif_getversion(DBD *dbd)
+{
+    DBT key, data;
+    uint32_t version;
+    int ret;
+
+    memset(&key, 0, sizeof(key));
+    memset(&data, 0, sizeof(data));
+    key.data = ROOTINFO_KEY;
+    key.size = ROOTINFO_KEYLEN;
+
+    switch (dbif_get(dbd, DBIF_CNID, &key, &data, 0)) {
+    case 1:
+        memcpy(&version, (char *)data.data + CNID_DID_OFS, sizeof(version));
+        version = ntohl(version);
+        LOG(log_debug, logtype_cnid, "CNID database version %u", version);
+        ret = version;
+        break;
+    default:
+        ret = -1;
+        break;
+    }
+    return ret;
+}
+
+/*!
+ * Return CNID database version number
+ * @returns -1 on error, version number otherwise
+ */
+int dbif_setversion(DBD *dbd, int version)
+{
+    DBT key, data;
+    uint32_t v;
+
+    v = version;
+    v = htonl(v);
+
+    memset(&key, 0, sizeof(key));
+    memset(&data, 0, sizeof(data));
+    key.data = ROOTINFO_KEY;
+    key.size = ROOTINFO_KEYLEN;
+
+    switch (dbif_get(dbd, DBIF_CNID, &key, &data, 0)) {
+    case 1:
+        break;
+    default:
+        return -1;
+    }
+
+    memcpy((char *)data.data + CNID_DID_OFS, &v, sizeof(v));
+    data.size = ROOTINFO_DATALEN;
+    if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) < 0)
+        return -1;
+
+    return 0;
+}
+
 /*!
  * Search the database by name
  *
index 04eea3d909183961ef25b91460bd4781fd4ad320..033fc72ea16875d298fdf2ca0ee385119d745c3d 100644 (file)
@@ -89,7 +89,9 @@ extern DBD *dbif_init(const char *envhome, const char *dbname);
 extern int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags);
 extern int dbif_open(DBD *dbd, struct db_param *dbp, int reindex);
 extern int dbif_close(DBD *dbd);
-extern int dbif_prep_upgrade(const char *path);
+extern int dbif_env_remove(const char *path);
+extern int dbif_getversion(DBD *dbd);
+extern int dbif_setversion(DBD *dbd, int);
 
 extern int dbif_get(DBD *, const int, DBT *, DBT *, u_int32_t);
 extern int dbif_pget(DBD *, const int, DBT *, DBT *, DBT *, u_int32_t);
index 1b1b988752f6c8ce7b7d2a86b378a72118e37764..91027157292ea7dea5d85373b1c948cf95959d37 100644 (file)
@@ -385,7 +385,7 @@ int main(int argc, char *argv[])
     if (dbif_close(dbd) < 0)
         err++;
 
-    if (dbif_prep_upgrade(dir) < 0)
+    if (dbif_env_remove(dir) < 0)
         err++;
 
     free_lock(lockfd);
index 6525ce4898c63508bb6c8cb97979cfea61800fdd..741077b1fcdbfeecf6c2d9dd0d571de5932b4c13 100644 (file)
 #define ROOTINFO_KEYLEN 4
 
 /* 
-   Rootinfo data:
-   4 unused bytes (cnid) 
-   8 bytes, in first 4 bytes db stamp: struct stat.st_ctime of database file (dev)
-   8 unused bytes (inode)
+   Rootinfo data, fields as they are used by normal entries for CNIDs (for reference):
+   4 bytes: CNID 
+   8 bytes: dev
+   8 bytes: inode
    4 bytes: is a file/directory (type)
-   4 unused bytes (did)
-   9 bytes name "RootInfo"
+   4 bytes: DID
+   x bytes: name
+
+   Contents in Rootinfo entry:
+   4 bytes: 0
+   8 bytes: db stamp: struct stat.st_ctime of database file
+   8 bytes: unused
+   4 bytes: last used CNID
+   4 bytes: version as htonl(uint32_t)
+   9 bytes: name "RootInfo"
 */
 #define ROOTINFO_DATA    "\0\0\0\0" \
                          "\0\0\0\0\0\0\0\0" \
                          "RootInfo"
 #define ROOTINFO_DATALEN (3*4 + 2*8 + 9)
 
+/* 
+ * CNID version history:
+ * 0: up to Netatalk 2.1.x
+ * 1: starting with 2.2, additional name index, used in cnid_find
+ */
+#define CNID_VERSION_0 0
+#define CNID_VERSION_1 1
+
+/* Current CNID version */
+#define CNID_VERSION CNID_VERSION_1
+
 #endif