]> arthur.barton.de Git - netatalk.git/commitdiff
Refine CNID salvatio strategies
authorfranklahm <franklahm>
Wed, 25 Nov 2009 14:59:15 +0000 (14:59 +0000)
committerfranklahm <franklahm>
Wed, 25 Nov 2009 14:59:15 +0000 (14:59 +0000)
etc/cnid_dbd/Makefile.am
etc/cnid_dbd/README
etc/cnid_dbd/cmd_dbd.c
etc/cnid_dbd/cmd_dbd.h
etc/cnid_dbd/cmd_dbd_lookup.c [deleted file]
etc/cnid_dbd/cmd_dbd_scanvol.c
etc/cnid_dbd/dbd.h
etc/cnid_dbd/dbd_add.c
etc/cnid_dbd/dbd_lookup.c
etc/cnid_dbd/dbif.c
etc/cnid_dbd/main.c

index d3af2bbb87c669bcc6a4aa43ebada00040843950..a8866351810149eb56e564705c596ea418b44529 100644 (file)
@@ -16,7 +16,7 @@ cnid_dbd_LDADD = $(top_builddir)/libatalk/libatalk.la @BDB_LIBS@
 cnid_metad_SOURCES = cnid_metad.c usockfd.c db_param.c
 cnid_metad_LDADD = $(top_builddir)/libatalk/libatalk.la
 
-dbd_SOURCES = cmd_dbd.c cmd_dbd_scanvol.c cmd_dbd_lookup.c \
+dbd_SOURCES = cmd_dbd.c cmd_dbd_scanvol.c \
                          dbif.c pack.c \
                          dbd_delete.c dbd_update.c dbd_add.c dbd_lookup.c \
                          dbd_rebuild_add.c dbd_getstamp.c
index 7255a9e2745e53040f65bac8d637c92e8926ff08..cbd2f9f5a07b76ba4de429e0e34a45f685fe1ee7 100644 (file)
@@ -68,85 +68,12 @@ other instances of afpd that access the volume. You can safely kill it
 with SIGTERM, it will be restarted automatically by cnid_metad as soon
 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 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
-supporting files should therefore be writeable by that user/group. cnid_dbd
-reads configuration information from the file db_param in the database
-directory on startup. If the file does not exist, suitable default
-values for all parameters are used. The format for a single parameter
-is the parameter name, followed by one or more spaces, followed by the
-parameter value, followed by a newline. The following parameters are
-currently recognized:
-
-Name               Default
-====               =======
-cachesize          8192
-flush_frequency    100
-flush_interval     1800
-usock_file         <databasedirectory>/usock
-fd_table_size      128
-idle_timeout       600
-
-"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
-performance. The db_stat utility with the "-m" option that comes with
-Berkely DB can help you determine wether you need to change this
-value. The default is pretty conservative so that a large percentage
-of requests should be satisfied from the cache directly. If memory is
-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.
-
-"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.
-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
-have to use another value if the total length of the default pathname
-exceeds the limits for unix domain socket files on your system,
-usually this is something like 100 bytes.
-
-"fd_table_size" is the maximum number of connections (filedescriptors)
-that can be open for afpd client processes in cnid_dbd. If this number
-is exceeded, one of the existing connections is closed and reused. The
-affected afpd process will transparently reconnect later, which causes
-slight overhead. On the other hand, setting this parameter too high
-could affect performance in cnid_dbd since all descriptors have to be
-checked in a select() system call, or worse, you might exceed the per
-process limit of open file descriptors on your system. It is safe to
-set the value to 1 on volumes where only one afpd client process
-is expected to run, e.g. home directories.
-
-"idle_timeout" is the number of seconds of inactivity before an idle
-cnid_dbd exits. Set this to 0 to disable the timeout.
+supporting files should therefore be writeable by that user/group.
 
 Current shortcomings:
 
-- The implementation for cnid_dbd doubles code from libatalk/cnid,
-making it more difficult to keep changes to the library interface and
-the semantics of database requests in sync.  If cnid_dbd takes over
-the world, this problem will eventually disappear, otherwise it should
-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.
-
-- mmap for IPC would be nice as an alternative.
-
 - The parameter file parsing of db_param is very simpleminded. It is
 easy to cause buffer overruns and the like.
 Also, there is no support for blanks (or weird characters) in
index 59b7df6a2cedff5dd7b614a340b2f860479f14d0..e9f9c031b96a66772e5a14b6b86133d1813f819a 100644 (file)
@@ -1,5 +1,5 @@
 /* 
-   $Id: cmd_dbd.c,v 1.14 2009-11-24 14:48:07 franklahm Exp $
+   $Id: cmd_dbd.c,v 1.15 2009-11-25 14:59:15 franklahm Exp $
 
    Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
    
@@ -266,9 +266,8 @@ static void usage (void)
            "   -x rebuild indexes (just for completeness, mostly useless!)\n"
            "   -v verbose\n\n"
            "WARNING:\n"
-           "If you want/need to run an -r -f rebuild after adding 'cachecnid' to a volume configuration,\n"
-           "you must run a rebuild with -r alone at first in order to sync all existing CNIDs from the db\n"
-           "to the AppleDouble files!\n"
+           "For -r -f restore of the CNID database from the adouble files, the CNID must of course\n"
+           "be synched to them files first with a plain -r rebuild !\n"
         );
 }
 
index 2d061a7aeb4e6de7c400aa1a9c74b8a1ca1dfb2e..e2364054e645cca40be76e49665b18483593331b 100644 (file)
@@ -34,6 +34,5 @@ extern int cmd_dbd_scanvol(DBD *dbd, struct volinfo *volinfo, dbd_flags_t flags)
   Functions for querying the database which couldn't be reused from the existing
   funcs pool of dbd_* for one reason or another
 */
-extern int cmd_dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int roflag);
 extern int cmd_dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply);
 #endif /* CMD_DBD_H */
diff --git a/etc/cnid_dbd/cmd_dbd_lookup.c b/etc/cnid_dbd/cmd_dbd_lookup.c
deleted file mode 100644 (file)
index 93866e2..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * $Id: cmd_dbd_lookup.c,v 1.3 2009-10-14 01:38:28 didg Exp $
- *
- * Copyright (C) Frank Lahm 2009
- * All Rights Reserved.  See COPYING.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/param.h>
-#include <errno.h>
-#include <netatalk/endian.h>
-#include <atalk/logger.h>
-#include <atalk/cnid_dbd_private.h>
-
-#include "pack.h"
-#include "dbif.h"
-#include "dbd.h"
-#include "cmd_dbd.h"
-
-/* 
-   ATTENTION:
-   whatever you change here, also change cmd_dbd_lookup.c !
-   cmd_dbd_lookup has an read-only mode, but besides that it's the same.
- */
-
-
-/*
- *  This returns the CNID corresponding to a particular file and logs any inconsitencies.
- *  If roflags == 1 we only scan, if roflag == 0, we modify i.e. call dbd_update
- *  FIXME: realign this wih dbd_lookup.
- */
-
-int cmd_dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int roflag)
-{
-    unsigned char *buf;
-    DBT key, devdata, diddata;
-    uint64_t dev = 0;
-    int devino = 1, didname = 1; 
-    int rc;
-    cnid_t id_devino, id_didname;
-    u_int32_t type_devino  = (unsigned)-1;
-    u_int32_t type_didname = (unsigned)-1;
-    int update = 0;
-    
-    memset(&key, 0, sizeof(key));
-    memset(&diddata, 0, sizeof(diddata));
-    memset(&devdata, 0, sizeof(devdata));
-
-    rply->namelen = 0; 
-    rply->cnid = 0;
-    
-    buf = pack_cnid_data(rqst); 
-
-    /* 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.size = CNID_DEVINO_LEN;
-
-    if ((rc = dbif_get(dbd, DBIF_IDX_DEVINO, &key, &devdata, 0))  < 0) {
-        dbd_log( LOGSTD, "dbd_search: Unable to get CNID %u, name %s",
-                ntohl(rqst->did), rqst->name);
-        rply->result = CNID_DBD_RES_ERR_DB;
-        return -1;
-    }
-    if (rc == 0) {
-        devino = 0;
-    }
-    else {
-        memcpy(&id_devino, devdata.data, sizeof(rply->cnid));
-        memcpy(&type_devino, (char *)devdata.data +CNID_TYPE_OFS, sizeof(type_devino));
-        type_devino = ntohl(type_devino);
-    }
-
-    key.data = buf + CNID_DID_OFS;
-    key.size = CNID_DID_LEN + rqst->namelen + 1;
-
-    if ((rc = dbif_get(dbd, DBIF_IDX_DIDNAME, &key, &diddata, 0))  < 0) {
-        dbd_log( LOGSTD, "dbd_search: Unable to get CNID %u, name %s",
-                ntohl(rqst->did), rqst->name);
-        rply->result = CNID_DBD_RES_ERR_DB;
-        return -1;
-    }
-    if (rc == 0) {
-        didname = 0;
-    }
-    else {
-        memcpy(&id_didname, diddata.data, sizeof(rply->cnid));
-        memcpy(&type_didname, (char *)diddata.data +CNID_TYPE_OFS, sizeof(type_didname));
-        type_didname = ntohl(type_didname);
-    }
-    
-    if (!devino && !didname) {  
-        /* not found */
-        dbd_log( LOGDEBUG, "name: '%s/%s', did: %u, dev/ino: 0x%llx/0x%llx is not in the CNID database", 
-                 cwdbuf, rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
-        rply->result = CNID_DBD_RES_NOTFOUND;
-        return 1;
-    }
-
-    if (devino && didname && id_devino == id_didname && type_devino == rqst->type) {
-        /* the same */
-        rply->cnid = id_didname;
-        rply->result = CNID_DBD_RES_OK;
-        return 1;
-    }
-
-    /* 
-       Order matters for the next 2 ifs because both found a CNID but they didn't match.
-       So in order to pick the CNID from "didname" it must come after devino.
-       See test cases laid out in dbd_lookup.c.
-    */
-    if (devino) {
-        dbd_log( LOGSTD, "CNID resolve problem: server side rename oder reused inode for '%s/%s'", cwdbuf, rqst->name);
-        rqst->cnid = id_devino;
-        if (type_devino != rqst->type) {
-            /* same dev/inode but not same type: it's an inode reused, delete the record */
-            if (! roflag)
-                if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
-                    return -1;
-        }
-        else {
-            update = 1;
-        }
-    }
-    if (didname) {
-        dbd_log( LOGSTD, "CNID resolve problem: changed dev/ino for '%s/%s'", cwdbuf, rqst->name);
-        rqst->cnid = id_didname;
-        /* we have a did/name.
-           If it's the same dev or not the same type, e.g. a remove followed by a new file
-           with the same name */
-        if (!memcmp(&dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) ||
-            type_didname != rqst->type) {
-            if (! roflag)
-                if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
-                    return -1;
-        }
-        else {
-            update = 1;
-        }
-    }
-
-    if (!update || roflag) {
-        rply->result = CNID_DBD_RES_NOTFOUND;
-        return 1;
-    }
-    /* Fix up the database. assume it was a file move and rename */
-    rc = dbd_update(dbd, rqst, rply);
-    if (rc >0) {
-        rply->cnid = rqst->cnid;
-    }
-
-    dbd_log( LOGSTD, "CNID database needed update: dev/ino: 0x%llx/0x%llx, did: %u, name: '%s/%s' --> CNID: %u", 
-             (unsigned long long)rqst->dev, (unsigned long long)rqst->ino,
-             ntohl(rqst->did), cwdbuf, rqst->name, ntohl(rply->cnid));
-
-    return rc;
-}
-
-/* 
-   This is taken from dbd_add.c, but this func really is only "add", dbd_add calls dbd_lookup
-   before adding.
-   FIXME: realign with dbd_add using e.g. using a new arg like "int lookup".
-*/
-int cmd_dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
-{
-    if (get_cnid(dbd, rply) < 0) {
-        if (rply->result == CNID_DBD_RES_ERR_MAX) {
-            dbd_log( LOGSTD, "FATAL: CNID database has reached its limit.");
-            /* This will cause an abort/rollback if transactions are used */
-            return 0;
-        } else {
-            dbd_log( LOGSTD, "Failed to compute CNID for %s, error reading/updating Rootkey", rqst->name);
-            return -1;
-        }
-    }
-    
-    if (add_cnid(dbd, rqst, rply) < 0) {
-        if (rply->result == CNID_DBD_RES_ERR_DUPLCNID) {
-            dbd_log( LOGSTD, "Cannot add CNID %u. Corrupt/invalid Rootkey?.", ntohl(rply->cnid));
-            /* abort/rollback, see above */
-            return 0;
-        } else {
-            dbd_log( LOGSTD, "Failed to add CNID for %s to database", rqst->name);
-            return -1;
-        }
-    }
-    dbd_log( LOGDEBUG, "Add to CNID database: did: %u, cnid: %u, name: '%s', dev/ino: 0x%llx/0x%llx",
-             ntohl(rqst->did), ntohl(rply->cnid), rqst->name,
-             (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
-
-    rply->result = CNID_DBD_RES_OK;
-    return 1;
-}
index 1d6d6a920287f112e51a84e72a147d3464392776..0893d0ae19839aa30526b2452ae1c11aac2fb134 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  $Id: cmd_dbd_scanvol.c,v 1.10 2009-10-14 01:38:28 didg Exp $
+  $Id: cmd_dbd_scanvol.c,v 1.11 2009-11-25 14:59:15 franklahm Exp $
 
   Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
 
@@ -443,7 +443,7 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi
     rqst.namelen = strlen(name);
 
     /* Query the database */
-    ret = cmd_dbd_lookup(dbd, &rqst, &rply, (dbd_flags & DBD_FLAGS_SCAN) ? 1 : 0);
+    ret = dbd_lookup(dbd, &rqst, &rply, (dbd_flags & DBD_FLAGS_SCAN) ? 1 : 0);
     dbif_txn_close(dbd, ret);
     if (rply.result == CNID_DBD_RES_OK) {
         db_cnid = rply.cnid;
@@ -492,7 +492,7 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi
         /* Note: the next test will use this new CNID too! */
         if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
             /* add to db */
-            ret = cmd_dbd_add(dbd, &rqst, &rply);
+            ret = dbd_add(dbd, &rqst, &rply, 1);
             dbif_txn_close(dbd, ret);
             db_cnid = rply.cnid;
             dbd_log( LOGSTD, "New CNID for '%s/%s': %u", cwdbuf, name, ntohl(db_cnid));
index cca91c6ef271594e1e21a3632176860f50e37f36..0dbff51dba97a4ac133c6ab20469470031c54987 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd.h,v 1.6 2009-10-14 01:38:28 didg Exp $
+ * $Id: dbd.h,v 1.7 2009-11-25 14:59:15 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * Copyright (C) Frank Lahm 2009
@@ -15,10 +15,10 @@ extern int add_cnid(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *
 extern int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply);
 
 extern int dbd_stamp(DBD *dbd);
-extern int dbd_add(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
+extern int dbd_add(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *, int nolookup);
+extern int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *, int roflag);
 extern int dbd_get(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
 extern int dbd_resolve(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
-extern int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
 extern int dbd_update(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
 extern int dbd_delete(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *, int idx);
 extern int dbd_getstamp(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
index 7f66ca30b387b0d9a101bd5f0e480487482f95b4..22fa61192692264886694c876d578979c9133728 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd_add.c,v 1.6 2009-05-14 13:46:08 franklahm Exp $
+ * $Id: dbd_add.c,v 1.7 2009-11-25 14:59:15 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -159,18 +159,21 @@ int dbd_stamp(DBD *dbd)
 }
 
 /* ------------------------ */
-int dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
+/* We need a nolookup version for `dbd` */
+int dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int nolookup)
 {
     rply->namelen = 0;
 
     /* See if we have an entry already and return it if yes */
-    if (dbd_lookup(dbd, rqst, rply) < 0)
-        return -1;
+    if (! nolookup) {
+        if (dbd_lookup(dbd, rqst, rply, 0) < 0)
+            return -1;
 
-    if (rply->result == CNID_DBD_RES_OK) {
-        /* Found it. rply->cnid is the correct CNID now. */
-        LOG(log_debug, logtype_cnid, "dbd_add: dbd_lookup success, cnid %u", ntohl(rply->cnid));
-        return 1;
+        if (rply->result == CNID_DBD_RES_OK) {
+            /* Found it. rply->cnid is the correct CNID now. */
+            LOG(log_debug, logtype_cnid, "dbd_add: dbd_lookup success --> CNID: %u", ntohl(rply->cnid));
+            return 1;
+        }
     }
 
     if (get_cnid(dbd, rply) < 0) {
@@ -186,7 +189,8 @@ int dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     
     if (add_cnid(dbd, rqst, rply) < 0) {
         if (rply->result == CNID_DBD_RES_ERR_DUPLCNID) {
-            LOG(log_error, logtype_cnid, "dbd_add: Cannot add CNID %u. Corrupt/invalid Rootkey?.", ntohl(rply->cnid));
+            LOG(log_error, logtype_cnid, "dbd_add(DID: %u/\"%s\", dev/ino 0x%llx/0x%llx): Cannot add CNID: %u",
+                ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rply->cnid));
             /* abort/rollback, see above */
             return 0;
         } else {
@@ -194,9 +198,8 @@ int dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
             return -1;
         }
     }
-    LOG(log_debug, logtype_cnid, "dbd_add: Added dev/ino 0x%llx/0x%llx did %u name %s cnid %u",
-        (unsigned long long)rqst->dev, (unsigned long long)rqst->ino,
-        ntohl(rqst->did), rqst->name, ntohl(rply->cnid));
+    LOG(log_debug, logtype_cnid, "dbd_add(DID: %u/\"%s\", dev/ino 0x%llx/0x%llx): Added with CNID: %u",
+        ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rply->cnid));
 
     rply->result = CNID_DBD_RES_OK;
     return 1;
index f70ed4f9291a38a4833c95bfebbac82860256616..45119da8fcdd97e020bd77228bfe3162e3473fa6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd_lookup.c,v 1.10 2009-11-24 12:01:04 franklahm Exp $
+ * $Id: dbd_lookup.c,v 1.11 2009-11-25 14:59:15 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * Copyright (C) Frank Lahm 2009
@@ -7,12 +7,11 @@
  */
 
 /* 
-   ATTENTION:
-   whatever you change here, also change cmd_dbd_lookup.c !
-   cmd_dbd_lookup has an read-only mode but besides that it's the same.
-*/
+CNID salvation spec:
+general rule: better safe then sorry, so we always delete CNIDs and assing
+new ones in case of a lookup mismatch.
+
 
-/* 
 The lines...
 
 Id  Did T   Dev Inode   Name
@@ -21,41 +20,48 @@ a   b   c   d   e       name1
 -->
 f   g   h   i   h       name2
 
-...are the expected results of certain operations.
+...are the expected results of certain operations. (f) is the speced CNID, in some
+cases it's only intermediate as described in the text and is overridden by another
+spec.
 
+1) UNIX rename (via mv) or inode reusage(!)
+-------------------------------------------
+Name is possibly changed (rename case) but inode is the same.
+We should try to keep the CNID, but we cant, because inode reusage is probably
+much to frequent.
 
-1) UNIX rename (mv)
--------------------
-Name is changed but inode stays the same. We should try to keep the CNID.
+rename:
+15  2   f   1   1       file
+-->
+15  x   f   1   1       renamedfile
 
+inode reusage:
 15  2   f   1   1       file
 -->
-15  2   f   1   1       movedfile
+16  y   f   1   1       inodereusagefile
 
 Result in dbd_lookup (-: not found, +: found):
-- devino
-+ didname
++ devino
+- didname
 
 Possible solution:
-Update.
+None. Delete old data, file gets new CNID in both cases (rename and inode).
 
-
-2) UNIX copy (cp)
------------------
-Changed inode and name. Result is just a new file which will get a fresh CNID.
-Unfortunately the old one gets orphaned.
+2) UNIX mv from one folder to another
+----------------------------------------
+Name is unchanged and inode stays the same, but DID is different.
+We should try to keep the CNID.
 
 15  2   f   1   1       file
 -->
-16  2   f   1   2       copyfile
+15  x   f   1   1       file
 
 Result in dbd_lookup:
-- devino
++ devino
 - didname
 
-Possible fixup solution:
-Not possible. Only dbd -re can delete the orphaned CNID 15
-
+Possible solution:
+strcmp names, if they match keep CNID.
 
 3) Restore from backup
 ----------------------
@@ -70,31 +76,34 @@ Result in dbd_lookup:
 Possible fixup solution:
 Update.
 
-
-4) inode reusage eg. UNIX emacs
--------------------------------
-This one is tough:
+4) emacs
+--------
 emacs uses a backup file (file~). When saving because of inode reusage of the fs,
-both files exchange inodes. There's probably no appropiate solution for all
-scenarios where this might occur eg. for the emacs case it would be good to
-preserve the CNIDs while probably in the general case we should assign new CNIDs
-to both files:
+both files exchange inodes.
 
-General case:
+General case for inode reusage:
 15  2   f   1   1       file
 -->
 16  2   f   1   1       new_file_with_reused_inode
 
+Result in dbd_lookup:
++ devino
+- didname
+
 Emacs case:
 15  2   f   1   1       file
 16  2   f   1   2       file~
--->
-??  2   f   1   2       file
-??  2   f   1   1       file~
+--> this would be nice:
+15  2   f   1   2       file
+16  2   f   1   1       file~
+--> but because we must follow the general case you get this:
+17  2   f   1   2       file
+18  2   f   1   1       file~
 
-Result in dbd_lookup:
-+ devino
-+ didname
+Result in dbd_lookup for the emacs case:
++ devino --> CNID: 16
++ didname -> CNID: 15
+devino search and didname search result in different CNIDs !!
 
 Possible fixup solution:
 to be safe we must implement the general case, sorry emacs.
@@ -122,11 +131,10 @@ to be safe we must implement the general case, sorry emacs.
  *  up the database if there's a problem.
  */
 
-int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
+int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int roflag)
 {
     unsigned char *buf;
     DBT key, devdata, diddata;
-    char dev[CNID_DEV_LEN];
     int devino = 1, didname = 1; 
     int rc;
     cnid_t id_devino, id_didname;
@@ -134,7 +142,6 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     u_int32_t type_didname = (unsigned)-1;
     int update = 0;
     
-    
     memset(&key, 0, sizeof(key));
     memset(&diddata, 0, sizeof(diddata));
     memset(&devdata, 0, sizeof(devdata));
@@ -143,7 +150,6 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     rply->cnid = 0;
     
     buf = pack_cnid_data(rqst); 
-    memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN);
 
     /* 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. */
@@ -152,7 +158,7 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
 
     if ((rc = dbif_get(dbd, DBIF_IDX_DEVINO, &key, &devdata, 0))  < 0) {
         LOG(log_error, logtype_cnid, "dbd_lookup: Unable to get CNID %u, name %s",
-                ntohl(rqst->did), rqst->name);
+            ntohl(rqst->did), rqst->name);
         rply->result = CNID_DBD_RES_ERR_DB;
         return -1;
     }
@@ -170,7 +176,7 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
 
     if ((rc = dbif_get(dbd, DBIF_IDX_DIDNAME, &key, &diddata, 0))  < 0) {
         LOG(log_error, logtype_cnid, "dbd_lookup: Unable to get CNID %u, name %s",
-                ntohl(rqst->did), rqst->name);
+            ntohl(rqst->did), rqst->name);
         rply->result = CNID_DBD_RES_ERR_DB;
         return -1;
     }
@@ -182,77 +188,102 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
         memcpy(&type_didname, (char *)diddata.data +CNID_TYPE_OFS, sizeof(type_didname));
         type_didname = ntohl(type_didname);
     }
-    
-    if (!devino && !didname) {  
-        /* not found */
-
-        LOG(log_debug, logtype_cnid, "cnid_lookup: dev/ino 0x%llx/0x%llx did %u name %s neither in devino nor didname", 
-            (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rqst->did), rqst->name);
 
+    /* Have we found anything at all ? */
+    if (!devino && !didname) {  
+        /* nothing found */
+        LOG(log_debug, logtype_cnid, "dbd_lookup: name: '%s', did: %u, dev/ino: 0x%llx/0x%llx is not in the CNID database", 
+            rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
         rply->result = CNID_DBD_RES_NOTFOUND;
         return 1;
     }
 
-    if (devino && didname && id_devino == id_didname && type_devino == rqst->type) {
-        /* the same */
-
-        LOG(log_debug, logtype_cnid, "cnid_lookup: Looked up dev/ino 0x%llx/0x%llx did %u name %s as %u", 
-            (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rqst->did), rqst->name, ntohl(id_didname));
+    /* Check for type (file/dir) mismatch */
+    if (devino && (type_devino != rqst->type)) {
+        /* one is a dir one is a file, remove from db */
+        rqst->cnid = id_devino;
+        if (! roflag)
+            if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+                return -1;
+        rply->result = CNID_DBD_RES_NOTFOUND;
+        return 1;
+    } else if (didname && (type_didname != rqst->type)) {
+        /* same: one is a dir one is a file, remove from db */
+        rqst->cnid = id_didname;
+        if (! roflag)
+            if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+                return -1;
+        rply->result = CNID_DBD_RES_NOTFOUND;
+        return 1;
+    }
 
+    if (devino && didname && id_devino == id_didname) {
+        /* everything is fine */
+        LOG(log_debug, logtype_cnid, "dbd_lookup(DID:%u/'%s',0x%llx/0x%llx): Got CNID: %u",
+            ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, htonl(id_didname));
         rply->cnid = id_didname;
         rply->result = CNID_DBD_RES_OK;
         return 1;
     }
-    
-    /* 
-       Order matters for the next 2 ifs because both found a CNID but they do not match.
-       So in order to pick the CNID from "didname" it must come after devino.
-       See test cases laid out in dbd_lookup.c.
-    */
-    if (devino) {
-        LOG(log_maxdebug, logtype_cnid, "CNID resolve problem: server side rename oder reused inode for '%s'", rqst->name);
-        rqst->cnid = id_devino;
-        if (type_devino != rqst->type) {
-            /* same dev:inode but not same type one is a folder the other 
-             * is a file,it's an inode reused, delete the record
-            */
-            if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0) {
+
+    if (devino && didname && id_devino != id_didname) {
+        /* CNIDs don't match, something of a worst case! */
+        LOG(log_debug, logtype_cnid, "dbd_lookup: CNID mismatch: (DID:%u/'%s') --> %u , (0x%llx/0x%llx) --> %u",
+            ntohl(rqst->did), rqst->name, ntohl(id_didname),
+            (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(id_devino));
+
+        /* Something like 5), the emacs case (see above), remove it all */
+        if (! roflag) {
+            rqst->cnid = id_devino;
+            if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+                return -1;
+
+            rqst->cnid = id_didname;
+            if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
                 return -1;
-            }
         }
-        else {
+        rply->result = CNID_DBD_RES_NOTFOUND;
+        return 1;
+    }
+
+    if ( ! didname) {
+        LOG(log_debug, logtype_cnid, "dbd_lookup(DID:%u/'%s',0x%llx/0x%llx): CNID resolve problem: server side rename oder reused inode",
+            ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
+        rqst->cnid = id_devino;
+        /* Case 2) ? */
+        if (strcmp(rqst->name, (char *)devdata.data + CNID_NAME_OFS) == 0) {
+            LOG(log_debug, logtype_cnid, "dbd_lookup: server side mv from one dir to another");
             update = 1;
+        } else {
+            if ( ! roflag)
+                if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+                    return -1;
+            rply->result = CNID_DBD_RES_NOTFOUND;
+            return 1;
         }
     }
-    if (didname) {
-        LOG(log_maxdebug, logtype_cnid, "CNID resolve problem: changed dev/ino for '%s'", rqst->name);
+
+    if ( ! devino) {
+        LOG(log_debug, logtype_cnid, "dbd_lookup(DID:%u/'%s',0x%llx/0x%llx): CNID resolve problem: changed dev/ino",
+            ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
         rqst->cnid = id_didname;
-        /* we have a did:name 
-         * if it's the same dev or not the same type
-         * just delete it
-        */
-        if (!memcmp(dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) ||
-                   type_didname != rqst->type) {
-            if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0) {
-                return -1;
-            }
-        }
-        else {
-            update = 1;
-        }
+        update = 1;
     }
-    if (!update) {
+
+    /* This is also a catch all if we've forgot to catch some possibility with the preceding ifs*/
+    if (!update || roflag) {
         rply->result = CNID_DBD_RES_NOTFOUND;
         return 1;
     }
-    /* Fix up the database. assume it was a file move and rename */
+
+    /* Fix up the database */
     rc = dbd_update(dbd, rqst, rply);
     if (rc >0) {
         rply->cnid = rqst->cnid;
     }
 
-    LOG(log_debug, logtype_cnid, "cnid_lookup: Looked up dev/ino 0x%llx/0x%llx did %u name %s as %u (needed update)", 
-        (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rqst->did), rqst->name, ntohl(rply->cnid));
+    LOG(log_debug, logtype_cnid, "dbd_lookup(DID:%u/'%s',0x%llx/0x%llx): Got CNID (needed update): %u", 
+        ntohl(rqst->did), rqst->name, (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rply->cnid));
 
     return rc;
 }
index cb155c03a3b8c190307274d964d4780eabf700f6..0fdbb9ff56d1128f10bf69e9a4a15422acfa8fc9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbif.c,v 1.16 2009-10-14 01:38:28 didg Exp $
+ * $Id: dbif.c,v 1.17 2009-11-25 14:59:15 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * Copyright (C) Frank Lahm 2009
@@ -299,7 +299,7 @@ int dbif_open(DBD *dbd, struct db_param *dbp _U_, int reindex)
         }
         
         if ((stat(dbd->db_filename, &st)) == 0) {
-            LOG(log_debug, logtype_cnid, "See if we can upgrade the CNID database");
+            LOG(log_debug, logtype_cnid, "See if we can upgrade the CNID database...");
             if ((ret = db_create(&upgrade_db, dbd->db_env, 0))) {
                 LOG(log_error, logtype_cnid, "error creating handle for database: %s", db_strerror(ret));
                 return -1;
@@ -316,6 +316,7 @@ int dbif_open(DBD *dbd, struct db_param *dbp _U_, int reindex)
                 LOG(log_error, logtype_cnid, "error forcing checkpoint: %s", db_strerror(ret));
                 return -1;
             }
+            LOG(log_debug, logtype_cnid, "Finished CNID database upgrade check");
         }
         
         if ((fchdir(cwd)) != 0) {
index febadc1a7cae04d7c1daeae7299e7f300616ffe5..42cf28489f14e61c055a73a73eb9a75a74742347 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: main.c,v 1.15 2009-10-19 08:09:07 didg Exp $
+ * $Id: main.c,v 1.16 2009-11-25 14:59:15 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * Copyright (c) Frank Lahm 2009
@@ -153,7 +153,7 @@ static int loop(struct db_param *dbp)
                 ret = 1;
                 break;
             case CNID_DBD_OP_ADD:
-                ret = dbd_add(dbd, &rqst, &rply);
+                ret = dbd_add(dbd, &rqst, &rply, 0);
                 break;
             case CNID_DBD_OP_GET:
                 ret = dbd_get(dbd, &rqst, &rply);
@@ -162,7 +162,7 @@ static int loop(struct db_param *dbp)
                 ret = dbd_resolve(dbd, &rqst, &rply);
                 break;
             case CNID_DBD_OP_LOOKUP:
-                ret = dbd_lookup(dbd, &rqst, &rply);
+                ret = dbd_lookup(dbd, &rqst, &rply, 0);
                 break;
             case CNID_DBD_OP_UPDATE:
                 ret = dbd_update(dbd, &rqst, &rply);