]> arthur.barton.de Git - netatalk.git/commitdiff
Overhaul CNID dbd backend, make it default, txn only... See #2724774 after-dbd-overhaul
authorfranklahm <franklahm>
Tue, 21 Apr 2009 08:55:44 +0000 (08:55 +0000)
committerfranklahm <franklahm>
Tue, 21 Apr 2009 08:55:44 +0000 (08:55 +0000)
17 files changed:
etc/cnid_dbd/README
etc/cnid_dbd/cnid_metad.c
etc/cnid_dbd/comm.c
etc/cnid_dbd/db_param.c
etc/cnid_dbd/db_param.h
etc/cnid_dbd/dbd.h
etc/cnid_dbd/dbd_add.c
etc/cnid_dbd/dbd_dbcheck.c
etc/cnid_dbd/dbd_getstamp.c
etc/cnid_dbd/dbd_lookup.c
etc/cnid_dbd/dbif.c
etc/cnid_dbd/dbif.h
etc/cnid_dbd/main.c
include/atalk/cnid_dbd_private.h
libatalk/cnid/dbd/cnid_dbd.c
macros/cnid-backend.m4
macros/db3-check.m4

index f34d4a800f2dd19d171726edf7f6405593fd3a60..7255a9e2745e53040f65bac8d637c92e8926ff08 100644 (file)
@@ -1,9 +1,8 @@
-This is a reimplementation of the netatalk CNID database support that
-attempts to put all current functionality into a separate daemon
-called cnid_dbd. There is one such daemon per netatalk volume. The
-underlying database structure is still based on Berkeley DB and the
-database format is the same as in the current CNID implementation, so
-this can be used as a drop-in replacement.
+This is a implementation of the netatalk CNID database support that
+attempts to put all functionality into a separate daemon called cnid_dbd.
+There is one such daemon per netatalk volume. The underlying database
+structure is based on Berkeley DB and the database format is the same
+as in the cdb CNID backend, so this can be used as a drop-in replacement.
 
 Advantages: 
 
@@ -23,10 +22,10 @@ Advantages:
 
 - If an afpd process crashes, the CNID database is unaffected. If the
   process was making changes to the database at the time of the crash,
-  those changes will either be completed (no transactions) or rolled
-  back entirely (transactions). If the process was not using the
-  database at the time of the crash, no corrective action is
-  necessary. In both cases, database consistency is assured.
+  those changes will be rolled back entirely (transactions).
+  If the process was not using the database at the time of the crash,
+  no corrective action is necessary. In any case, database consistency
+  is assured.
 
 Disadvantages:
 
@@ -53,17 +52,9 @@ Disadvantages:
 
 Installation and configuration
 
-cnid_dbd is now part of a new CNID framework whereby various CNID
-backends (including the ones present so far) can be selected for afpd
-as a runtime option for a given volume. The default is to compile
-support for all these backends, so normally there is no need to
-specify other options to configure. The only exception is
-transactional support, which is enabled as the default. If you want to
-turn it off use --with-cnid-dbd-txn=no.
-
-In order to turn on cnid_dbd backend support for a given volume, set
-the option -cnidscheme:dbd in your AppleVolumes.default file or
-equivalent. The default for this parameter is -cnidscheme:cdb.
+cnid_dbd is part of the CNID framework whereby various CNID backends
+can be selected for afpd as a runtime option for a given volume.
+By default only last and dbd backend are built and dbd is the default.
 
 There are two executeables that will be built in etc/cnid_dbd and
 installed into the systems binaries directories of netatalk
@@ -80,11 +71,8 @@ as the volume is accessed again.
 cnid_metad needs one command line argument, the name of the cnid_dbd
 executeable. You can either specify "cnid_dbd" if it is in the path
 for cnid_metad or otherwise use the fully qualified pathname to
-cnid_dbd, e.g. /usr/local/netatalk/sbin/cnid_dbd. cnid_metad also uses
-a unix domain socket to receive requests from afpd. The pathname for
-that socket is /tmp/cnid_meta. It should not be deleted while
-cnid_metad runs.
-
+cnid_dbd, e.g. /usr/local/netatalk/sbin/cnid_dbd. cnid_metad listens
+on TCP port 4700 by default for request from afpd processes.
 
 cnid_dbd changes to the Berkeley DB directory on startup and sets
 effective UID and GID to owner and group of that directory. Database and
@@ -97,21 +85,14 @@ parameter value, followed by a newline. The following parameters are
 currently recognized:
 
 Name               Default
-
-backlog            20
-cachesize          1024
-nosync             0
+====               =======
+cachesize          8192
 flush_frequency    100
-flush_interval     30
+flush_interval     1800
 usock_file         <databasedirectory>/usock
-fd_table_size      16
+fd_table_size      128
 idle_timeout       600
 
-
-"backlog" specifies the maximum number of connection requests that can
-be pending on the unix domain socket cnid_dbd uses. listen(2) has more
-information about this value on your system.
-
 "cachesize" determines the size of the Berkeley DB cache in
 kilobytes. Each cnid_dbd process grabs that much memory on top of its
 normal memory footprint. It can be used to tune database
@@ -123,27 +104,16 @@ not a bottleneck on your system you might want to leave it at that
 value. The Berkeley DB Tutorial and Reference Guide has a section
 "Selecting a cache size" that gives more detailed information.
 
-"nosync" is only valid if transactional support is enabled. If it is
-set to 1, transactional changes to the database are not synchronously
-written to disk when the transaction completes. This will increase
-performance considerably at the risk of recent changes getting
-lost in case of a crash. The database will still be consistent,
-though. See "Transaction throughput" in the Berkeley DB Tutorial for
-more information.
-
 "flush_frequency" and "flush_interval" control how often changes to
 the database are written to the underlying database files if no
 transactions are used or how often the transaction system is
 checkpointed for transactions. Both of these operations are
 performed if either i) more than flush_frequency requests have been
 received or ii) more than flush_interval seconds have elapsed since
-the last save/checkpoint. If you use transactions with nosync set to
-zero these parameters only influence how long recovery takes after
-a crash, there should never be any lost data. If nosync is 1, changes
-might be lost, but only since the last checkpoint. Be careful to check
-your harddisk configuration for on disk cache settings. Many IDE disks
-just cache writes as the default behaviour, so even flushing database
-files to disk will not have the desired effect.
+the last save/checkpoint.
+Be careful to check your harddisk configuration for on disk cache
+settings. Many IDE disks just cache writes as the default behaviour,
+so even flushing database files to disk will not have the desired effect.
 
 "usock_file" gives the pathname of the unix domain socket file that
 that instance of cnid_dbd will use for receiving requests. You might
@@ -175,9 +145,6 @@ be possible to merge things again, if transactional support is
 eliminated from libatalk/cnid. I do not think it can work relieably in
 the current form anyway.
 
-- It would be more flexible to have transaction support as a run time
-option as well.
-
 - mmap for IPC would be nice as an alternative.
 
 - The parameter file parsing of db_param is very simpleminded. It is
@@ -186,12 +153,11 @@ Also, there is no support for blanks (or weird characters) in
 filenames for the usock_file parameter.
 
 - There is no protection against a malicious user connecting to the
-cnid_dbd socket and changing the database. I will adress this problem
-soon.
+cnid_dbd socket and changing the database.
 
 Please feel free to grep the source in etc/cnid_dbd and the file
 libatalk/cnid/dbd/cnid_dbd.c for the string TODO, which indicates
 comments that adress other, less important points.
 
 
-Joerg Lenneis, lenneis@wu-wien.ac.at
+The Netatalk Team
index aacc45afe13d408ba1edaa389a1136f2e6821080..daa70c641af14fc0c728c947dd35b0e4cc601f44 100644 (file)
@@ -1,12 +1,29 @@
 /*
- * $Id: cnid_metad.c,v 1.7 2009-03-31 12:13:00 franklahm Exp $
+ * $Id: cnid_metad.c,v 1.8 2009-04-21 08:55:44 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
  *
  */
 
-/* cnid_dbd metadaemon to start up cnid_dbd upon request from afpd */
+/* 
+   cnid_dbd metadaemon to start up cnid_dbd upon request from afpd.
+   Here is how it works:
+   
+                       via TCP socket
+   1.       afpd          ------->        cnid_metad
+
+                   via UNIX domain socket
+   2.   cnid_metad        ------->         cnid_dbd
+
+                    passes afpd client fd
+   3.   cnid_metad        ------->         cnid_dbd
+
+   Result:
+                       via TCP socket
+   4.       afpd          ------->         cnid_dbd
+ */
+
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -41,8 +58,8 @@
 #include <stdio.h>
 #include <time.h>
 #include <sys/ioctl.h>
-  
-#ifndef WEXITSTATUS 
+
+#ifndef WEXITSTATUS
 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
 #endif /* ! WEXITSTATUS */
 #ifndef WIFEXITED
 #include "usockfd.h"
 
 #define DBHOME        ".AppleDB"
-#define DBHOMELEN    8      
+#define DBHOMELEN    8
 
 static int srvfd;
 static int rqstfd;
 volatile sig_atomic_t alarmed = 0;
 
-#define MAXSRV 512
-
 #define MAXSPAWN   3                   /* Max times respawned in.. */
-
+#define MAXVOLS    512
 #define DEFAULTHOST  "localhost"
 #define DEFAULTPORT  4700
 #define TESTTIME   22                  /* this much seconds apfd client tries to
@@ -110,19 +125,19 @@ struct server {
     pid_t pid;
     time_t tm;                    /* When respawned last */
     int count;                    /* Times respawned in the last TESTTIME secondes */
-    int toofast; 
+    int toofast;
     int control_fd;               /* file descriptor to child cnid_dbd process */
 };
 
-static struct server srv[MAXSRV +1];
+static struct server srv[MAXVOLS];
 
 /* Default logging config: log to syslog with level log_note */
 static char *logconfig = "default log_note";
 
-static struct server *test_usockfn(char *dir, char *fn _U_)
+static struct server *test_usockfn(char *dir)
 {
-int i;
-    for (i = 1; i <= MAXSRV; i++) {
+    int i;
+    for (i = 0; i < MAXVOLS; i++) {
         if (srv[i].name && !strcmp(srv[i].name, dir)) {
             return &srv[i];
         }
@@ -133,54 +148,54 @@ int i;
 /* -------------------- */
 static int send_cred(int socket, int fd)
 {
-   int ret;
-   struct msghdr msgh; 
-   struct iovec iov[1];
-   struct cmsghdr *cmsgp = NULL;
-   char *buf;
-   size_t size;
-   int er=0;
-
-   size = CMSG_SPACE(sizeof fd);
-   buf = malloc(size);
-   if (!buf) {
-       LOG(log_error, logtype_cnid, "error in sendmsg: %s", strerror(errno));
-       return -1;
-   }
-
-   memset(&msgh,0,sizeof (msgh));
-   memset(buf,0, size);
-
-   msgh.msg_name = NULL;
-   msgh.msg_namelen = 0;
-
-   msgh.msg_iov = iov;
-   msgh.msg_iovlen = 1;
-
-   iov[0].iov_base = &er;
-   iov[0].iov_len = sizeof(er);
-
-   msgh.msg_control = buf;
-   msgh.msg_controllen = size;
-
-   cmsgp = CMSG_FIRSTHDR(&msgh);
-   cmsgp->cmsg_level = SOL_SOCKET;
-   cmsgp->cmsg_type = SCM_RIGHTS;
-   cmsgp->cmsg_len = CMSG_LEN(sizeof(fd));
-
-   *((int *)CMSG_DATA(cmsgp)) = fd;
-   msgh.msg_controllen = cmsgp->cmsg_len;
-
-   do  {
-       ret = sendmsg(socket,&msgh, 0);
-   } while ( ret == -1 && errno == EINTR );
-   if (ret == -1) {
-       LOG(log_error, logtype_cnid, "error in sendmsg: %s", strerror(errno));
-       free(buf);
-       return -1;
-   }
-   free(buf);
-   return 0;
+    int ret;
+    struct msghdr msgh;
+    struct iovec iov[1];
+    struct cmsghdr *cmsgp = NULL;
+    char *buf;
+    size_t size;
+    int er=0;
+
+    size = CMSG_SPACE(sizeof fd);
+    buf = malloc(size);
+    if (!buf) {
+        LOG(log_error, logtype_cnid, "error in sendmsg: %s", strerror(errno));
+        return -1;
+    }
+
+    memset(&msgh,0,sizeof (msgh));
+    memset(buf,0, size);
+
+    msgh.msg_name = NULL;
+    msgh.msg_namelen = 0;
+
+    msgh.msg_iov = iov;
+    msgh.msg_iovlen = 1;
+
+    iov[0].iov_base = &er;
+    iov[0].iov_len = sizeof(er);
+
+    msgh.msg_control = buf;
+    msgh.msg_controllen = size;
+
+    cmsgp = CMSG_FIRSTHDR(&msgh);
+    cmsgp->cmsg_level = SOL_SOCKET;
+    cmsgp->cmsg_type = SCM_RIGHTS;
+    cmsgp->cmsg_len = CMSG_LEN(sizeof(fd));
+
+    *((int *)CMSG_DATA(cmsgp)) = fd;
+    msgh.msg_controllen = cmsgp->cmsg_len;
+
+    do  {
+        ret = sendmsg(socket,&msgh, 0);
+    } while ( ret == -1 && errno == EINTR );
+    if (ret == -1) {
+        LOG(log_error, logtype_cnid, "error in sendmsg: %s", strerror(errno));
+        free(buf);
+        return -1;
+    }
+    free(buf);
+    return 0;
 }
 
 /* -------------------- */
@@ -194,104 +209,101 @@ static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
     char buf1[8];
     char buf2[8];
 
-    up = test_usockfn(dbdir, usockfn);
+    LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: dbdir: '%s', UNIX socket file: '%s'", 
+        dbdir, usockfn);
+
+    up = test_usockfn(dbdir);
     if (up && up->pid) {
-       /* we already have a process, send our fd */
-       if (send_cred(up->control_fd, rqstfd) < 0) {
-           /* FIXME */
-           return -1;
-       }
-       return 0;
+        /* we already have a process, send our fd */
+        if (send_cred(up->control_fd, rqstfd) < 0) {
+            /* FIXME */
+            return -1;
+        }
+        return 0;
     }
 
+    LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: no cnid_dbd for that volume yet. Starting one ...");
+
     time(&t);
     if (!up) {
         /* find an empty slot */
-        for (i = 1; i <= MAXSRV; i++) {
-            if (!srv[i].pid && srv[i].tm + TESTTIME < t) {
+        for (i = 0; i < MAXVOLS; i++) {
+            if ( !srv[i].pid ) {
                 up = &srv[i];
-                free(up->name);
                 up->tm = t;
                 up->count = 0;
                 up->toofast = 0;
-                /* copy name */
                 up->name = strdup(dbdir);
                 break;
             }
         }
         if (!up) {
-           LOG(log_error, logtype_cnid, "no free slot");
-           return -1;
+            LOG(log_error, logtype_cnid, "no free slot for cnid_dbd child. Configured maximum: %d. Do you have so many volumes?", MAXVOLS);
+            return -1;
         }
     }
     else {
         /* we have a slot but no process, check for respawn too fast */
-        if (up->tm + TESTTIME > t) {
-            if (up->toofast) {
-                /* silently exit */
-                return -1;
-            }
-            up->count++;
-        } else {
-            up->count = 0;
-           up->toofast = 0;
-            up->tm = t;
-        }
-        if (up->count > MAXSPAWN) {
-           up->toofast = 1;
-            up->tm = t;
-           LOG(log_error, logtype_cnid, "respawn too fast %s", up->name);
-           /* FIXME should we sleep a little ? */
-           return -1;
+        if ( (t < (up->tm + TESTTIME)) /* We're in the respawn time window */
+             &&
+             (up->count > MAXSPAWN) ) /* ...and already tried to fork too often */
+            return -1; /* just exit, dont sleep, because we might have work to do for another client  */
+
+        if ( t >= (up->tm + TESTTIME) ) { /* "reset" timer and count */
+             up->count = 0;
+             up->tm = t;
         }
-        
+        up->count++;
     }
-    /* create socketpair for comm between parent and child 
-     * FIXME Do we really need a permanent pipe between them ?
-     */
+
+    /* 
+       Create socketpair for comm between parent and child.
+       We use it to pass fds from connecting afpd processes to our
+       cnid_dbd child via fd passing.
+    */
     if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) {
-       LOG(log_error, logtype_cnid, "error in socketpair: %s", strerror(errno));
-       return -1;
+        LOG(log_error, logtype_cnid, "error in socketpair: %s", strerror(errno));
+        return -1;
     }
-        
+
     if ((pid = fork()) < 0) {
-       LOG(log_error, logtype_cnid, "error in fork: %s", strerror(errno));
-       return -1;
-    }    
+        LOG(log_error, logtype_cnid, "error in fork: %s", strerror(errno));
+        return -1;
+    }
     if (pid == 0) {
         int ret;
-       /*
-        *  Child. Close descriptors and start the daemon. If it fails
-        *  just log it. The client process will fail connecting
-        *  afterwards anyway.
-        */
-
-       close(srvfd);
-       close(sv[0]);
-       
-       for (i = 1; i <= MAXSRV; i++) {
+        /*
+         *  Child. Close descriptors and start the daemon. If it fails
+         *  just log it. The client process will fail connecting
+         *  afterwards anyway.
+         */
+
+        close(srvfd);
+        close(sv[0]);
+
+        for (i = 0; i < MAXVOLS; i++) {
             if (srv[i].pid && up != &srv[i]) {
-               close(srv[i].control_fd);
+                close(srv[i].control_fd);
             }
         }
 
-       sprintf(buf1, "%i", sv[1]);
-       sprintf(buf2, "%i", rqstfd);
-       
-       if (up->count == MAXSPAWN) {
-           /* there's a pb with the db inform child 
-            * it will run recover, delete the db whatever
-           */
-           LOG(log_error, logtype_cnid, "try with -d %s", up->name);
-           ret = execlp(dbdpn, dbdpn, "-d", dbdir, buf1, buf2, logconfig, NULL);
-       }
-       else {
-           ret = execlp(dbdpn, dbdpn, dbdir, buf1, buf2, logconfig, NULL);
-       }
-       if (ret < 0) {
-           LOG(log_error, logtype_cnid, "Fatal error in exec: %s", strerror(errno));
-           exit(0);
-       }
+        sprintf(buf1, "%i", sv[1]);
+        sprintf(buf2, "%i", rqstfd);
+
+        if (up->count == MAXSPAWN) {
+            /* there's a pb with the db inform child
+             * it will run recover, delete the db whatever
+             */
+            LOG(log_error, logtype_cnid, "try with -d %s", up->name);
+            ret = execlp(dbdpn, dbdpn, "-d", dbdir, buf1, buf2, logconfig, NULL);
+        }
+        else {
+            ret = execlp(dbdpn, dbdpn, dbdir, buf1, buf2, logconfig, NULL);
+        }
+        if (ret < 0) {
+            LOG(log_error, logtype_cnid, "Fatal error in exec: %s", strerror(errno));
+            exit(0);
+        }
     }
     /*
      *  Parent.
@@ -305,7 +317,7 @@ static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
 /* ------------------ */
 static int set_dbdir(char *dbdir, int len)
 {
-   struct stat st;
+    struct stat st;
 
     if (!len)
         return -1;
@@ -316,60 +328,60 @@ static int set_dbdir(char *dbdir, int len)
     }
 
     if (dbdir[len - 1] != '/') {
-         strcat(dbdir, "/");
-         len++;
+        strcat(dbdir, "/");
+        len++;
     }
     strcpy(dbdir + len, DBHOME);
     if (stat(dbdir, &st) < 0 && mkdir(dbdir, 0755 ) < 0) {
         LOG(log_error, logtype_cnid, "set_dbdir: mkdir failed for %s", dbdir);
         return -1;
     }
-    return 0;   
+    return 0;
 }
 
 /* ------------------ */
 uid_t user_to_uid ( username )
-char    *username;
+    char    *username;
 {
     struct passwd *this_passwd;
+
     /* check for anything */
     if ( !username || strlen ( username ) < 1 ) return 0;
+
     /* grab the /etc/passwd record relating to username */
     this_passwd = getpwnam ( username );
+
     /* return false if there is no structure returned */
     if (this_passwd == NULL) return 0;
+
     /* return proper uid */
     return this_passwd->pw_uid;
-} 
+
+}
 
 /* ------------------ */
 gid_t group_to_gid ( group )
-char    *group;
+    char    *group;
 {
     struct group *this_group;
+
     /* check for anything */
     if ( !group || strlen ( group ) < 1 ) return 0;
+
     /* grab the /etc/groups record relating to group */
     this_group = getgrnam ( group );
+
     /* return false if there is no structure returned */
     if (this_group == NULL) return 0;
+
     /* return proper gid */
     return this_group->gr_gid;
+
 }
 
 /* ------------------ */
 void catch_alarm(int sig) {
-       alarmed = 1;
+    alarmed = 1;
 }
 
 /* ------------------ */
@@ -392,14 +404,14 @@ int main(int argc, char *argv[])
     int    ret;
 
     set_processname("cnid_metad");
-    
+
     while (( cc = getopt( argc, argv, "ds:p:h:u:g:l:")) != -1 ) {
         switch (cc) {
         case 'd':
             debug = 1;
             break;
         case 'h':
-            host = strdup(optarg);  
+            host = strdup(optarg);
             break;
         case 'u':
             uid = user_to_uid (optarg);
@@ -436,9 +448,9 @@ int main(int argc, char *argv[])
         LOG(log_error, logtype_cnid, "main: bad arguments");
         exit(1);
     }
-    
+
     if (!debug) {
+
         switch (fork()) {
         case 0 :
             fclose(stdin);
@@ -447,7 +459,7 @@ int main(int argc, char *argv[])
 
 #ifdef TIOCNOTTY
             {
-               int i;
+                int i;
                 if (( i = open( "/dev/tty", O_RDWR )) >= 0 ) {
                     (void)ioctl( i, TIOCNOTTY, 0 );
                     setpgid( 0, getpid());
@@ -457,7 +469,7 @@ int main(int argc, char *argv[])
 #else
             setpgid( 0, getpid());
 #endif
-           break;
+            break;
         case -1 :  /* error */
             LOG(log_error, logtype_cnid, "detach from terminal: %s", strerror(errno));
             exit(1);
@@ -491,29 +503,28 @@ int main(int argc, char *argv[])
 
     while (1) {
         rqstfd = usockfd_check(srvfd, 10000000);
-       /* Collect zombie processes and log what happened to them */       
+        /* Collect zombie processes and log what happened to them */
         while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
-           for (i = 1; i <= MAXSRV; i++) {
-               if (srv[i].pid == pid) {
-                   srv[i].pid = 0;
-#if 0                   
-                   free(srv[i].name);
-#endif                   
-                   close(srv[i].control_fd);
-                   break;
-               }
+            for (i = 0; i < MAXVOLS; i++) {
+                if (srv[i].pid == pid) {
+                    srv[i].pid = 0;
+                    free(srv[i].name);
+                    srv[i].name = NULL;
+                    close(srv[i].control_fd);
+                    break;
+                }
             }
-           if (WIFEXITED(status)) {
-               LOG(log_info, logtype_cnid, "cnid_dbd pid %i exited with exit code %i", 
-                   pid, WEXITSTATUS(status));
-           }
-           else if (WIFSIGNALED(status)) {
-               LOG(log_info, logtype_cnid, "cnid_dbd pid %i exited with signal %i", 
-                   pid, WTERMSIG(status));
-           }
-           /* FIXME should */
-           
-       }
+            if (WIFEXITED(status)) {
+                LOG(log_info, logtype_cnid, "cnid_dbd pid %i exited with exit code %i",
+                    pid, WEXITSTATUS(status));
+            }
+            else if (WIFSIGNALED(status)) {
+                LOG(log_info, logtype_cnid, "cnid_dbd pid %i exited with signal %i",
+                    pid, WTERMSIG(status));
+            }
+            /* FIXME should */
+
+        }
         if (rqstfd <= 0)
             continue;
 
@@ -521,13 +532,13 @@ int main(int argc, char *argv[])
            SIGIPE ignored there? Answer: Ignored for dsi, but not for asp ... */
         alarm(5); /* to prevent read from getting stuck */
         ret = read(rqstfd, &len, sizeof(int));
-       alarm(0);
-       if (alarmed) {
-           alarmed = 0;
-           LOG(log_severe, logtype_cnid, "Read(1) bailed with alarm (timeout)");
-           goto loop_end;
-       }
-       
+        alarm(0);
+        if (alarmed) {
+            alarmed = 0;
+            LOG(log_severe, logtype_cnid, "Read(1) bailed with alarm (timeout)");
+            goto loop_end;
+        }
+
         if (!ret) {
             /* already close */
             goto loop_end;
@@ -541,37 +552,37 @@ int main(int argc, char *argv[])
             goto loop_end;
         }
         /*
-         *  checks for buffer overruns. The client libatalk side does it too 
+         *  checks for buffer overruns. The client libatalk side does it too
          *  before handing the dir path over but who trusts clients?
          */
         if (!len || len +DBHOMELEN +2 > MAXPATHLEN) {
             LOG(log_error, logtype_cnid, "wrong len parameter: %d", len);
             goto loop_end;
         }
-        
+
         alarm(5);
-       actual_len = read(rqstfd, dbdir, len);
-       alarm(0);
-       if (alarmed) {
-           alarmed = 0;
-           LOG(log_severe, logtype_cnid, "Read(2) bailed with alarm (timeout)");
-           goto loop_end;
-       }
+        actual_len = read(rqstfd, dbdir, len);
+        alarm(0);
+        if (alarmed) {
+            alarmed = 0;
+            LOG(log_severe, logtype_cnid, "Read(2) bailed with alarm (timeout)");
+            goto loop_end;
+        }
         if (actual_len != len) {
             LOG(log_error, logtype_cnid, "error/short read (dir): %s", strerror(errno));
             goto loop_end;
         }
         dbdir[len] = '\0';
-        
+
         if (set_dbdir(dbdir, len) < 0) {
             goto loop_end;
         }
-        
-        if ((dbp = db_param_read(dbdir)) == NULL) {
+
+        if ((dbp = db_param_read(dbdir, METAD)) == NULL) {
             LOG(log_error, logtype_cnid, "Error reading config file");
             goto loop_end;
         }
-       maybe_start_dbd(dbdpn, dbdir, dbp->usock_file);
+        maybe_start_dbd(dbdpn, dbdir, dbp->usock_file);
 
     loop_end:
         close(rqstfd);
index e909d6345374ca79e17aa5e70008942c5743e2ef..853e0e9f47acf3b642736769e177bcd5d5d03529 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: comm.c,v 1.2 2005-04-28 20:49:47 bfernhomberg Exp $
+ * $Id: comm.c,v 1.3 2009-04-21 08:55:44 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -7,7 +7,7 @@
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
-#endif 
+#endif
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -16,7 +16,7 @@
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
-#endif 
+#endif
 
 #include <sys/param.h>
 #define _XPG4_2 1
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
-#endif 
+#endif
 
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
-#endif 
+#endif
 
 #ifdef HAVE_SYS_UIO_H
 #include <sys/uio.h>
-#endif 
+#endif
 
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
@@ -51,7 +51,7 @@
 
 /* Length of the space taken up by a padded control message of length len */
 #ifndef CMSG_SPACE
-#define        CMSG_SPACE(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + __CMSG_ALIGN(len))
+#define CMSG_SPACE(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + __CMSG_ALIGN(len))
 #endif
 
 
@@ -73,27 +73,27 @@ static void invalidate_fd(int fd)
 
     if (fd == control_fd)
         return;
-    for (i = 0; i != fds_in_use; i++) 
-       if (fd_table[i].fd == fd)
-           break;
-    
+    for (i = 0; i != fds_in_use; i++)
+        if (fd_table[i].fd == fd)
+            break;
+
     assert(i < fds_in_use);
 
     fds_in_use--;
     fd_table[i] = fd_table[fds_in_use];
     fd_table[fds_in_use].fd = -1;
-    close(fd);    
+    close(fd);
     return;
 }
 
 static int recv_cred(int fd)
 {
-int ret;
-struct msghdr msgh; 
-struct iovec iov[1];
-struct cmsghdr *cmsgp = NULL;
-char buf[CMSG_SPACE(sizeof(int))];
-char dbuf[80];
+    int ret;
+    struct msghdr msgh;
+    struct iovec iov[1];
+    struct cmsghdr *cmsgp = NULL;
+    char buf[CMSG_SPACE(sizeof(int))];
+    char dbuf[80];
 
     memset(&msgh,0,sizeof(msgh));
     memset(buf,0,sizeof(buf));
@@ -111,24 +111,24 @@ char dbuf[80];
     msgh.msg_controllen = sizeof(buf);
 
     do  {
-          ret = recvmsg(fd ,&msgh,0);
+        ret = recvmsg(fd ,&msgh,0);
     } while ( ret == -1 && errno == EINTR );
 
     if ( ret == -1 ) {
         return -1;
     }
-      
+
     for ( cmsgp = CMSG_FIRSTHDR(&msgh); cmsgp != NULL; cmsgp = CMSG_NXTHDR(&msgh,cmsgp) ) {
         if ( cmsgp->cmsg_level == SOL_SOCKET && cmsgp->cmsg_type == SCM_RIGHTS ) {
-              return *(int *) CMSG_DATA(cmsgp);
+            return *(int *) CMSG_DATA(cmsgp);
         }
     }
 
     if ( ret == sizeof (int) )
-       errno = *(int *)dbuf; /* Rcvd errno */
+        errno = *(int *)dbuf; /* Rcvd errno */
     else
-       errno = ENOENT;    /* Default errno */
-   
+        errno = ENOENT;    /* Default errno */
+
     return -1;
 }
 
@@ -150,14 +150,14 @@ static int check_fd()
     int i;
     int maxfd = control_fd;
     time_t t;
-    
+
     FD_ZERO(&readfds);
     FD_SET(control_fd, &readfds);
-    
+
     for (i = 0; i != fds_in_use; i++) {
-       FD_SET(fd_table[i].fd, &readfds);
-       if (maxfd < fd_table[i].fd)
-           maxfd = fd_table[i].fd;
+        FD_SET(fd_table[i].fd, &readfds);
+        if (maxfd < fd_table[i].fd)
+            maxfd = fd_table[i].fd;
     }
 
     tv.tv_usec = 0;
@@ -170,43 +170,43 @@ static int check_fd()
     }
 
     if (!ret)
-       return 0;
+        return 0;
 
     time(&t);
 
     if (FD_ISSET(control_fd, &readfds)) {
-       int    l = 0;
-       
+        int    l = 0;
+
         fd = recv_cred(control_fd);
         if (fd < 0) {
             return -1;
         }
-       if (fds_in_use < fd_table_size) {
-           fd_table[fds_in_use].fd = fd;
-           fd_table[fds_in_use].tm = t;
-           fds_in_use++;
-       } else {
-           time_t older = t;
-            
-           for (i = 0; i != fds_in_use; i++) {
-               if (older <= fd_table[i].tm) {
-                   older = fd_table[i].tm;
-                   l = i;
-               }
-           }
-           close(fd_table[l].fd);
-           fd_table[l].fd = fd;
-           fd_table[l].tm = t;
-       }
-       return 0;
+        if (fds_in_use < fd_table_size) {
+            fd_table[fds_in_use].fd = fd;
+            fd_table[fds_in_use].tm = t;
+            fds_in_use++;
+        } else {
+            time_t older = t;
+
+            for (i = 0; i != fds_in_use; i++) {
+                if (older <= fd_table[i].tm) {
+                    older = fd_table[i].tm;
+                    l = i;
+                }
+            }
+            close(fd_table[l].fd);
+            fd_table[l].fd = fd;
+            fd_table[l].tm = t;
+        }
+        return 0;
     }
 
     for (i = 0; i != fds_in_use; i++) {
-       if (FD_ISSET(fd_table[i].fd, &readfds)) {
-           fd_table[i].tm = t;
-           return fd_table[i].fd;
-       }
-    }      
+        if (FD_ISSET(fd_table[i].fd, &readfds)) {
+            fd_table[i].tm = t;
+            return fd_table[i].fd;
+        }
+    }
     /* We should never get here */
     return 0;
 }
@@ -217,13 +217,13 @@ int comm_init(struct db_param *dbp, int ctrlfd, int clntfd)
 
     fds_in_use = 0;
     fd_table_size = dbp->fd_table_size;
-    
+
     if ((fd_table = malloc(fd_table_size * sizeof(struct connection))) == NULL) {
         LOG(log_error, logtype_cnid, "Out of memory");
-       return -1;
+        return -1;
     }
     for (i = 0; i != fd_table_size; i++)
-       fd_table[i].fd = -1;
+        fd_table[i].fd = -1;
     /* from dup2 */
     control_fd = ctrlfd;
 #if 0
@@ -231,17 +231,17 @@ int comm_init(struct db_param *dbp, int ctrlfd, int clntfd)
     /* this one dump core in recvmsg, great */
     if ( setsockopt(control_fd, SOL_SOCKET, SO_PASSCRED, &b, sizeof (b)) < 0) {
         LOG(log_error, logtype_cnid, "setsockopt SO_PASSCRED %s",  strerror(errno));
-       return -1;
+        return -1;
     }
 #endif
     /* push the first client fd */
     fd_table[fds_in_use].fd = clntfd;
     fds_in_use++;
-    
+
     return 0;
 }
 
-/* ------------ 
+/* ------------
    nbe of clients
 */
 int comm_nbe(void)
@@ -262,8 +262,8 @@ int comm_rcv(struct cnid_dbd_rqst *rqst)
         return 0;
     nametmp = rqst->name;
     if ((b = read(cur_fd, rqst, sizeof(struct cnid_dbd_rqst))) != sizeof(struct cnid_dbd_rqst)) {
-       if (b)
-           LOG(log_error, logtype_cnid, "error reading message header: %s", strerror(errno));
+        if (b)
+            LOG(log_error, logtype_cnid, "error reading message header: %s", strerror(errno));
         invalidate_fd(cur_fd);
         rqst->name = nametmp;
         return 0;
@@ -277,7 +277,7 @@ int comm_rcv(struct cnid_dbd_rqst *rqst)
     /* We set this to make life easier for logging. None of the other stuff
        needs zero terminated strings. */
     rqst->name[rqst->namelen] = '\0';
-        
+
     return 1;
 }
 
@@ -285,9 +285,9 @@ int comm_rcv(struct cnid_dbd_rqst *rqst)
 #define USE_WRITEV
 int comm_snd(struct cnid_dbd_rply *rply)
 {
-#ifdef USE_WRITEV 
-  struct iovec iov[2];
-  size_t towrite;
+#ifdef USE_WRITEV
+    struct iovec iov[2];
+    size_t towrite;
 #endif
 
     if (!rply->namelen) {
@@ -298,7 +298,7 @@ int comm_snd(struct cnid_dbd_rply *rply)
         }
         return 1;
     }
-#ifdef USE_WRITEV 
+#ifdef USE_WRITEV
 
     iov[0].iov_base = rply;
     iov[0].iov_len = sizeof(struct cnid_dbd_rply);
@@ -322,7 +322,7 @@ int comm_snd(struct cnid_dbd_rply *rply)
         invalidate_fd(cur_fd);
         return 0;
     }
-#endif    
+#endif
     return 1;
 }
 
index 4fb20b018ea92d44179d0b9be06e84b92983ae0d..413071fb06f1fe9f2f97d42b2ad2d95411623057 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * $Id: db_param.c,v 1.3 2009-02-04 20:28:01 didg Exp $
+ * $Id: db_param.c,v 1.4 2009-04-21 08:55:44 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
+ * Copyright (c) Frank Lahm 2009
  * All Rights Reserved.  See COPYING.
  */
 
 #include <errno.h>
 #include <sys/param.h>
 #include <sys/un.h>
-
-
 #include <atalk/logger.h>
 
 #include "db_param.h"
 
-
 #define DB_PARAM_FN       "db_param"
 #define MAXKEYLEN         64
 
-#define DEFAULT_LOGFILE_AUTOREMOVE 0   
-#define DEFAULT_CACHESIZE          1024 * 4 
-#define DEFAULT_NOSYNC             0    
-#define DEFAULT_FLUSH_FREQUENCY    100  
-#define DEFAULT_FLUSH_INTERVAL     30   
+#define DEFAULT_LOGFILE_AUTOREMOVE 1
+#define DEFAULT_CACHESIZE          8 * 1024 
+#define DEFAULT_FLUSH_FREQUENCY    100
+#define DEFAULT_FLUSH_INTERVAL     1800
 #define DEFAULT_USOCK_FILE         "usock"
-#define DEFAULT_FD_TABLE_SIZE      64
-#define DEFAULT_IDLE_TIMEOUT       600
-#define DEFAULT_CHECK              0
+#define DEFAULT_FD_TABLE_SIZE      128
+#define DEFAULT_IDLE_TIMEOUT       10 * 60
 
 static struct db_param params;
 static int parse_err;
@@ -46,7 +42,6 @@ static int parse_err;
 static size_t usock_maxlen()
 {
     struct sockaddr_un addr;
-
     return sizeof(addr.sun_path) - 1;
 }
 
@@ -72,10 +67,8 @@ static int make_pathname(char *path, char *dir, char *fn, size_t maxlen)
 
 static void default_params(struct db_param *dbp, char *dir)
 {        
-    dbp->check               = DEFAULT_CHECK;
     dbp->logfile_autoremove  = DEFAULT_LOGFILE_AUTOREMOVE;
     dbp->cachesize           = DEFAULT_CACHESIZE;
-    dbp->nosync              = DEFAULT_NOSYNC;
     dbp->flush_frequency     = DEFAULT_FLUSH_FREQUENCY;
     dbp->flush_interval      = DEFAULT_FLUSH_INTERVAL;
     if (make_pathname(dbp->usock_file, dir, DEFAULT_USOCK_FILE, usock_maxlen()) < 0) {
@@ -84,6 +77,7 @@ static void default_params(struct db_param *dbp, char *dir)
     }
     dbp->fd_table_size       = DEFAULT_FD_TABLE_SIZE;
     dbp->idle_timeout        = DEFAULT_IDLE_TIMEOUT;
+
     return;
 }
 
@@ -105,7 +99,7 @@ static int parse_int(char *val)
    buffer overflow) nor elegant, we need to add support for whitespace in
    filenames as well. */
 
-struct db_param *db_param_read(char *dir)
+struct db_param *db_param_read(char *dir, enum identity id)
 {
     FILE *fp;
     static char key[MAXKEYLEN + 1];
@@ -114,6 +108,7 @@ struct db_param *db_param_read(char *dir)
     int    items;
     
     default_params(&params, dir);
+    params.dir = dir;
     
     if (make_pathname(pfn, dir, DB_PARAM_FN, MAXPATHLEN) < 0) {
         LOG(log_error, logtype_cnid, "Parameter filename too long");
@@ -141,33 +136,44 @@ struct db_param *db_param_read(char *dir)
             parse_err++;
             break;
         }
-        
-        if (! strcmp(key, "logfile_autoremove")) 
-            params.logfile_autoremove = parse_int(val);
-        else if (! strcmp(key, "cachesize"))
-            params.cachesize = parse_int(val);
-        else if (! strcmp(key, "nosync"))
-            params.nosync = parse_int(val);
-        else if (! strcmp(key, "check"))
-            params.check = parse_int(val);
-        else if (! strcmp(key, "flush_frequency"))
-            params.flush_frequency = parse_int(val);
-        else if (! strcmp(key, "flush_interval"))
-            params.flush_interval = parse_int(val);
-        else if (! strcmp(key, "usock_file")) {
+
+        /* Config for both cnid_meta and dbd */
+        if (! strcmp(key, "usock_file")) {
             if (make_pathname(params.usock_file, dir, val, usock_maxlen()) < 0) {
                 LOG(log_error, logtype_cnid, "usock filename %s too long", val);
                 parse_err++;
+            } else
+                LOG(log_info, logtype_cnid, "db_param: setting UNIX domain socket filename to %s", params.usock_file);
+        }
+
+        /* Config for cnid_metad only */
+        if ( id == METAD ) {
+            /* Currently empty */
+        }
+
+        /* Config for dbd only */
+        else if (id == DBD ) {
+            if (! strcmp(key, "fd_table_size")) {
+                params.fd_table_size = parse_int(val);
+                LOG(log_info, logtype_cnid, "db_param: setting max number of concurrent afpd connections per volume (fd_table_size) to %d", params.fd_table_size);
+            } else if (! strcmp(key, "logfile_autoremove")) {
+                params.logfile_autoremove = parse_int(val);
+                LOG(log_info, logtype_cnid, "db_param: setting logfile_autoremove to %d", params.logfile_autoremove);
+            } else if (! strcmp(key, "cachesize")) {
+                params.cachesize = parse_int(val);
+                LOG(log_info, logtype_cnid, "db_param: setting cachesize to %d", params.cachesize);
+            } else if (! strcmp(key, "flush_frequency")) {
+                params.flush_frequency = parse_int(val);
+                LOG(log_info, logtype_cnid, "db_param: setting flush_frequency to %d", params.flush_frequency);
+            } else if (! strcmp(key, "flush_interval")) {
+                params.flush_interval = parse_int(val);
+                LOG(log_info, logtype_cnid, "db_param: setting flush_interval to %d", params.flush_interval);
+            } else if (! strcmp(key, "idle_timeout")) {
+                params.idle_timeout = parse_int(val);
+                LOG(log_info, logtype_cnid, "db_param: setting idle timeout to %d", params.idle_timeout);
             }
-        } else if (! strcmp(key, "fd_table_size"))
-            params.fd_table_size = parse_int(val);
-       else if (! strcmp(key, "idle_timeout"))
-            params.idle_timeout = parse_int(val);
-       else {
-            LOG(log_error, logtype_cnid, "error parsing %s -> %s in config file", key, val);
-            parse_err++;
         }
-        if(parse_err)
+        if (parse_err)
             break;
     }
     
index 515ed9a8a2742e2aef2edb6c1a44617f683c2aad..2690673f684e715b338b6efd7abd95d7a125b735 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: db_param.h,v 1.2 2005-04-28 20:49:47 bfernhomberg Exp $
+ * $Id: db_param.h,v 1.3 2009-04-21 08:55:44 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
 #include <sys/param.h>
 #include <sys/cdefs.h>
 
+enum identity {
+    METAD,
+    DBD
+};
 
 struct db_param {
-    int check;
+    char *dir;
     int logfile_autoremove;
     int cachesize;
-    int nosync;
-    int flush_frequency;
     int flush_interval;
+    int flush_frequency;
     char usock_file[MAXPATHLEN + 1];    
     int fd_table_size;
     int idle_timeout;
+    int max_vols;
 };
 
-extern struct db_param *      db_param_read  __P((char *));
+extern struct db_param *      db_param_read  __P((char *, enum identity));
 
 
 #endif /* CNID_DBD_DB_PARAM_H */
index eb944d525ae15a32522b78f4a75b7c8fdb56b91e..f7b7567b71b52129471317dd177f800981a6f569 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd.h,v 1.2 2005-04-28 20:49:47 bfernhomberg Exp $
+ * $Id: dbd.h,v 1.3 2009-04-21 08:55:44 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -8,7 +8,6 @@
 #ifndef CNID_DBD_DBD_H
 #define CNID_DBD_DBD_H 1
 
-
 #include <atalk/cnid_dbd_private.h>
 
 extern int      dbd_stamp __P((void));
@@ -20,7 +19,6 @@ extern int      dbd_update  __P((struct cnid_dbd_rqst *, struct cnid_dbd_rply *)
 extern int      dbd_delete  __P((struct cnid_dbd_rqst *, struct cnid_dbd_rply *));
 extern int      dbd_getstamp  __P((struct cnid_dbd_rqst *, struct cnid_dbd_rply *));
 extern int      dbd_rebuild_add __P((struct cnid_dbd_rqst *, struct cnid_dbd_rply *));
-extern int      dbd_check  __P((char *));
-
+extern int      dbd_check_indexes  __P((char *));
 
 #endif /* CNID_DBD_DBD_H */
index d2e8477932c2f402ad15df9bfe49a14c08027af7..25a3afce040f48e3ed6023dca0dd1319df790495 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd_add.c,v 1.2 2005-04-28 20:49:47 bfernhomberg Exp $
+ * $Id: dbd_add.c,v 1.3 2009-04-21 08:55:44 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -128,7 +128,7 @@ int dbd_stamp(void)
     cnid_t hint;
     char buf[ROOTINFO_DATALEN];
     char stamp[CNID_DEV_LEN];
-     
+
     memset(&rootinfo_key, 0, sizeof(rootinfo_key));
     memset(&rootinfo_data, 0, sizeof(rootinfo_data));
     rootinfo_key.data = ROOTINFO_KEY;
index 4a36dcbffbd4f41e6bf21b1ff8425152ec1257e5..b55a1e5c0754e5b6121cb14c588a7ee4b8468092 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd_dbcheck.c,v 1.2 2005-04-28 20:49:48 bfernhomberg Exp $
+ * $Id: dbd_dbcheck.c,v 1.3 2009-04-21 08:55:44 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
 #include "dbif.h"
 #include "dbd.h"
 
-#ifndef CNID_BACKEND_DBD_TXN
-int dbd_check(char *dbdir)
+int dbd_check_indexes(char *dbdir)
 {
     u_int32_t c_didname = 0, c_devino = 0, c_cnid = 0;
-#if 0
-    char dbdir[MAXPATHLEN];
 
-    if (NULL == getcwd(dbdir, sizeof(dbdir)) )
-        return -1;
-#endif
-
-    LOG(log_debug, logtype_cnid, "CNID database at `%s' is being checked (quick)", dbdir);
+    LOG(log_note, logtype_cnid, "CNID database at `%s' is being checked (quick)", dbdir);
 
     if (dbif_count(DBIF_IDX_CNID, &c_cnid)) 
         return -1;
@@ -55,9 +48,8 @@ int dbd_check(char *dbdir)
         return 1;
     }
 
-    LOG(log_debug, logtype_cnid, "CNID database at `%s' seems ok, %u entries.", dbdir, c_cnid);
+    LOG(log_note, logtype_cnid, "CNID database at `%s' seems ok, %u entries.", dbdir, c_cnid);
     return 0;  
 }
 
-#endif
 
index 804878bb5372efd06a830c867c8cbd5519f86393..328e80b458faa2868ebdbb179d111a94a7c178ff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd_getstamp.c,v 1.2 2005-04-28 20:49:48 bfernhomberg Exp $
+ * $Id: dbd_getstamp.c,v 1.3 2009-04-21 08:55:44 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -50,9 +50,9 @@ int dbd_getstamp(struct cnid_dbd_rqst *rqst _U_, struct cnid_dbd_rply *rply)
     rply->namelen = CNID_DEV_LEN;
     rply->name = (char *)data.data + CNID_DEV_OFS;
     
-#ifdef DEBUG
-    LOG(log_info, logtype_cnid, "cnid_getstamp: Returning stamp");
-#endif
+
+    LOG(log_debug, logtype_cnid, "cnid_getstamp: Returning stamp '%08x'", *(uint32_t *)rply->name);
+
     rply->result = CNID_DBD_RES_OK;
     return 1;
 }
index d5073357288f4d56ad3ed81ff043842392512cbc..0c7e59a033f90012ddc4b8350747601b58ea2f63 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd_lookup.c,v 1.3 2005-05-03 14:55:11 didg Exp $
+ * $Id: dbd_lookup.c,v 1.4 2009-04-21 08:55:44 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -32,7 +32,9 @@ int dbd_lookup(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     unsigned char *buf;
     DBT key, devdata, diddata;
     char dev[CNID_DEV_LEN];
+#if 0
     char ino[CNID_INO_LEN];
+#endif
     int devino = 1, didname = 1; 
     int rc;
     cnid_t id_devino, id_didname;
@@ -50,12 +52,14 @@ int dbd_lookup(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     
     buf = pack_cnid_data(rqst); 
     memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN);
+#if 0
     /* FIXME: ino is not needed later on, remove? */
     memcpy(ino, buf + CNID_INO_OFS, CNID_INO_LEN);
+#endif
 
     /* Look for a CNID.  We have two options: dev/ino or did/name.  If we
        only get a match in one of them, that means a file has moved. */
-    key.data = buf +CNID_DEVINO_OFS;
+    key.data = buf + CNID_DEVINO_OFS;
     key.size = CNID_DEVINO_LEN;
 
     if ((rc = dbif_get(DBIF_IDX_DEVINO, &key, &devdata, 0))  < 0) {
@@ -72,10 +76,8 @@ int dbd_lookup(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
         memcpy(&type_devino, (char *)devdata.data +CNID_TYPE_OFS, sizeof(type_devino));
         type_devino = ntohl(type_devino);
     }
-    
-    /* FIXME: This second call to pack_cnid_data() is redundant, any reason it is here? */
-    buf = pack_cnid_data(rqst); 
-    key.data = buf +CNID_DID_OFS;
+
+    key.data = buf + CNID_DID_OFS;
     key.size = CNID_DID_LEN + rqst->namelen + 1;
 
     if ((rc = dbif_get(DBIF_IDX_DIDNAME, &key, &diddata, 0))  < 0) {
@@ -95,20 +97,20 @@ int dbd_lookup(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     
     if (!devino && !didname) {  
         /* not found */
-#ifdef DEBUG
-       LOG(log_info, logtype_cnid, "cnid_lookup: dev/ino %s did %u name %s neither in devino nor didname", 
-           stringify_devino(rqst->dev, rqst->ino), ntohl(rqst->did), rqst->name);
-#endif
+
+        LOG(log_debug, logtype_cnid, "cnid_lookup: dev/ino %s did %u name %s neither in devino nor didname", 
+            stringify_devino(rqst->dev, rqst->ino), ntohl(rqst->did), rqst->name);
+
         rply->result = CNID_DBD_RES_NOTFOUND;
         return 1;
     }
 
     if (devino && didname && id_devino == id_didname && type_devino == rqst->type) {
         /* the same */
-#ifdef DEBUG
-       LOG(log_info, logtype_cnid, "cnid_lookup: Looked up dev/ino %s did %u name %s as %u", 
-           stringify_devino(rqst->dev, rqst->ino), ntohl(rqst->did), rqst->name, ntohl(id_didname));
-#endif
+
+        LOG(log_debug, logtype_cnid, "cnid_lookup: Looked up dev/ino %s did %u name %s as %u", 
+            stringify_devino(rqst->dev, rqst->ino), ntohl(rqst->did), rqst->name, ntohl(id_didname));
+
         rply->cnid = id_didname;
         rply->result = CNID_DBD_RES_OK;
         return 1;
@@ -154,9 +156,9 @@ int dbd_lookup(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     if (rc >0) {
         rply->cnid = rqst->cnid;
     }
-#ifdef DEBUG
-    LOG(log_info, logtype_cnid, "cnid_lookup: Looked up dev/ino %s did %u name %s as %u (needed update)", 
-       stringify_devino(rqst->dev, rqst->ino), ntohl(rqst->did), rqst->name, ntohl(rply->cnid));
-#endif
+
+    LOG(log_debug, logtype_cnid, "cnid_lookup: Looked up dev/ino %s did %u name %s as %u (needed update)", 
+        stringify_devino(rqst->dev, rqst->ino), ntohl(rqst->did), rqst->name, ntohl(rply->cnid));
+
     return rc;
 }
index e2531e448144330b9b7ec12e00e92134a847dcbb..29e63f506c0fed0a6b503a61ef84abd9f1464c70 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbif.c,v 1.4 2008-08-07 07:39:14 didg Exp $
+ * $Id: dbif.c,v 1.5 2009-04-21 08:55:44 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
 
 #define DB_ERRLOGFILE "db_errlog"
 
-
 static DB_ENV *db_env = NULL;
 static DB_TXN *db_txn = NULL;
 static FILE   *db_errlog = NULL;
 
-#ifdef CNID_BACKEND_DBD_TXN
-#define DBOPTIONS    (DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN)
-#else
-#define DBOPTIONS    (DB_CREATE | DB_INIT_CDB | DB_INIT_MPOOL | DB_PRIVATE) 
-#endif
+/* 
+   Note: DB_INIT_LOCK is here so we can run the db_* utilities while netatalk is running.
+   It's a likey performance hit, but it might we worth it.
+ */
+#define DBOPTIONS    (DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN)
 
 static struct db_table {
-     char            *name;
-     DB              *db;
-     u_int32_t       general_flags;
-     DBTYPE          type;
+    char            *name;
+    DB              *db;
+    u_int32_t       general_flags;
+    DBTYPE          type;
 } db_table[] =
 {
-     { "cnid2.db",       NULL,      0, DB_BTREE},
-     { "devino.db",      NULL,      0, DB_BTREE},
-     { "didname.db",     NULL,      0, DB_BTREE},
+    { "cnid2.db",       NULL,      0, DB_BTREE},
+    { "devino.db",      NULL,      0, DB_BTREE},
+    { "didname.db",     NULL,      0, DB_BTREE},
 };
 
 static char *old_dbfiles[] = {"cnid.db", NULL};
@@ -57,18 +56,10 @@ extern int devino(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey);
 
 /* --------------- */
 static int  db_compat_associate (DB *p, DB *s,
-                   int (*callback)(DB *, const DBT *,const DBT *, DBT *),
-                   u_int32_t flags)
+                                 int (*callback)(DB *, const DBT *,const DBT *, DBT *),
+                                 u_int32_t flags)
 {
-#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
-    return p->associate(p, db_txn, s, callback, flags);
-#else
-#if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 0)
-    return p->associate(p,       s, callback, flags);
-#else
-    return 0;
-#endif
-#endif
+    return p->associate(p, NULL, s, callback, flags);
 }
 
 /* --------------- */
@@ -76,11 +67,7 @@ static int db_compat_open(DB *db, char *file, char *name, DBTYPE type, int mode)
 {
     int ret;
 
-#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
-    ret = db->open(db, db_txn, file, name, type, DB_CREATE, mode); 
-#else
-    ret = db->open(db,       file, name, type, DB_CREATE, mode); 
-#endif
+    ret = db->open(db, NULL, file, name, type, DB_CREATE, mode);
 
     if (ret) {
         LOG(log_error, logtype_cnid, "error opening database %s: %s", name, db_strerror(ret));
@@ -96,16 +83,16 @@ static int upgrade_required()
     int i;
     int found = 0;
     struct stat st;
-    
+
     for (i = 0; old_dbfiles[i] != NULL; i++) {
-       if ( !(stat(old_dbfiles[i], &st) < 0) ) {
-           found++;
-           continue;
-       }
-       if (errno != ENOENT) {
-           LOG(log_error, logtype_cnid, "cnid_open: Checking %s gave %s", old_dbfiles[i], strerror(errno));
-           found++;
-       }
+        if ( !(stat(old_dbfiles[i], &st) < 0) ) {
+            found++;
+            continue;
+        }
+        if (errno != ENOENT) {
+            LOG(log_error, logtype_cnid, "cnid_open: Checking %s gave %s", old_dbfiles[i], strerror(errno));
+            found++;
+        }
     }
     return found;
 }
@@ -132,39 +119,40 @@ int dbif_stamp(void *buffer, int size)
 /* --------------- */
 /*
  *  We assume our current directory is already the BDB homedir. Otherwise
- *  opening the databases will not work as expected. If we use transactions,
- *  dbif_env_init(), dbif_close() and dbif_stamp() are the only interface
- *  functions that can be called without a valid transaction handle in db_txn.
+ *  opening the databases will not work as expected.
  */
 int dbif_env_init(struct db_param *dbp)
 {
     int ret;
-#ifdef CNID_BACKEND_DBD_TXN
     char **logfiles = NULL;
     char **file;
-#endif
 
     /* Refuse to do anything if this is an old version of the CNID database */
     if (upgrade_required()) {
-       LOG(log_error, logtype_cnid, "Found version 1 of the CNID database. Please upgrade to version 2");
-       return -1;
+        LOG(log_error, logtype_cnid, "Found version 1 of the CNID database. Please upgrade to version 2");
+        return -1;
     }
 
     if ((db_errlog = fopen(DB_ERRLOGFILE, "a")) == NULL)
         LOG(log_warning, logtype_cnid, "error creating/opening DB errlogfile: %s", strerror(errno));
 
-#ifdef CNID_BACKEND_DBD_TXN
     if ((ret = db_env_create(&db_env, 0))) {
-        LOG(log_error, logtype_cnid, "error creating DB environment: %s", 
+        LOG(log_error, logtype_cnid, "error creating DB environment: %s",
             db_strerror(ret));
         db_env = NULL;
         return -1;
-    }    
-    if (db_errlog != NULL)
-        db_env->set_errfile(db_env, db_errlog); 
+    }
+
+    if (db_errlog != NULL) {
+        db_env->set_errfile(db_env, db_errlog);
+        db_env->set_msgfile(db_env, db_errlog);
+    }
+
     db_env->set_verbose(db_env, DB_VERB_RECOVERY, 1);
+
+    /* Open the database for recovery using DB_PRIVATE option which is faster */
     if ((ret = db_env->open(db_env, ".", DBOPTIONS | DB_PRIVATE | DB_RECOVER, 0))) {
-        LOG(log_error, logtype_cnid, "error opening DB environment: %s", 
+        LOG(log_error, logtype_cnid, "error opening DB environment: %s",
             db_strerror(ret));
         db_env->close(db_env, 0);
         db_env = NULL;
@@ -175,18 +163,19 @@ int dbif_env_init(struct db_param *dbp)
         fflush(db_errlog);
 
     if ((ret = db_env->close(db_env, 0))) {
-        LOG(log_error, logtype_cnid, "error closing DB environment after recovery: %s", 
+        LOG(log_error, logtype_cnid, "error closing DB environment after recovery: %s",
             db_strerror(ret));
         db_env = NULL;
         return -1;
     }
-#endif
+
     if ((ret = db_env_create(&db_env, 0))) {
         LOG(log_error, logtype_cnid, "error creating DB environment after recovery: %s",
             db_strerror(ret));
         db_env = NULL;
         return -1;
     }
+
     if ((ret = db_env->set_cachesize(db_env, 0, 1024 * dbp->cachesize, 0))) {
         LOG(log_error, logtype_cnid, "error setting DB environment cachesize to %i: %s",
             dbp->cachesize, db_strerror(ret));
@@ -194,40 +183,42 @@ int dbif_env_init(struct db_param *dbp)
         db_env = NULL;
         return -1;
     }
-    
-    if (db_errlog != NULL)
+
+    if (db_errlog != NULL) {
         db_env->set_errfile(db_env, db_errlog);
+        db_env->set_msgfile(db_env, db_errlog);
+    }
     if ((ret = db_env->open(db_env, ".", DBOPTIONS , 0))) {
         LOG(log_error, logtype_cnid, "error opening DB environment after recovery: %s",
             db_strerror(ret));
         db_env->close(db_env, 0);
         db_env = NULL;
-        return -1;      
+        return -1;
     }
 
-#ifdef CNID_BACKEND_DBD_TXN
-    if (dbp->nosync && (ret = db_env->set_flags(db_env, DB_TXN_NOSYNC, 1))) {
-        LOG(log_error, logtype_cnid, "error setting TXN_NOSYNC flag: %s",
+    if ((ret = db_env->set_flags(db_env, DB_AUTO_COMMIT, 1))) {
+        LOG(log_error, logtype_cnid, "error setting DB_AUTO_COMMIT flag: %s",
             db_strerror(ret));
         db_env->close(db_env, 0);
         db_env = NULL;
         return -1;
     }
+
     if (dbp->logfile_autoremove && db_env->log_archive(db_env, &logfiles, 0)) {
-       LOG(log_error, logtype_cnid, "error getting list of stale logfiles: %s",
+        LOG(log_error, logtype_cnid, "error getting list of stale logfiles: %s",
             db_strerror(ret));
         db_env->close(db_env, 0);
         db_env = NULL;
         return -1;
     }
     if (logfiles != NULL) {
-       for (file = logfiles; *file != NULL; file++) {
-           if (unlink(*file) < 0)
-               LOG(log_warning, logtype_cnid, "Error removing stale logfile %s: %s", *file, strerror(errno));
-       }
-       free(logfiles);
+        for (file = logfiles; *file != NULL; file++) {
+            if (unlink(*file) < 0)
+                LOG(log_warning, logtype_cnid, "Error removing stale logfile %s: %s", *file, strerror(errno));
+        }
+        free(logfiles);
     }
-#endif
+
     return 0;
 }
 
@@ -240,36 +231,27 @@ int dbif_open(struct db_param *dbp _U_, int do_truncate)
 
     for (i = 0; i != DBIF_DB_CNT; i++) {
         if ((ret = db_create(&(db_table[i].db), db_env, 0))) {
-            LOG(log_error, logtype_cnid, "error creating handle for database %s: %s", 
+            LOG(log_error, logtype_cnid, "error creating handle for database %s: %s",
                 db_table[i].name, db_strerror(ret));
             return -1;
         }
 
-        if (db_table[i].general_flags) { 
+        if (db_table[i].general_flags) {
             if ((ret = db_table[i].db->set_flags(db_table[i].db, db_table[i].general_flags))) {
-                LOG(log_error, logtype_cnid, "error setting flags for database %s: %s", 
+                LOG(log_error, logtype_cnid, "error setting flags for database %s: %s",
                     db_table[i].name, db_strerror(ret));
                 return -1;
             }
         }
 
-#if 0
-#ifndef CNID_BACKEND_DBD_TXN
-        if ((ret = db_table[i].db->set_cachesize(db_table[i].db, 0, 1024 * dbp->cachesize, 0))) {
-            LOG(log_error, logtype_cnid, "error setting DB cachesize to %i for database %s: %s",
-                dbp->cachesize, db_table[i].name, db_strerror(ret));
-            return -1;
-        }
-#endif /* CNID_BACKEND_DBD_TXN */
-#endif
         if (db_compat_open(db_table[i].db, db_table[0].name, db_table[i].name, db_table[i].type, 0664) < 0)
             return -1;
         if (db_errlog != NULL)
             db_table[i].db->set_errfile(db_table[i].db, db_errlog);
 
         if (do_truncate && i > 0) {
-           if ((ret = db_table[i].db->truncate(db_table[i].db, db_txn, &count, 0))) {
-                LOG(log_error, logtype_cnid, "error truncating database %s: %s", 
+            if ((ret = db_table[i].db->truncate(db_table[i].db, NULL, &count, 0))) {
+                LOG(log_error, logtype_cnid, "error truncating database %s: %s",
                     db_table[i].name, db_strerror(ret));
                 return -1;
             }
@@ -277,16 +259,16 @@ int dbif_open(struct db_param *dbp _U_, int do_truncate)
     }
 
     /* TODO: Implement CNID DB versioning info on new databases. */
-    /* TODO: Make transaction support a runtime option. */
+
     /* Associate the secondary with the primary. */
     if ((ret = db_compat_associate(db_table[0].db, db_table[DBIF_IDX_DIDNAME].db, didname, (do_truncate)?DB_CREATE:0)) != 0) {
         LOG(log_error, logtype_cnid, "Failed to associate didname database: %s",db_strerror(ret));
         return -1;
     }
+
     if ((ret = db_compat_associate(db_table[0].db, db_table[DBIF_IDX_DEVINO].db, devino, (do_truncate)?DB_CREATE:0)) != 0) {
         LOG(log_error, logtype_cnid, "Failed to associate devino database: %s",db_strerror(ret));
-       return -1;
+        return -1;
     }
 
     return 0;
@@ -315,11 +297,11 @@ int dbif_close()
 {
     int ret;
     int err = 0;
-    
-    if (dbif_closedb()) 
-       err++;
-     
-    if (db_env != NULL && (ret = db_env->close(db_env, 0))) { 
+
+    if (dbif_closedb())
+        err++;
+
+    if (db_env != NULL && (ret = db_env->close(db_env, 0))) {
         LOG(log_error, logtype_cnid, "error closing DB environment: %s", db_strerror(ret));
         err++;
     }
@@ -333,15 +315,11 @@ int dbif_close()
 }
 
 /*
- *  The following three functions are wrappers for DB->get(), DB->put() and
- *  DB->del(). We define them here because we want access to the db_txn
- *  transaction handle and the database handles limited to the functions in this
- *  file. A consequence is that there is always only one transaction in
- *  progress. For nontransactional access db_txn is NULL. All three return -1 on
- *  error. dbif_get()/dbif_del return 1 if the key was found and 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
  *  otherwise. dbif_put() returns 0 if key/val was successfully updated and 1 if
  *  the DB_NOOVERWRITE flag was specified and the key already exists.
- *  
+ *
  *  All return codes other than DB_NOTFOUND and DB_KEYEXIST from the DB->()
  *  functions are not expected and therefore error conditions.
  */
@@ -352,13 +330,13 @@ int dbif_get(const int dbi, DBT *key, DBT *val, u_int32_t flags)
     DB *db = db_table[dbi].db;
 
     ret = db->get(db, db_txn, key, val, flags);
-     
+
     if (ret == DB_NOTFOUND)
         return 0;
     if (ret) {
         LOG(log_error, logtype_cnid, "error retrieving value from %s: %s", db_table[dbi].name, db_strerror(errno));
         return -1;
-    } else 
+    } else
         return 1;
 }
 
@@ -370,17 +348,13 @@ int dbif_pget(const int dbi, DBT *key, DBT *pkey, DBT *val, u_int32_t flags)
 
     ret = db->pget(db, db_txn, key, pkey, val, flags);
 
-#if DB_VERSION_MAJOR >= 4
     if (ret == DB_NOTFOUND || ret == DB_SECONDARY_BAD) {
-#else
-    if (ret == DB_NOTFOUND) {
-#endif     
         return 0;
     }
     if (ret) {
         LOG(log_error, logtype_cnid, "error retrieving value from %s: %s", db_table[dbi].name, db_strerror(errno));
         return -1;
-    } else 
+   } else
         return 1;
 }
 
@@ -390,8 +364,13 @@ int dbif_put(const int dbi, DBT *key, DBT *val, u_int32_t flags)
     int ret;
     DB *db = db_table[dbi].db;
 
+    if (dbif_txn_begin() < 0) {
+        LOG(log_error, logtype_cnid, "error setting key/value in %s: %s", db_table[dbi].name, db_strerror(errno));
+        return -1;
+    }
+
     ret = db->put(db, db_txn, key, val, flags);
-     
+
     if (ret) {
         if ((flags & DB_NOOVERWRITE) && ret == DB_KEYEXIST) {
             return 1;
@@ -408,13 +387,14 @@ int dbif_del(const int dbi, DBT *key, u_int32_t flags)
     int ret;
     DB *db = db_table[dbi].db;
 
+    if (dbif_txn_begin() < 0) {
+        LOG(log_error, logtype_cnid, "error deleting key/value from %s: %s", db_table[dbi].name, db_strerror(errno));
+        return -1;
+    }
+
     ret = db->del(db, db_txn, key, flags);
 
-#if DB_VERSION_MAJOR > 3
     if (ret == DB_NOTFOUND || ret == DB_SECONDARY_BAD)
-#else
-    if (ret == DB_NOTFOUND)
-#endif
         return 0;
     if (ret) {
         LOG(log_error, logtype_cnid, "error deleting key/value from %s: %s", db_table[dbi].name, db_strerror(errno));
@@ -423,46 +403,50 @@ int dbif_del(const int dbi, DBT *key, u_int32_t flags)
         return 1;
 }
 
-#ifdef CNID_BACKEND_DBD_TXN
-
 int dbif_txn_begin()
 {
     int ret;
-#if DB_VERSION_MAJOR >= 4
+
+    /* If we already have a acitve txn, just return */
+    if (db_txn)
+        return 0;
+
     ret = db_env->txn_begin(db_env, NULL, &db_txn, 0);
-#else     
-    ret = txn_begin(db_env, NULL, &db_txn, 0);
-#endif
+
     if (ret) {
         LOG(log_error, logtype_cnid, "error starting transaction: %s", db_strerror(errno));
         return -1;
-    } else 
+    } else
         return 0;
 }
 
 int dbif_txn_commit()
 {
     int ret;
-#if DB_VERSION_MAJOR >= 4
+
+    if (!db_txn)
+        return 0;
+
     ret = db_txn->commit(db_txn, 0);
-#else
-    ret = txn_commit(db_txn, 0);
-#endif
+    db_txn = NULL;
+    
     if (ret) {
         LOG(log_error, logtype_cnid, "error committing transaction: %s", db_strerror(errno));
         return -1;
-    } else 
-        return 0;
+    } else
+        return 1;
 }
 
 int dbif_txn_abort()
 {
     int ret;
-#if DB_VERSION_MAJOR >= 4
+
+    if (!db_txn)
+        return 0;
+
     ret = db_txn->abort(db_txn);
-#else
-    ret = txn_abort(db_txn);
-#endif
+    db_txn = NULL;
+    
     if (ret) {
         LOG(log_error, logtype_cnid, "error aborting transaction: %s", db_strerror(errno));
         return -1;
@@ -473,51 +457,21 @@ int dbif_txn_abort()
 int dbif_txn_checkpoint(u_int32_t kbyte, u_int32_t min, u_int32_t flags)
 {
     int ret;
-#if DB_VERSION_MAJOR >= 4
     ret = db_env->txn_checkpoint(db_env, kbyte, min, flags);
-#else 
-    ret = txn_checkpoint(db_env, kbyte, min, flags);
-#endif
     if (ret) {
         LOG(log_error, logtype_cnid, "error checkpointing transaction susystem: %s", db_strerror(errno));
         return -1;
-    } else 
-        return 0;
-}
-
-#else
-
-int dbif_sync()
-{
-    int i;
-    int ret;
-    int err = 0;
-     
-    for (i = 0; i != /* DBIF_DB_CNT*/ 1; i++) {
-        if ((ret = db_table[i].db->sync(db_table[i].db, 0))) {
-            LOG(log_error, logtype_cnid, "error syncing database %s: %s", db_table[i].name, db_strerror(ret));
-            err++;
-        }
-    }
-    if (err)
-        return -1;
-    else
+    } else
         return 0;
 }
 
-
-int dbif_count(const int dbi, u_int32_t *count) 
+int dbif_count(const int dbi, u_int32_t *count)
 {
     int ret;
     DB_BTREE_STAT *sp;
     DB *db = db_table[dbi].db;
 
-#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
-    ret = db->stat(db, db_txn, &sp, 0);
-#else
-    ret = db->stat(db, &sp, 0);
-#endif
+    ret = db->stat(db, NULL, &sp, 0);
 
     if (ret) {
         LOG(log_error, logtype_cnid, "error getting stat infotmation on database: %s", db_strerror(errno));
@@ -529,5 +483,5 @@ int dbif_count(const int dbi, u_int32_t *count)
 
     return 0;
 }
-#endif /* CNID_BACKEND_DBD_TXN */
+
 
index a8b5998c6a90990b3fa075bafda6cd8c4cd7b4ca..0939ceb971486a10967ed0b9d56dbd839c98a1ad 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbif.h,v 1.2 2005-04-28 20:49:48 bfernhomberg Exp $
+ * $Id: dbif.h,v 1.3 2009-04-21 08:55:44 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -30,14 +30,9 @@ extern int        dbif_del __P((const int, DBT *, u_int32_t));
 
 extern int        dbif_count __P((const int, u_int32_t *));
 
-
-#ifdef CNID_BACKEND_DBD_TXN
 extern int        dbif_txn_begin  __P((void));
 extern int        dbif_txn_commit  __P((void));
 extern int        dbif_txn_abort  __P((void));
 extern int        dbif_txn_checkpoint  __P((u_int32_t, u_int32_t, u_int32_t));
-#else
-extern int        dbif_sync  __P((void));
-#endif /* CNID_BACKEND_DBD_TXN */
 
 #endif
index 6c21d8597aa227f9ed32b71f73fb9ffba500b8eb..d1dde1bbf640bcd0ebd3c1f647c8df71dddb7c18 100644 (file)
@@ -1,10 +1,22 @@
 /*
- * $Id: main.c,v 1.3 2009-03-31 11:40:26 franklahm Exp $
+ * $Id: main.c,v 1.4 2009-04-21 08:55:44 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
+ * Copyright (c) Frank Lahm 2009
  * All Rights Reserved.  See COPYING.
  */
 
+/* 
+   dbd and transactions
+   ====================
+
+   We use AUTO_COMMIT for our BerkeleyDB environment. This avoids explicit transactions
+   for every bdb access which speeds up reads. But in order to be able to rollback
+   in case of errors we start a transaction once we encounter the first write.
+   The logic to do this is stuffed two levels lower into the dbif.c file and functions
+   dbif_put and dbif_del.
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
@@ -83,113 +95,128 @@ static int loop(struct db_param *dbp)
     struct cnid_dbd_rqst rqst;
     struct cnid_dbd_rply rply;
     int ret, cret;
-    time_t now, time_next_flush, time_last_rqst;
     int count;
+    time_t now, time_next_flush, time_last_rqst;
+    char timebuf[64];
     static char namebuf[MAXPATHLEN + 1];
-    u_int32_t checkp_flags;
 
     count = 0;
     now = time(NULL);
     time_next_flush = now + dbp->flush_interval;
     time_last_rqst = now;
-    if (dbp->nosync)
-        checkp_flags = DB_FORCE;
-    else
-        checkp_flags = 0;
 
     rqst.name = namebuf;
 
+    strftime(timebuf, 63, "%b %d %H:%M:%S.",localtime(&time_next_flush));
+    LOG(log_debug, logtype_cnid, "Checkpoint interval: %d seconds. Next checkpoint: %s",
+        dbp->flush_interval, timebuf);
+
     while (1) {
         if ((cret = comm_rcv(&rqst)) < 0)
             return -1;
 
         now = time(NULL);
 
-        if (count > dbp->flush_frequency || now > time_next_flush) {
-#ifdef CNID_BACKEND_DBD_TXN
-            if (dbif_txn_checkpoint(0, 0, checkp_flags) < 0)
-                return -1;
-#else
-            if (dbif_sync() < 0)
-                return -1;
-#endif
-            count = 0;
-            time_next_flush = now + dbp->flush_interval;
-        }
-
         if (cret == 0) {
+            /* comm_rcv returned from select without receiving anything. */
+
+            /* Give signals a chance... */
             block_sigs_onoff(0);
             block_sigs_onoff(1);
             if (exit_sig)
+                /* Received signal (TERM|INT) */
                 return 0;
             if (dbp->idle_timeout && comm_nbe() <= 0 && (now - time_last_rqst) > dbp->idle_timeout)
+                /* Idle timeout */
                 return 0;
-            continue;
-        }
-        /* We got a request */
-        time_last_rqst = now;
-        count++;
+        } else {
+            /* We got a request */
+            time_last_rqst = now;
+
+            memset(&rply, 0, sizeof(rply));
+            switch(rqst.op) {
+                /* ret gets set here */
+            case CNID_DBD_OP_OPEN:
+            case CNID_DBD_OP_CLOSE:
+                /* open/close are noops for now. */
+                rply.namelen = 0;
+                ret = 1;
+                break;
+            case CNID_DBD_OP_ADD:
+                ret = dbd_add(&rqst, &rply);
+                break;
+            case CNID_DBD_OP_GET:
+                ret = dbd_get(&rqst, &rply);
+                break;
+            case CNID_DBD_OP_RESOLVE:
+                ret = dbd_resolve(&rqst, &rply);
+                break;
+            case CNID_DBD_OP_LOOKUP:
+                ret = dbd_lookup(&rqst, &rply);
+                break;
+            case CNID_DBD_OP_UPDATE:
+                ret = dbd_update(&rqst, &rply);
+                break;
+            case CNID_DBD_OP_DELETE:
+                ret = dbd_delete(&rqst, &rply);
+                break;
+            case CNID_DBD_OP_GETSTAMP:
+                ret = dbd_getstamp(&rqst, &rply);
+                break;
+            case CNID_DBD_OP_REBUILD_ADD:
+                ret = dbd_rebuild_add(&rqst, &rply);
+                break;
+            default:
+                LOG(log_error, logtype_cnid, "loop: unknown op %d", rqst.op);
+                ret = -1;
+                break;
+            }
+            
+            if ((cret = comm_snd(&rply)) < 0 || ret < 0) {
+                dbif_txn_abort();
+                return -1;
+            }
+            
+            if (ret == 0 || cret == 0) {
+                if (dbif_txn_abort() < 0)
+                    return -1;
+            } else {
+                ret = dbif_txn_commit();
+                if (  ret < 0)
+                    return -1;
+                else if ( ret > 0 )
+                    /* We had a designated txn because we wrote to the db */
+                    count++;
+            }
+        } /* got a request */
+
+        /*
+          Shall we checkpoint bdb ?
+          "flush_interval" seconds passed ?
+        */
+        if (now > time_next_flush) {
+            LOG(log_info, logtype_cnid, "Checkpointing BerkeleyDB for volume '%s'", dbp->dir);
+            if (dbif_txn_checkpoint(0, 0, 0) < 0)
+                return -1;
+            count = 0;
+            time_next_flush = now + dbp->flush_interval;
 
-#ifdef CNID_BACKEND_DBD_TXN
-        if (dbif_txn_begin() < 0)
-            return -1;
-#endif /* CNID_BACKEND_DBD_TXN */
-
-        memset(&rply, 0, sizeof(rply));
-        switch(rqst.op) {
-            /* ret gets set here */
-        case CNID_DBD_OP_OPEN:
-        case CNID_DBD_OP_CLOSE:
-            /* open/close are noops for now. */
-            rply.namelen = 0;
-            ret = 1;
-            break;
-        case CNID_DBD_OP_ADD:
-            ret = dbd_add(&rqst, &rply);
-            break;
-        case CNID_DBD_OP_GET:
-            ret = dbd_get(&rqst, &rply);
-            break;
-        case CNID_DBD_OP_RESOLVE:
-            ret = dbd_resolve(&rqst, &rply);
-            break;
-        case CNID_DBD_OP_LOOKUP:
-            ret = dbd_lookup(&rqst, &rply);
-            break;
-        case CNID_DBD_OP_UPDATE:
-            ret = dbd_update(&rqst, &rply);
-            break;
-        case CNID_DBD_OP_DELETE:
-            ret = dbd_delete(&rqst, &rply);
-            break;
-        case CNID_DBD_OP_GETSTAMP:
-            ret = dbd_getstamp(&rqst, &rply);
-            break;
-        case CNID_DBD_OP_REBUILD_ADD:
-            ret = dbd_rebuild_add(&rqst, &rply);
-            break;
-        default:
-            LOG(log_error, logtype_cnid, "loop: unknown op %d", rqst.op);
-            ret = -1;
-            break;
+            strftime(timebuf, 63, "%b %d %H:%M:%S.",localtime(&time_next_flush));
+            LOG(log_debug, logtype_cnid, "Checkpoint interval: %d seconds. Next checkpoint: %s",
+                dbp->flush_interval, timebuf);
         }
 
-        if ((cret = comm_snd(&rply)) < 0 || ret < 0) {
-#ifdef CNID_BACKEND_DBD_TXN
-            dbif_txn_abort();
-#endif /* CNID_BACKEND_DBD_TXN */
-            return -1;
-        }
-#ifdef CNID_BACKEND_DBD_TXN
-        if (ret == 0 || cret == 0) {
-            if (dbif_txn_abort() < 0)
-                return -1;
-        } else {
-            if (dbif_txn_commit() < 0)
+        /* 
+           Shall we checkpoint bdb ?
+           Have we commited "count" more changes than "flush_frequency" ?
+        */
+        if (count > dbp->flush_frequency) {
+            LOG(log_info, logtype_cnid, "Checkpointing BerkeleyDB after %d writes for volume '%s'", count, dbp->dir);
+            if (dbif_txn_checkpoint(0, 0, 0) < 0)
                 return -1;
+            count = 0;
         }
-#endif /* CNID_BACKEND_DBD_TXN */
-    }
+    } /* while(1) */
 }
 
 /* ------------------------ */
@@ -283,7 +310,6 @@ int main(int argc, char *argv[])
 {
     struct db_param *dbp;
     int err = 0;
-    int ret;
     int lockfd, ctrlfd, clntfd;
     char *dir, *logconfig;
 
@@ -315,53 +341,25 @@ int main(int argc, char *argv[])
        only shut down after one second of inactivity. */
     block_sigs_onoff(1);
 
-    if ((dbp = db_param_read(dir)) == NULL)
+    if ((dbp = db_param_read(dir, DBD)) == NULL)
         exit(1);
+    LOG(log_maxdebug, logtype_cnid, "Finished parsing db_param config file");
 
     if (dbif_env_init(dbp) < 0)
         exit(2); /* FIXME: same exit code as failure for dbif_open() */
-
-#ifdef CNID_BACKEND_DBD_TXN
-    if (dbif_txn_begin() < 0)
-        exit(6);
-#endif
+    LOG(log_debug, logtype_cnid, "Finished initializing BerkeleyDB environment");
 
     if (dbif_open(dbp, 0) < 0) {
-#ifdef CNID_BACKEND_DBD_TXN
-        dbif_txn_abort();
-#endif
         dbif_close();
         exit(2);
     }
-
-#ifndef CNID_BACKEND_DBD_TXN
-    if (dbp->check && (ret = dbd_check(dir))) {
-        if (ret < 0) {
-            dbif_close();
-            exit(2);
-        }
-        dbif_closedb();
-        LOG(log_info, logtype_cnid, "main: re-opening, secondaries will be rebuilt. This may take some time");
-        if (dbif_open(dbp, 1) < 0) {
-            LOG(log_info, logtype_cnid, "main: re-opening databases failed");
-            dbif_close();
-            exit(2);
-        }
-        LOG(log_info, logtype_cnid, "main: rebuilt done");
-    }
-#endif
+    LOG(log_debug, logtype_cnid, "Finished opening BerkeleyDB databases");
 
     if (dbd_stamp() < 0) {
-#ifdef CNID_BACKEND_DBD_TXN
-        dbif_txn_abort();
-#endif
         dbif_close();
         exit(5);
     }
-#ifdef CNID_BACKEND_DBD_TXN
-    if (dbif_txn_commit() < 0)
-        exit(6);
-#endif
+    LOG(log_maxdebug, logtype_cnid, "Finished checking database stamp");
 
     if (comm_init(dbp, ctrlfd, clntfd) < 0) {
         dbif_close();
@@ -371,13 +369,6 @@ int main(int argc, char *argv[])
     if (loop(dbp) < 0)
         err++;
 
-#ifndef CNID_BACKEND_DBD_TXN
-    /* FIXME: Do we really need to sync before closing the DB? Just closing it
-       should be enough. */
-    if (dbif_sync() < 0)
-        err++;
-#endif
-
     if (dbif_close() < 0)
         err++;
 
index c4c48f545aa2d223371067cdc4d64b4cb37db501..4128c7644ab5d6a2b7303c76087c5d76db2ee192 100644 (file)
 #define ROOTINFO_KEY    "\0\0\0\0"
 #define ROOTINFO_KEYLEN 4
 
-/*                         cnid   - dev        - inode     - type  - did  - name */
-#define ROOTINFO_DATA    "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0RootInfo"
-#define ROOTINFO_DATALEN (3*4 +2*8  +9)
-
-
-
+/* 
+   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)
+   4 bytes: last used cnid (type)
+   4 unused bytes (did)
+   9 bytes name "RootInfo"
+*/
+#define ROOTINFO_DATA    "\0\0\0\0" \
+                         "\0\0\0\0\0\0\0\0" \
+                         "\0\0\0\0\0\0\0\0" \
+                         "\0\0\0\0" \
+                         "\0\0\0\0" \
+                         "RootInfo"
+#define ROOTINFO_DATALEN (3*4 + 2*8 + 9)
 
 struct cnid_dbd_rqst {
     int     op;
index c172ff4986e7e8a94ad7fcad7c2b2a7402fb86a2..9ed3613bc9292b9acea146c532138bd76c75c5f4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cnid_dbd.c,v 1.6 2009-04-01 09:57:38 franklahm Exp $
+ * $Id: cnid_dbd.c,v 1.7 2009-04-21 08:55:44 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -33,8 +33,8 @@
 #include <arpa/inet.h>
 #include <errno.h>
 #include <netdb.h>
-#include <time.h>    
+#include <time.h>
+
 #include <netatalk/endian.h>
 #include <atalk/logger.h>
 #include <atalk/adouble.h>
@@ -46,9 +46,9 @@
 #define SOL_TCP IPPROTO_TCP
 #endif /* ! SOL_TCP */
 
-static void RQST_RESET(struct cnid_dbd_rqst  *r) 
-{ 
-   memset(r, 0, sizeof(struct cnid_dbd_rqst ));
+static void RQST_RESET(struct cnid_dbd_rqst  *r)
+{
+    memset(r, 0, sizeof(struct cnid_dbd_rqst ));
 }
 
 /* ----------- */
@@ -57,11 +57,11 @@ extern int              Cnid_port;
 
 static int tsock_getfd(char *host, int port)
 {
-int sock;
-struct sockaddr_in server;
-struct hostent* hp;
-int attr;
-int err;
+    int sock;
+    struct sockaddr_in server;
+    struct hostent* hp;
+    int attr;
+    int err;
 
     server.sin_family=AF_INET;
     server.sin_port=htons((unsigned short)port);
@@ -69,47 +69,50 @@ int err;
         LOG(log_error, logtype_cnid, "getfd: -cnidserver not defined");
         return -1;
     }
-    
+
     hp=gethostbyname(host);
     if (!hp) {
-       unsigned long int addr=inet_addr(host);
-       LOG(log_warning, logtype_cnid, "getfd: Could not resolve host %s, trying numeric address instead", host);
+        unsigned long int addr=inet_addr(host);
+        LOG(log_warning, logtype_cnid, "getfd: Could not resolve host %s, trying numeric address instead", host);
         if (addr!= (unsigned)-1)
             hp=gethostbyaddr((char*)addr,sizeof(addr),AF_INET);
-       if (!hp) {
-           LOG(log_error, logtype_cnid, "getfd: Could not resolve host %s", host);
-           return(-1);
-       }
+
+        if (!hp) {
+            LOG(log_error, logtype_cnid, "getfd: Could not resolve host %s", host);
+            return(-1);
+        }
     }
     memcpy((char*)&server.sin_addr,(char*)hp->h_addr,sizeof(server.sin_addr));
     sock=socket(PF_INET,SOCK_STREAM,0);
     if (sock==-1) {
-       LOG(log_error, logtype_cnid, "getfd: socket %s: %s", host, strerror(errno));
-       return(-1);
+        LOG(log_error, logtype_cnid, "getfd: socket %s: %s", host, strerror(errno));
+        return(-1);
     }
     attr = 1;
     if (setsockopt(sock, SOL_TCP, TCP_NODELAY, &attr, sizeof(attr)) == -1) {
-       LOG(log_error, logtype_cnid, "getfd: set TCP_NODELAY %s: %s", host, strerror(errno));
-       close(sock);
-       return(-1);
+        LOG(log_error, logtype_cnid, "getfd: set TCP_NODELAY %s: %s", host, strerror(errno));
+        close(sock);
+        return(-1);
     }
     if(connect(sock ,(struct sockaddr*)&server,sizeof(server))==-1) {
         struct timeval tv;
         err = errno;
-       close(sock);
-       sock=-1;
-       LOG(log_error, logtype_cnid, "getfd: connect %s: %s", host, strerror(err));
+        close(sock);
+        sock=-1;
+        LOG(log_error, logtype_cnid, "getfd: connect %s: %s", host, strerror(err));
         switch (err) {
         case ENETUNREACH:
-        case ECONNREFUSED: 
-            
+        case ECONNREFUSED:
+
             tv.tv_usec = 0;
             tv.tv_sec  = 5;
             select(0, NULL, NULL, NULL, &tv);
             break;
         }
     }
+
+    LOG(log_debug7, logtype_cnid, "tsock_getfd: using sockfd %d for cnid server '%s:%d'", sock, host, port);
+
     return(sock);
 }
 
@@ -118,18 +121,20 @@ static int write_vec(int fd, struct iovec *iov, size_t towrite)
 {
     ssize_t len;
     size_t len1;
-    
+
+    LOG(log_maxdebug, logtype_cnid, "write_vec: request to write %d bytes", towrite);
+
     len1 =  iov[1].iov_len;
     while (towrite > 0) {
         if (((len = writev(fd, iov, 2)) == -1 && errno == EINTR) || !len)
             continue;
+
         if ((size_t)len == towrite) /* wrote everything out */
             break;
         else if (len < 0) { /* error */
             return -1;
         }
+
         towrite -= len;
         if (towrite > len1) { /* skip part of header */
             iov[0].iov_base = (char *) iov[0].iov_base + len;
@@ -143,6 +148,9 @@ static int write_vec(int fd, struct iovec *iov, size_t towrite)
             iov[1].iov_len -= len;
         }
     }
+
+    LOG(log_maxdebug, logtype_cnid, "write_vec: wrote %d bytes", towrite);
+
     return 0;
 }
 
@@ -152,8 +160,10 @@ static int init_tsock(CNID_private *db)
     int fd;
     int len;
     struct iovec iov[2];
-    
-    if ((fd = tsock_getfd(Cnid_srv, Cnid_port)) < 0) 
+
+    LOG(log_debug, logtype_cnid, "init_tsock: BEGIN. Opening volume '%s'", db->db_dir);
+
+    if ((fd = tsock_getfd(Cnid_srv, Cnid_port)) < 0)
         return -1;
 
     len = strlen(db->db_dir);
@@ -169,23 +179,27 @@ static int init_tsock(CNID_private *db)
         close(fd);
         return -1;
     }
+
+    LOG(log_debug, logtype_cnid, "init_tsock: ok");
+
     return fd;
 }
 
 /* --------------------- */
-static int send_packet(CNID_private *db, struct cnid_dbd_rqst *rqst, int silent)
+static int send_packet(CNID_private *db, struct cnid_dbd_rqst *rqst)
 {
     struct iovec iov[2];
     size_t towrite;
-  
-    
+
+    LOG(log_maxdebug, logtype_cnid, "send_packet: BEGIN");
+
     if (!rqst->namelen) {
         if (write(db->fd, rqst, sizeof(struct cnid_dbd_rqst)) != sizeof(struct cnid_dbd_rqst)) {
-           if (!silent)
-               LOG(log_warning, logtype_cnid, "send_packet: Error/short write rqst (db_dir %s): %s", 
-                   db->db_dir, strerror(errno));
+            LOG(log_warning, logtype_cnid, "send_packet: Error/short write rqst (db_dir %s): %s",
+                db->db_dir, strerror(errno));
             return -1;
         }
+        LOG(log_maxdebug, logtype_cnid, "send_packet: OK");
         return 0;
     }
 
@@ -198,12 +212,12 @@ static int send_packet(CNID_private *db, struct cnid_dbd_rqst *rqst, int silent)
     towrite = sizeof(struct cnid_dbd_rqst) +rqst->namelen;
 
     if (write_vec(db->fd, iov, towrite) < 0) {
-       if (!silent)
-           LOG(log_warning, logtype_cnid, "send_packet: Error writev rqst (db_dir %s): %s", 
-                     db->db_dir, strerror(errno));
-       return -1;            
+        LOG(log_warning, logtype_cnid, "send_packet: Error writev rqst (db_dir %s): %s",
+            db->db_dir, strerror(errno));
+        return -1;
     }
-
+    
+    LOG(log_maxdebug, logtype_cnid, "send_packet: OK");
     return 0;
 }
 
@@ -230,13 +244,13 @@ static int dbd_reply_stamp(struct cnid_dbd_rply *rply)
     return 0;
 }
 
-/* --------------------- 
+/* ---------------------
  * send a request and get reply
  * assume send is non blocking
  * if no answer after sometime (at least MAX_DELAY secondes) return an error
-*/
+ */
 #define MAX_DELAY 40
-static int dbd_rpc(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int silent)
+static int dbd_rpc(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
 {
     ssize_t ret;
     char *nametmp;
@@ -245,56 +259,55 @@ static int dbd_rpc(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd
     int    maxfd;
     size_t len;
 
-    if (send_packet(db, rqst, silent) < 0) {
+    LOG(log_maxdebug, logtype_cnid, "dbd_rpc: BEGIN");
+
+    if (send_packet(db, rqst) < 0) {
         return -1;
     }
     FD_ZERO(&readfds);
     FD_SET(db->fd, &readfds);
     maxfd = db->fd +1;
-        
+
     tv.tv_usec = 0;
     tv.tv_sec  = MAX_DELAY;
     while ((ret = select(maxfd + 1, &readfds, NULL, NULL, &tv)) < 0 && errno == EINTR);
 
     if (ret < 0) {
-       if (!silent)
-           LOG(log_error, logtype_cnid, "dbd_rpc: Error in select (db_dir %s): %s",
-               db->db_dir, strerror(errno));
+        LOG(log_error, logtype_cnid, "dbd_rpc: Error in select (db_dir %s): %s",
+            db->db_dir, strerror(errno));
         return ret;
     }
     /* signal ? */
     if (!ret) {
         /* no answer */
-       if (!silent)
-           LOG(log_error, logtype_cnid, "dbd_rpc: select timed out (db_dir %s)",
-               db->db_dir);
+        LOG(log_error, logtype_cnid, "dbd_rpc: select timed out (db_dir %s)",
+            db->db_dir);
         return -1;
     }
-
     len = rply->namelen;
     nametmp = rply->name;
-    /* assume that if we have something then everything is there (doesn't sleep) */ 
+    /* assume that if we have something then everything is there (doesn't sleep) */
     if ((ret = read(db->fd, rply, sizeof(struct cnid_dbd_rply))) != sizeof(struct cnid_dbd_rply)) {
-       if (!silent)
-           LOG(log_error, logtype_cnid, "dbd_rpc: Error reading header from fd (db_dir %s): %s",
-                db->db_dir, ret == -1?strerror(errno):"closed");
+        LOG(log_error, logtype_cnid, "dbd_rpc: Error reading header from fd (db_dir %s): %s",
+            db->db_dir, ret == -1?strerror(errno):"closed");
         rply->name = nametmp;
         return -1;
     }
     rply->name = nametmp;
     if (rply->namelen && rply->namelen > len) {
-       if (!silent)
-            LOG(log_error, logtype_cnid, 
-                 "dbd_rpc: Error reading name (db_dir %s): %s name too long wanted %d only %d, garbage?",
-                 db->db_dir, rply->namelen, len);
+        LOG(log_error, logtype_cnid,
+            "dbd_rpc: Error reading name (db_dir %s): %s name too long: %d. only wanted %d, garbage?",
+            db->db_dir, rply->name, rply->namelen, len);
         return -1;
     }
     if (rply->namelen && (ret = read(db->fd, rply->name, rply->namelen)) != (ssize_t)rply->namelen) {
-       if (!silent)
-            LOG(log_error, logtype_cnid, "dbd_rpc: Error reading name from fd (db_dir %s): %s",
-                db->db_dir, ret == -1?strerror(errno):"closed");
+        LOG(log_error, logtype_cnid, "dbd_rpc: Error reading name from fd (db_dir %s): %s",
+            db->db_dir, ret == -1?strerror(errno):"closed");
         return -1;
     }
+
+    LOG(log_maxdebug, logtype_cnid, "dbd_rpc: END");
+
     return 0;
 }
 
@@ -303,75 +316,79 @@ static int transmit(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_db
 {
     struct timeval tv;
     time_t orig, t;
-    int silent = 1;
     int clean = 1; /* no errors so far - to prevent sleep on first try */
-    
+
+    LOG(log_debug7, logtype_cnid, "transmit: BEGIN");
+
     if (db->changed) {
         /* volume and db don't have the same timestamp
-        */
+         */
         return -1;
     }
     time(&orig);
     while (1) {
-
         if (db->fd == -1) {
+            LOG(log_debug, logtype_cnid, "transmit: connecting to cnid_dbd ...");
             struct cnid_dbd_rqst rqst_stamp;
             struct cnid_dbd_rply rply_stamp;
             char  stamp[ADEDLEN_PRIVSYN];
-                
+
             if ((db->fd = init_tsock(db)) < 0) {
                 time(&t);
                 if (t - orig > MAX_DELAY)
                     return -1;
-               continue;
+                continue;
             }
             dbd_initstamp(&rqst_stamp);
             memset(stamp, 0, ADEDLEN_PRIVSYN);
             rply_stamp.name = stamp;
             rply_stamp.namelen = ADEDLEN_PRIVSYN;
 
-            if (dbd_rpc(db, &rqst_stamp, &rply_stamp, silent) < 0)
+            if (dbd_rpc(db, &rqst_stamp, &rply_stamp) < 0)
                 goto transmit_fail;
             if (dbd_reply_stamp(&rply_stamp ) < 0)
                 goto transmit_fail;
-            
+
             if (db->notfirst) {
-               if (memcmp(stamp, db->stamp, ADEDLEN_PRIVSYN)) {
-                    LOG(log_error, logtype_cnid, "transmit: not the same db!");
-                   db->changed = 1;
-                   return -1;
-               }
+                LOG(log_debug7, logtype_cnid, "transmit: reconnected to cnid_dbd, comparing database stamps...");
+                if (memcmp(stamp, db->stamp, ADEDLEN_PRIVSYN)) {
+                    LOG(log_error, logtype_cnid, "transmit: ... not the same db!");
+                    db->changed = 1;
+                    return -1;
+                }
+                LOG(log_debug7, logtype_cnid, "transmit: ... OK.");
             }
             else {
                 db->notfirst = 1;
-                if (db->client_stamp) {
-                   memcpy(db->client_stamp, stamp, ADEDLEN_PRIVSYN);
-               }
-               memcpy(db->stamp, stamp, ADEDLEN_PRIVSYN);
+                if (db->client_stamp)
+                    memcpy(db->client_stamp, stamp, ADEDLEN_PRIVSYN);
+                memcpy(db->stamp, stamp, ADEDLEN_PRIVSYN);
             }
+            LOG(log_debug, logtype_cnid, "transmit: succesfully attached to cnid_dbd for volume '%s' with stamp '%08lx'.", 
+                db->db_dir, *(uint64_t *)stamp);
         }
-        if (!dbd_rpc(db, rqst, rply, silent)) {
+        if (!dbd_rpc(db, rqst, rply)) {
+            LOG(log_debug7, logtype_cnid, "transmit: END OK");
             return 0;
-       }
-transmit_fail:
-       silent = 0; /* From now on dbd_rpc and subroutines called from there
-                       will log messages if something goes wrong again */
+        }
+    transmit_fail:
+        LOG(log_error, logtype_cnid, "transmit: something went wrong");
         if (db->fd != -1) {
             close(db->fd);
             db->fd = -1; /* FD not valid... will need to reconnect */
         }
         time(&t);
         if (t - orig > MAX_DELAY) {
-           LOG(log_error, logtype_cnid, "transmit: Request to dbd daemon (db_dir %s) timed out.", db->db_dir);
+            LOG(log_error, logtype_cnid, "transmit: Request to dbd daemon (db_dir %s) timed out.", db->db_dir);
             return -1;
-       }
+        }
 
-       if (!clean) { /* don't sleep if just got disconnected by cnid server */
+        if (!clean) { /* don't sleep if just got disconnected by cnid server */
             /* sleep a little before retry */
             tv.tv_usec = 0;
             tv.tv_sec  = 5;
             select(0, NULL, NULL, NULL, &tv); /* sleep for 5 seconds */
-       } else {
+        } else {
             clean = 0; /* false... next time sleep */
         }
     }
@@ -382,17 +399,17 @@ transmit_fail:
 static struct _cnid_db *cnid_dbd_new(const char *volpath)
 {
     struct _cnid_db *cdb;
-    
+
     if ((cdb = (struct _cnid_db *)calloc(1, sizeof(struct _cnid_db))) == NULL)
-       return NULL;
-       
+        return NULL;
+
     if ((cdb->volpath = strdup(volpath)) == NULL) {
         free(cdb);
-       return NULL;
+        return NULL;
     }
-    
+
     cdb->flags = CNID_FLAG_PERSISTENT | CNID_FLAG_LAZY_INIT;
-    
+
     cdb->cnid_add = cnid_dbd_add;
     cdb->cnid_delete = cnid_dbd_delete;
     cdb->cnid_get = cnid_dbd_get;
@@ -403,7 +420,7 @@ static struct _cnid_db *cnid_dbd_new(const char *volpath)
     cdb->cnid_update = cnid_dbd_update;
     cdb->cnid_rebuild_add = cnid_dbd_rebuild_add;
     cdb->cnid_close = cnid_dbd_close;
-    
+
     return cdb;
 }
 
@@ -414,19 +431,19 @@ struct _cnid_db *cnid_dbd_open(const char *dir, mode_t mask _U_)
     struct _cnid_db *cdb = NULL;
 
     if (!dir) {
-         return NULL;
+        return NULL;
     }
-    
+
     if ((cdb = cnid_dbd_new(dir)) == NULL) {
         LOG(log_error, logtype_cnid, "cnid_open: Unable to allocate memory for database");
-       return NULL;
+        return NULL;
     }
-        
+
     if ((db = (CNID_private *)calloc(1, sizeof(CNID_private))) == NULL) {
         LOG(log_error, logtype_cnid, "cnid_open: Unable to allocate memory for database");
         goto cnid_dbd_open_fail;
     }
-    
+
     cdb->_private = db;
 
     /* We keep a copy of the directory in the db structure so that we can
@@ -434,21 +451,21 @@ struct _cnid_db *cnid_dbd_open(const char *dir, mode_t mask _U_)
     strcpy(db->db_dir, dir);
     db->magic = CNID_DB_MAGIC;
     db->fd = -1;
-#ifdef DEBUG
-    LOG(log_info, logtype_cnid, "opening database connection to %s", db->db_dir); 
-#endif
+
+    LOG(log_debug, logtype_cnid, "cnid_dbd_open: Finished initializing cnid dbd module for volume '%s'", db->db_dir);
+
     return cdb;
 
 cnid_dbd_open_fail:
     if (cdb != NULL) {
-       if (cdb->volpath != NULL) {
-           free(cdb->volpath);
-       }
-       free(cdb);
+        if (cdb->volpath != NULL) {
+            free(cdb->volpath);
+        }
+        free(cdb);
     }
     if (db != NULL)
-       free(db);
-       
+        free(db);
+
     return NULL;
 }
 
@@ -459,28 +476,27 @@ void cnid_dbd_close(struct _cnid_db *cdb)
 
     if (!cdb) {
         LOG(log_error, logtype_cnid, "cnid_close called with NULL argument !");
-       return;
+        return;
     }
 
     if ((db = cdb->_private) != NULL) {
-#ifdef DEBUG 
-        LOG(log_info, logtype_cnid, "closing database connection to %s", db->db_dir);
-#endif  
-       if (db->fd >= 0)
-           close(db->fd);
+        LOG(log_info, logtype_cnid, "closing database connection for volume '%s'", db->db_dir);
+
+        if (db->fd >= 0)
+            close(db->fd);
         free(db);
     }
-    
+
     free(cdb->volpath);
     free(cdb);
-    
+
     return;
 }
 
 /* ---------------------- */
 cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st,
-                const cnid_t did, char *name, const size_t len,
-                cnid_t hint _U_)
+                    const cnid_t did, char *name, const size_t len,
+                    cnid_t hint _U_)
 {
     CNID_private *db;
     struct cnid_dbd_rqst rqst;
@@ -512,15 +528,19 @@ cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st,
     rqst.name = name;
     rqst.namelen = len;
 
+    LOG(log_debug, logtype_cnid, "cnid_dbd_add: CNID: %u, name: '%s', inode: 0x%llx, type: %d (0=file, 1=dir)",
+        ntohl(did), name, (long long)st->st_ino, rqst.type);
+
     rply.namelen = 0;
     if (transmit(db, &rqst, &rply) < 0) {
         errno = CNID_ERR_DB;
         return CNID_INVALID;
     }
-    
+
     switch(rply.result) {
     case CNID_DBD_RES_OK:
         id = rply.cnid;
+        LOG(log_debug, logtype_cnid, "cnid_dbd_add: got CNID: %u", ntohl(id));
         break;
     case CNID_DBD_RES_ERR_MAX:
         errno = CNID_ERR_MAX;
@@ -534,6 +554,7 @@ cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st,
     default:
         abort();
     }
+
     return id;
 }
 
@@ -545,19 +566,20 @@ cnid_t cnid_dbd_get(struct _cnid_db *cdb, const cnid_t did, char *name, const si
     struct cnid_dbd_rply rply;
     cnid_t id;
 
-
     if (!cdb || !(db = cdb->_private) || !name) {
-        LOG(log_error, logtype_cnid, "cnid_get: Parameter error");
-        errno = CNID_ERR_PARAM;        
+        LOG(log_error, logtype_cnid, "cnid_dbd_get: Parameter error");
+        errno = CNID_ERR_PARAM;
         return CNID_INVALID;
     }
 
     if (len > MAXPATHLEN) {
-        LOG(log_error, logtype_cnid, "cnid_add: Path name is too long");
+        LOG(log_error, logtype_cnid, "cnid_dbd_get: Path name is too long");
         errno = CNID_ERR_PATH;
         return CNID_INVALID;
     }
 
+    LOG(log_debug, logtype_cnid, "cnid_dbd_get: DID: %u, name: '%s'", ntohl(did), name);
+
     RQST_RESET(&rqst);
     rqst.op = CNID_DBD_OP_GET;
     rqst.did = did;
@@ -569,10 +591,11 @@ cnid_t cnid_dbd_get(struct _cnid_db *cdb, const cnid_t did, char *name, const si
         errno = CNID_ERR_DB;
         return CNID_INVALID;
     }
-    
+
     switch(rply.result) {
     case CNID_DBD_RES_OK:
         id = rply.cnid;
+        LOG(log_debug, logtype_cnid, "cnid_dbd_get: got CNID: %u", ntohl(id));
         break;
     case CNID_DBD_RES_NOTFOUND:
         id = CNID_INVALID;
@@ -581,7 +604,7 @@ cnid_t cnid_dbd_get(struct _cnid_db *cdb, const cnid_t did, char *name, const si
         id = CNID_INVALID;
         errno = CNID_ERR_DB;
         break;
-    default: 
+    default:
         abort();
     }
 
@@ -598,10 +621,12 @@ char *cnid_dbd_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t le
 
     if (!cdb || !(db = cdb->_private) || !id || !(*id)) {
         LOG(log_error, logtype_cnid, "cnid_resolve: Parameter error");
-        errno = CNID_ERR_PARAM;                
+        errno = CNID_ERR_PARAM;
         return NULL;
     }
 
+    LOG(log_debug, logtype_cnid, "cnid_dbd_resolve: resolving CNID: %u", ntohl(*id));
+
     /* TODO: We should maybe also check len. At the moment we rely on the caller
        to provide a buffer that is large enough for MAXPATHLEN plus
        CNID_HEADER_LEN plus 1 byte, which is large enough for the maximum that
@@ -627,6 +652,7 @@ char *cnid_dbd_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t le
     case CNID_DBD_RES_OK:
         *id = rply.did;
         name = rply.name;
+        LOG(log_debug, logtype_cnid, "cnid_dbd_resolve: resolved CNID: %u to '%s'", ntohl(*id), name);
         break;
     case CNID_DBD_RES_NOTFOUND:
         *id = CNID_INVALID;
@@ -651,7 +677,7 @@ int cnid_dbd_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len)
 
     if (!cdb || !(db = cdb->_private) || len != ADEDLEN_PRIVSYN) {
         LOG(log_error, logtype_cnid, "cnid_getstamp: Parameter error");
-        errno = CNID_ERR_PARAM;                
+        errno = CNID_ERR_PARAM;
         return -1;
     }
     db->client_stamp = buffer;
@@ -662,7 +688,7 @@ int cnid_dbd_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len)
 
 /* ---------------------- */
 cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did,
-                   char *name, const size_t len)
+                       char *name, const size_t len)
 {
     CNID_private *db;
     struct cnid_dbd_rqst rqst;
@@ -671,7 +697,7 @@ cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t
 
     if (!cdb || !(db = cdb->_private) || !st || !name) {
         LOG(log_error, logtype_cnid, "cnid_lookup: Parameter error");
-        errno = CNID_ERR_PARAM;        
+        errno = CNID_ERR_PARAM;
         return CNID_INVALID;
     }
 
@@ -694,6 +720,9 @@ cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t
     rqst.name = name;
     rqst.namelen = len;
 
+    LOG(log_debug, logtype_cnid, "cnid_dbd_lookup: CNID: %u, name: '%s', inode: 0x%llx, type: %d (0=file, 1=dir)",
+        ntohl(did), name, (long long)st->st_ino, rqst.type);
+
     rply.namelen = 0;
     if (transmit(db, &rqst, &rply) < 0) {
         errno = CNID_ERR_DB;
@@ -703,6 +732,7 @@ cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t
     switch (rply.result) {
     case CNID_DBD_RES_OK:
         id = rply.cnid;
+        LOG(log_debug, logtype_cnid, "cnid_dbd_lookup: got CNID: %u", ntohl(id));
         break;
     case CNID_DBD_RES_NOTFOUND:
         id = CNID_INVALID;
@@ -720,16 +750,15 @@ cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t
 
 /* ---------------------- */
 int cnid_dbd_update(struct _cnid_db *cdb, const cnid_t id, const struct stat *st,
-                const cnid_t did, char *name, const size_t len)
+                    const cnid_t did, char *name, const size_t len)
 {
     CNID_private *db;
     struct cnid_dbd_rqst rqst;
     struct cnid_dbd_rply rply;
 
-    
     if (!cdb || !(db = cdb->_private) || !id || !st || !name) {
         LOG(log_error, logtype_cnid, "cnid_update: Parameter error");
-        errno = CNID_ERR_PARAM;        
+        errno = CNID_ERR_PARAM;
         return -1;
     }
 
@@ -751,6 +780,9 @@ int cnid_dbd_update(struct _cnid_db *cdb, const cnid_t id, const struct stat *st
     rqst.name = name;
     rqst.namelen = len;
 
+    LOG(log_debug, logtype_cnid, "cnid_dbd_update: CNID: %u, name: '%s', inode: 0x%llx, type: %d (0=file, 1=dir)",
+        ntohl(id), name, (long long)st->st_ino, rqst.type);
+
     rply.namelen = 0;
     if (transmit(db, &rqst, &rply) < 0) {
         errno = CNID_ERR_DB;
@@ -759,6 +791,7 @@ int cnid_dbd_update(struct _cnid_db *cdb, const cnid_t id, const struct stat *st
 
     switch (rply.result) {
     case CNID_DBD_RES_OK:
+        LOG(log_debug, logtype_cnid, "cnid_dbd_update: updated");
     case CNID_DBD_RES_NOTFOUND:
         return 0;
     case CNID_DBD_RES_ERR_DB:
@@ -770,15 +803,15 @@ int cnid_dbd_update(struct _cnid_db *cdb, const cnid_t id, const struct stat *st
 }
 
 /* ---------------------- */
-cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st, 
-                           const cnid_t did, char *name, const size_t len, 
-                           cnid_t hint)
+cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st,
+                            const cnid_t did, char *name, const size_t len,
+                            cnid_t hint)
 {
     CNID_private *db;
     struct cnid_dbd_rqst rqst;
     struct cnid_dbd_rply rply;
     cnid_t id;
-    
+
     if (!cdb || !(db = cdb->_private) || !st || !name || hint == CNID_INVALID) {
         LOG(log_error, logtype_cnid, "cnid_rebuild_add: Parameter error");
         errno = CNID_ERR_PARAM;
@@ -805,6 +838,9 @@ cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st,
     rqst.namelen = len;
     rqst.cnid = hint;
 
+    LOG(log_debug, logtype_cnid, "cnid_dbd_rebuild_add: CNID: %u, name: '%s', inode: 0x%llx, type: %d (0=file, 1=dir), hint: %u",
+        ntohl(did), name, (long long)st->st_ino, rqst.type, hint);
+
     if (transmit(db, &rqst, &rply) < 0) {
         errno = CNID_ERR_DB;
         return CNID_INVALID;
@@ -813,6 +849,7 @@ cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st,
     switch(rply.result) {
     case CNID_DBD_RES_OK:
         id = rply.cnid;
+        LOG(log_debug, logtype_cnid, "cnid_dbd_rebuild_add: got CNID: %u", ntohl(id));
         break;
     case CNID_DBD_RES_ERR_MAX:
         errno = CNID_ERR_MAX;
@@ -830,19 +867,20 @@ cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st,
 }
 
 /* ---------------------- */
-int cnid_dbd_delete(struct _cnid_db *cdb, const cnid_t id) 
+int cnid_dbd_delete(struct _cnid_db *cdb, const cnid_t id)
 {
     CNID_private *db;
     struct cnid_dbd_rqst rqst;
     struct cnid_dbd_rply rply;
 
-
     if (!cdb || !(db = cdb->_private) || !id) {
         LOG(log_error, logtype_cnid, "cnid_delete: Parameter error");
-        errno = CNID_ERR_PARAM;        
+        errno = CNID_ERR_PARAM;
         return -1;
     }
 
+    LOG(log_debug, logtype_cnid, "cnid_dbd_delete: delete CNID: %u", ntohl(id));
+
     RQST_RESET(&rqst);
     rqst.op = CNID_DBD_OP_DELETE;
     rqst.cnid = id;
@@ -855,6 +893,7 @@ int cnid_dbd_delete(struct _cnid_db *cdb, const cnid_t id)
 
     switch (rply.result) {
     case CNID_DBD_RES_OK:
+        LOG(log_debug, logtype_cnid, "cnid_dbd_delete: deleted CNID: %u", ntohl(id));
     case CNID_DBD_RES_NOTFOUND:
         return 0;
     case CNID_DBD_RES_ERR_DB:
index a304b24ce4bbdcf5ee6e7b500f08bbc8d57a6df0..e05ba8d0d83c202e2772b27e22821e9dc58ea711 100644 (file)
@@ -13,7 +13,7 @@ AC_DEFUN([AC_NETATALK_CNID], [
         else
             use_cdb_backend=yes
         fi
-    ],[use_cdb_backend=yes]
+    ],[use_cdb_backend=no]
     )
 
     if test $use_cdb_backend = yes; then
@@ -43,31 +43,6 @@ AC_DEFUN([AC_NETATALK_CNID], [
         AC_MSG_RESULT([yes])
     ])
 
-    dnl Determine whether or not to use with transaction support in Database Daemon
-    AC_MSG_CHECKING([whether or not to use Database Daemon with transaction support])
-    AC_ARG_WITH(cnid-dbd-txn,
-    [  --with-cnid-dbd-txn           build transaction support for dbd backend],
-    [   if test x"$withval" = x"no"; then
-            AC_MSG_RESULT([no])
-            use_dbd_txn=no
-        else
-            use_dbd_txn=yes
-            AC_MSG_RESULT([yes])
-        fi
-       ],[
-        use_dbd_txn=no
-        AC_MSG_RESULT([no])
-    ])
-
-    if test $use_dbd_txn = yes; then
-        use_dbd_backend=yes
-        AC_DEFINE(CNID_BACKEND_DBD_TXN, 1, [Define if CNID Database Daemon backend has transaction support])
-    else
-        if test x"$use_dbd_backend" = x; then    
-            use_dbd_backend=no
-        fi
-    fi
-
     if test $use_dbd_backend = yes; then
         compiled_backends="$compiled_backends dbd"
         AC_DEFINE(CNID_BACKEND_DBD, 1, [Define if CNID Database Daemon backend should be compiled.])
index 73c10b37a4287558b12ffd79b0cbac784459594e..e2160d9fc9b1bb75604f33b6863852f0a836cea0 100644 (file)
@@ -1,4 +1,4 @@
-dnl $Id: db3-check.m4,v 1.17 2009-03-25 15:53:03 franklahm Exp $
+dnl $Id: db3-check.m4,v 1.18 2009-04-21 08:55:44 franklahm Exp $
 dnl Autoconf macros to check for the Berkeley DB library
 
 dnl -- check header for minimum version and return version in
@@ -70,11 +70,11 @@ AC_DEFUN([AC_PATH_BDB],[
     trybdbdir=""
     dobdbsearch=yes
     bdb_search_dirs="/usr/local /usr"
-    search_subdirs="/ /db4.7 /db47 /db4.6 /db46 /db4.5 /db45 /db4.4 /db44 /db4.3 /db43 /db4.2 /db42 /db4.1 /db41 /db4"
+    search_subdirs="/ /db4.7 /db47 /db4.6 /db46 /db4.5 /db45 /db4.4 /db44 /db4"
 
-    dnl required BDB version
+    dnl required BDB version: 4.4, because of DB_AUTO_COMMIT
     DB_MAJOR_REQ=4
-    DB_MINOR_REQ=1
+    DB_MINOR_REQ=4
     DB_PATCH_REQ=0
 
     dnl make sure atalk_libname is defined beforehand