]> arthur.barton.de Git - netatalk.git/commitdiff
Support for BerkeleyDB lib updates.
authorfranklahm <franklahm>
Thu, 3 Sep 2009 08:35:14 +0000 (08:35 +0000)
committerfranklahm <franklahm>
Thu, 3 Sep 2009 08:35:14 +0000 (08:35 +0000)
BerkeleyDB cursors API requires db >= 4.6.
Push NEWS for 2.1.

NEWS
etc/cnid_dbd/cmd_dbd.c
etc/cnid_dbd/dbif.c
etc/cnid_dbd/dbif.h
etc/cnid_dbd/main.c
macros/db3-check.m4

diff --git a/NEWS b/NEWS
index cfaa79a53b2f3093a176320d287c820282058226..809ce8fa2643b6956a231885a31a1ac5a30ee72d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,28 @@
+
+
+REMEMBER TO UPDATE the Changes in 2.0.x section !!!
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Changes in 2.1
+==============
+* UPD: cdb/dbd CNID backend requires BerkeleyDB >= 4.6
+* FIX: rewritten logger
+* NEW: cnid_metad: options -l and -f to configure logging
+* NEW: CNID database maintanance utility dbd
+* NEW: support BerkeleyDB upgrade. Starting with the next release
+       after 2.1 in case of BerkeleyDB library updates, Netatalk
+       will be able to upgrade the CNID databases.
+* NEW: AppleDouble compatible UNIX files utility suite `ad ...`.
+       With 2.1 only `ad ls`.
+* NEW: afpd: ACL support with ZFS
+* NEW: afpd: ExtendedAttributes support with ZFS
+
+Changes in 2.0.x
+================
+
+...........
+
+
 Changes in 2.0.0
 ================
 
index b4b6312c755ff504f83acf2067c6b13e4b7010f4..86ff5ec46e2f26c88d7977d0e6d3537e956f7b52 100644 (file)
@@ -1,5 +1,5 @@
 /* 
-   $Id: cmd_dbd.c,v 1.5 2009-05-28 11:28:49 franklahm Exp $
+   $Id: cmd_dbd.c,v 1.6 2009-09-03 08:35:15 franklahm Exp $
 
    Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
    
@@ -228,7 +228,7 @@ void free_lock(int lockfd)
 
 static void usage ()
 {
-    printf("Usage: dbd [-e|-v|-x] -d [-i] | -s | -r [-f] <path to netatalk volume>\n"
+    printf("Usage: dbd [-e|-v|-x|-u] -d [-i] | -s | -r [-f] <path to netatalk volume>\n"
            "dbd can dump, scan, reindex and rebuild Netatalk dbd CNID databases.\n"
            "dbd must be run with appropiate permissions i.e. as root.\n\n"
            "Main commands are:\n"
@@ -252,6 +252,11 @@ static void usage ()
            "      7. Check for orphaned CNIDs in database (requires -e)\n"
            "      Option: -f wipe database and rebuild from IDs stored in AppleDouble files,\n"
            "                 only available for volumes with 'cachecnid' option. Implies -e.\n"
+           "   -u Prepare upgrade:\n"
+           "      Before installing an upgraded version of Netatalk that is linked against\n"
+           "      a newer BerkeleyDB lib, run `dbd -u ...` from the OLD Netatalk pior to\n"
+           "      upgrading on all volumes. This removes the BerkleyDB environment.\n"
+           "      On exit cnid_dbd does this automatically, so normally calling dbd -u should not be necessary.\n\n"
            "General options:\n"
            "   -e only work on inactive volumes and lock them (exclusive)\n"
            "   -x rebuild indexes (just for completeness, mostly useless!)\n"
@@ -265,8 +270,8 @@ static void usage ()
 
 int main(int argc, char **argv)
 {
-    int c, lockfd;
-    int dump=0, scan=0, rebuild=0, rebuildindexes=0, dumpindexes=0, force=0;
+    int c, lockfd, ret = -1;
+    int dump=0, scan=0, rebuild=0, prep_upgrade=0, rebuildindexes=0, dumpindexes=0, force=0;
     dbd_flags_t flags = 0;
     char *volpath;
     struct volinfo volinfo;
@@ -276,7 +281,7 @@ int main(int argc, char **argv)
         exit(EXIT_FAILURE);
     }
 
-    while ((c = getopt(argc, argv, ":dsrvxife")) != -1) {
+    while ((c = getopt(argc, argv, ":dsruvxife")) != -1) {
         switch(c) {
         case 'd':
             dump = 1;
@@ -291,6 +296,9 @@ int main(int argc, char **argv)
         case 'r':
             rebuild = 1;
             break;
+        case 'u':
+            prep_upgrade = 1;
+            break;
         case 'v':
             verbose = 1;
             break;
@@ -314,7 +322,7 @@ int main(int argc, char **argv)
         }
     }
 
-    if ((dump + scan + rebuild) != 1) {
+    if ((dump + scan + rebuild + prep_upgrade) != 1) {
         usage();
         exit(EXIT_FAILURE);
     }
@@ -365,8 +373,15 @@ int main(int argc, char **argv)
     */
     lockfd = get_lock(dbpath);
 
+    /* Prepare upgrade ? */
+    if (prep_upgrade) {
+        if (dbif_prep_upgrade(dbpath))
+            goto exit_failure;
+        goto exit_success;
+    }        
+
     /* Check if -f is requested and wipe db if yes */
-    if ((flags & DBD_FLAGS_FORCE) && (volinfo.v_flags & AFPVOL_CACHE)) {
+    if ((flags & DBD_FLAGS_FORCE) && rebuild && (volinfo.v_flags & AFPVOL_CACHE)) {
         char cmd[8 + MAXPATHLEN];
         snprintf(cmd, 8 + MAXPATHLEN, "rm -f %s/*", dbpath);
         dbd_log( LOGDEBUG, "Removing old database of volume: '%s'", volpath);
@@ -378,11 +393,11 @@ int main(int argc, char **argv)
        Lets start with the BerkeleyDB stuff
     */
     if ((dbd = dbif_init(dbpath, "cnid2.db")) == NULL)
-        exit(EXIT_FAILURE);
+        goto exit_failure;
 
     if (dbif_env_open(dbd, &db_param, exclusive ? (DBOPTIONS | DB_RECOVER) : DBOPTIONS) < 0) {
         dbd_log( LOGSTD, "error opening database!");
-        exit(EXIT_FAILURE);
+        goto exit_failure;
     }
 
     if (exclusive)
@@ -390,12 +405,12 @@ int main(int argc, char **argv)
 
     if (dbif_open(dbd, &db_param, rebuildindexes) < 0) {
         dbif_close(dbd);
-        exit(EXIT_FAILURE);
+        goto exit_failure;
     }
 
     if (dbd_stamp(dbd) < 0) {
         dbif_close(dbd);
-        exit(EXIT_FAILURE);
+        goto exit_failure;
     }
 
     if (dump) {
@@ -410,13 +425,20 @@ int main(int argc, char **argv)
 
     if (dbif_close(dbd) < 0) {
         dbd_log( LOGSTD, "Error closing database");
-        exit(EXIT_FAILURE);
+        goto exit_failure;
     }
 
-    free_lock(lockfd);
+exit_success:
+    ret = 0;
 
+exit_failure:
+    free_lock(lockfd);
+    
     if ((fchdir(cdir)) < 0)
         dbd_log(LOGSTD, "fchdir: %s", strerror(errno));
 
-    return 0;
+    if (ret == 0)
+        exit(EXIT_SUCCESS);
+    else
+        exit(EXIT_FAILURE);
 }
index 38401fc577be5f46a39de489fdbbb4ea4adb0e54..cad4f71ade55a659171b1c824847ede6a4f0a88a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbif.c,v 1.12 2009-05-22 20:48:44 franklahm Exp $
+ * $Id: dbif.c,v 1.13 2009-09-03 08:35:15 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * Copyright (C) Frank Lahm 2009
@@ -279,10 +279,52 @@ int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags)
 /* --------------- */
 int dbif_open(DBD *dbd, struct db_param *dbp _U_, int reindex)
 {
-    int ret;
-    int i;
+    int ret, i, cwd;
     u_int32_t count;
+    struct stat st;
+    DB *upgrade_db;
+
+    /* Try to upgrade if it's a normal on-disk database */
+    if (dbd->db_envhome) {
+        /* Remember cwd */
+        if ((cwd = open(".", O_RDONLY)) < 0) {
+            LOG(log_error, logtype_cnid, "error opening cwd: %s", strerror(errno));
+            return -1;
+        }
+        
+        /* chdir to db_envhome. makes it easier checking for old db files and creating db_errlog file  */
+        if ((chdir(dbd->db_envhome)) != 0) {
+            LOG(log_error, logtype_cnid, "error chdiring to db_env '%s': %s", dbd->db_envhome, strerror(errno));        
+            return -1;
+        }
+        
+        if ((stat(dbd->db_filename, &st)) == 0) {
+            LOG(log_debug, logtype_cnid, "See if we can upgrade the CNID database");
+            if ((ret = db_create(&upgrade_db, dbd->db_env, 0))) {
+                LOG(log_error, logtype_cnid, "error creating handle for database: %s", db_strerror(ret));
+                return -1;
+            }
+            if ((ret = upgrade_db->upgrade(upgrade_db, dbd->db_filename, 0))) {
+                LOG(log_error, logtype_cnid, "error upgarding database: %s", db_strerror(ret));
+                return -1;
+            }
+            if ((ret = upgrade_db->close(upgrade_db, 0))) {
+                LOG(log_error, logtype_cnid, "error closing database: %s", db_strerror(ret));
+                return -1;
+            }
+            if ((ret = dbd->db_env->txn_checkpoint(dbd->db_env, 0, 0, DB_FORCE))) {
+                LOG(log_error, logtype_cnid, "error forcing checkpoint: %s", db_strerror(ret));
+                return -1;
+            }
+        }
+        
+        if ((fchdir(cwd)) != 0) {
+            LOG(log_error, logtype_cnid, "error chdiring back: %s", strerror(errno));        
+            return -1;
+        }
+    }
 
+    /* Now open databases ... */
     for (i = 0; i != DBIF_DB_CNT; i++) {
         if ((ret = db_create(&dbd->db_table[i].db, dbd->db_env, 0))) {
             LOG(log_error, logtype_cnid, "error creating handle for database %s: %s",
@@ -401,6 +443,99 @@ int dbif_close(DBD *dbd)
     return 0;
 }
 
+/* 
+   In order to support silent database upgrades:
+   destroy env at cnid_dbd shutdown.
+ */
+int dbif_prep_upgrade(const char *path)
+{
+    int cwd, ret;
+    DBD *dbd;
+
+    LOG(log_debug, logtype_cnid, "Reopening BerkeleyDB environment");
+    
+    if (NULL == (dbd = dbif_init(path, "cnid2.db")))
+        return -1;
+
+    /* Remember cwd */
+    if ((cwd = open(".", O_RDONLY)) < 0) {
+        LOG(log_error, logtype_cnid, "error opening cwd: %s", strerror(errno));
+        return -1;
+    }
+
+    /* chdir to db_envhome. makes it easier checking for old db files and creating db_errlog file  */
+    if ((chdir(dbd->db_envhome)) != 0) {
+        LOG(log_error, logtype_cnid, "error chdiring to db_env '%s': %s", dbd->db_envhome, strerror(errno));        
+        return -1;
+    }
+
+    if ((dbd->db_errlog = fopen(DB_ERRLOGFILE, "a")) == NULL)
+        LOG(log_warning, logtype_cnid, "error creating/opening DB errlogfile: %s", strerror(errno));
+    
+    if ((fchdir(cwd)) != 0) {
+        LOG(log_error, logtype_cnid, "error chdiring back: %s", strerror(errno));        
+        return -1;
+    }
+
+    /* Get db_env handle */
+    if ((ret = db_env_create(&dbd->db_env, 0))) {
+        LOG(log_error, logtype_cnid, "error creating DB environment: %s", db_strerror(ret));
+        dbd->db_env = NULL;
+        return -1;
+    }
+
+    /* Set logfile */
+    if (dbd->db_errlog != NULL) {
+        dbd->db_env->set_errfile(dbd->db_env, dbd->db_errlog);
+        dbd->db_env->set_msgfile(dbd->db_env, dbd->db_errlog);
+        dbd->db_env->set_verbose(dbd->db_env, DB_VERB_RECOVERY, 1);
+    }
+
+    /* Open environment with recovery */
+    if ((ret = dbd->db_env->open(dbd->db_env, 
+                                 dbd->db_envhome,
+                                 DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN | DB_RECOVER | DB_PRIVATE,
+                                 0))) {
+        LOG(log_error, logtype_cnid, "error opening DB environment: %s",
+            db_strerror(ret));
+        dbd->db_env->close(dbd->db_env, 0);
+        dbd->db_env = NULL;
+        return -1;
+    }
+
+    if (dbd->db_errlog != NULL)
+        fflush(dbd->db_errlog);
+
+    /* Remove logfiles */
+    if ((ret = dbd->db_env->log_archive(dbd->db_env, NULL, DB_ARCH_REMOVE))) {
+         LOG(log_error, logtype_cnid, "error removing transaction logfiles: %s", db_strerror(ret));
+         return -1;
+    }
+
+    if ((ret = dbd->db_env->close(dbd->db_env, 0))) {
+        LOG(log_error, logtype_cnid, "error closing DB environment after recovery: %s", db_strerror(ret));
+        dbd->db_env = NULL;
+        return -1;
+    }
+
+    LOG(log_debug, logtype_cnid, "BerkeleyDB environment recovery done.");
+
+    /* Get a new db_env handle and then remove environment */
+    if ((ret = db_env_create(&dbd->db_env, 0))) {
+        LOG(log_error, logtype_cnid, "error acquiring db_end handle: %s", db_strerror(ret));
+        dbd->db_env = NULL;
+        return -1;
+    }
+    if ((ret = dbd->db_env->remove(dbd->db_env, dbd->db_envhome, 0))) {
+        LOG(log_error, logtype_cnid, "error removing BerkeleyDB environment: %s", db_strerror(ret));
+        return -1;
+    }
+
+    LOG(log_debug, logtype_cnid, "Removed BerkeleyDB environment.");
+
+    return 0;
+}
+
 /*
  *  The following three functions are wrappers for DB->get(), DB->put() and DB->del().
  *  All three return -1 on error. dbif_get()/dbif_del return 1 if the key was found and 0
index a14c02d3ba1fe13f603da96eca2df92037c77c64..577ee8442e4e62b746b439737bd0c5051763fb2a 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  $Id: dbif.h,v 1.7 2009-05-22 20:48:44 franklahm Exp $
+  $Id: dbif.h,v 1.8 2009-09-03 08:35:15 franklahm Exp $
  
   Copyright (C) Joerg Lenneis 2003
   Copyright (C) Frank Lahm 2009
@@ -17,8 +17,8 @@
      dbd = dbif_init("cnid2.db");
      Pass NULL to create an in-memory db.
      Note: the DBD type is NOT from BerkeleyDB ! We've defined it.
-  3. Optional:
-     Call dbif_env_open to open an dbd environment, chdir to it beforehand
+  3. Call dbif_env_open to open an dbd environment if you called dbif_init
+     with a filename.
   4. Call dbif_open to finally open the CNID database itself
   
   Querying the CNID database
   Closing
   -------
   Call dbif_close.
+
+  Silent Upgrade Support
+  ----------------------
+
+  On cnid_dbd shutdown we reopen the environment with recovery, close and then
+  remove it. This enables an upgraded netatalk installation possibly linked against
+  a newer bdb lib to succesfully open/create an environment and then silently
+  upgrade the database itself. How nice!
 */
 
 #ifndef CNID_DBD_DBIF_H
@@ -81,6 +89,7 @@ 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_get(DBD *, const int, DBT *, DBT *, u_int32_t);
 extern int dbif_pget(DBD *, const int, DBT *, DBT *, DBT *, u_int32_t);
index 83918fa63bf3e4f9d1da8724176d8dfb888ca670..fc3af8204bd7d592527d8b85b8d05aec88e7f504 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: main.c,v 1.9 2009-07-12 09:21:34 franklahm Exp $
+ * $Id: main.c,v 1.10 2009-09-03 08:35:15 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * Copyright (c) Frank Lahm 2009
@@ -371,6 +371,9 @@ int main(int argc, char *argv[])
     if (dbif_close(dbd) < 0)
         err++;
 
+    if (dbif_prep_upgrade(dir) < 0)
+        err++;
+
     free_lock(lockfd);
 
     if (err)
index 411ed06b21e7154b7add0ac6091d70c13f8a2b9c..1d27b4336facbbdf3bc087988e39dac61316a1ca 100644 (file)
@@ -1,4 +1,4 @@
-dnl $Id: db3-check.m4,v 1.19 2009-07-03 08:15:19 franklahm Exp $
+dnl $Id: db3-check.m4,v 1.20 2009-09-03 08:35:15 franklahm Exp $
 dnl Autoconf macros to check for the Berkeley DB library
 
 dnl -- check header for minimum version and return version in
@@ -86,9 +86,9 @@ AC_DEFUN([AC_PATH_BDB],[
     bdb_search_dirs="/usr/local /usr"
     search_subdirs="/ /db4.7 /db47 /db4.6 /db46 /db4.5 /db45 /db4.4 /db44 /db4"
 
-    dnl required BDB version: 4.4, because of DB_AUTO_COMMIT
+    dnl required BDB version: 4.6, because of cursor API change
     DB_MAJOR_REQ=4
-    DB_MINOR_REQ=4
+    DB_MINOR_REQ=6
     DB_PATCH_REQ=0
 
     dnl make sure atalk_libname is defined beforehand