]> arthur.barton.de Git - netatalk.git/commitdiff
Fixes a serious error in the way recovery was run on db_env opening.
authorfranklahm <franklahm>
Wed, 6 May 2009 11:54:24 +0000 (11:54 +0000)
committerfranklahm <franklahm>
Wed, 6 May 2009 11:54:24 +0000 (11:54 +0000)
dbd -s and -r now are capable of:
   St Type Check (Status of implementation progress, type: file/dir)
   OK D    Make sure .AppleDouble dir exist, create if missing
   OK F    Make sure ad file exists
   OK F/D  Delete orphaned ad-files, log dirs in ad-dir
   OK F/D  Check name encoding by roundtripping, log on error
dbd -d now also dumps the rootinfo key.

19 files changed:
etc/cnid_dbd/Makefile.am
etc/cnid_dbd/cmd_dbd.h [new file with mode: 0644]
etc/cnid_dbd/cmd_dbd_scanvol.c [new file with mode: 0644]
etc/cnid_dbd/db_param.c
etc/cnid_dbd/db_param.h
etc/cnid_dbd/dbd.c
etc/cnid_dbd/dbd.h
etc/cnid_dbd/dbd_add.c
etc/cnid_dbd/dbd_dbcheck.c
etc/cnid_dbd/dbd_delete.c
etc/cnid_dbd/dbd_get.c
etc/cnid_dbd/dbd_getstamp.c
etc/cnid_dbd/dbd_lookup.c
etc/cnid_dbd/dbd_rebuild_add.c
etc/cnid_dbd/dbd_resolve.c
etc/cnid_dbd/dbd_update.c
etc/cnid_dbd/dbif.c
etc/cnid_dbd/dbif.h
etc/cnid_dbd/main.c

index fbde4afbe738e00e0e5989b25a46c08996a9fe08..e5e237cb61fe5f03914e04521f11f87a69edd68a 100644 (file)
@@ -16,11 +16,11 @@ 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 = dbd.c dbif.c pack.c
+dbd_SOURCES = dbd.c dbif.c pack.c cmd_dbd_scanvol.c
 dbd_CFLAGS = $(AM_CFLAGS)
 dbd_LDADD = $(top_builddir)/libatalk/libatalk.la @BDB_LIBS@
 
-noinst_HEADERS = dbif.h pack.h db_param.h dbd.h usockfd.h comm.h
+noinst_HEADERS = dbif.h pack.h db_param.h dbd.h usockfd.h comm.h cmd_dbd.h
 
 EXTRA_DIST = README
 
diff --git a/etc/cnid_dbd/cmd_dbd.h b/etc/cnid_dbd/cmd_dbd.h
new file mode 100644 (file)
index 0000000..70006fd
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef CMD_DBD_H
+#define CMD_DBD_H
+
+#include <atalk/volinfo.h>
+#include "dbif.h"
+
+enum logtype {LOGSTD, LOGDEBUG};
+typedef unsigned int dbd_flags_t;
+
+#define DBD_FLAGS_SCAN     (1 << 0)
+#define DBD_FLAGS_FORCE    (1 << 0)
+
+#define ADv2_DIRNAME ".AppleDouble"
+
+#define DIR_DOT_OR_DOTDOT(a) \
+        ((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0))
+
+#define STRCMP(a,b,c) \
+        (strcmp(a,c) b 0)
+
+extern void dbd_log(enum logtype lt, char *fmt, ...);
+extern int cmd_dbd_scanvol(DBD *dbd, struct volinfo *volinfo, dbd_flags_t flags);
+
+#endif /* CMD_DBD_H */
diff --git a/etc/cnid_dbd/cmd_dbd_scanvol.c b/etc/cnid_dbd/cmd_dbd_scanvol.c
new file mode 100644 (file)
index 0000000..07993ed
--- /dev/null
@@ -0,0 +1,523 @@
+/* 
+   $Id: cmd_dbd_scanvol.c,v 1.1 2009-05-06 11:54:24 franklahm Exp $
+
+   Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+*/
+
+/* 
+   dbd specs and implementation progress
+   =====================================
+
+   St Type Check (Status of implementation progress, type: file/dir)
+   -- ---- -----
+   OK D    Make sure .AppleDouble dir exist, create if missing. Error creating
+           it is fatal as that shouldn't happen as root
+   OK F    Make sure ad file exists
+   OK F/D  Delete orphaned ad-files, log dirs in ad-dir
+   OK F/D  Check name encoding by roundtripping, log on error
+   .. F/D  try: read CNID from ad file (if cnid caching is on)
+           try: fetch CNID from database
+           on mismatch: keep CNID from file, update database
+           on no CNID id ad file: write CNID from database to ad file
+           on no CNID in database: add CNID from ad file to database
+           on no CNID at all: create one and store in both places
+*/
+
+/* FIXME: set id */
+#if 0
+        ad_setid( &ad, s_path->st.st_dev, s_path->st.st_ino, dir->d_did, did, vol->v_stamp);
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include <atalk/adouble.h>
+#include <atalk/unicode.h>
+#include <atalk/volinfo.h>
+#include "cmd_dbd.h" 
+#include "dbif.h"
+#include "db_param.h"
+
+static DBD            *dbd_rebuild;
+static struct volinfo *volinfo;
+static dbd_flags_t    dbd_flags;
+static char           cwdbuf[MAXPATHLEN+1];
+static char           *netatalk_dirs[] = {
+    ".AppleDB",
+    ".AppleDesktop",
+    NULL
+};
+
+/* 
+   Taken form afpd/desktop.c
+*/
+static char *utompath(char *upath)
+{
+    static char  mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
+    char         *m, *u;
+    uint16_t     flags = CONV_IGNORE | CONV_UNESCAPEHEX;
+    size_t       outlen;
+
+    if (!upath)
+        return NULL;
+
+    m = mpath;
+    u = upath;
+    outlen = strlen(upath);
+
+    if ((volinfo->v_casefold & AFPVOL_UTOMUPPER))
+        flags |= CONV_TOUPPER;
+    else if ((volinfo->v_casefold & AFPVOL_UTOMLOWER))
+        flags |= CONV_TOLOWER;
+
+    if ((volinfo->v_flags & AFPVOL_EILSEQ)) {
+        flags |= CONV__EILSEQ;
+    }
+
+    /* convert charsets */
+    if ((size_t)-1 == ( outlen = convert_charset(volinfo->v_volcharset,
+                                                 CH_UTF8_MAC, 
+                                                 volinfo->v_maccharset,
+                                                 u, outlen, mpath, MAXPATHLEN, &flags)) ) { 
+        dbd_log( LOGSTD, "Conversion from %s to %s for %s failed.",
+                 volinfo->v_volcodepage, volinfo->v_maccodepage, u);
+        return NULL;
+    }
+
+    return(m);
+}
+
+/* 
+   Taken form afpd/desktop.c
+*/
+static char *mtoupath(char *mpath)
+{
+    static char  upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
+    char       *m, *u;
+    size_t       inplen;
+    size_t       outlen;
+    u_int16_t   flags = 0;
+
+    if (!mpath)
+        return NULL;
+        
+    if ( *mpath == '\0' ) {
+        return( "." );
+    }
+
+    /* set conversion flags */
+    if (!(volinfo->v_flags & AFPVOL_NOHEX))
+        flags |= CONV_ESCAPEHEX;
+    if (!(volinfo->v_flags & AFPVOL_USEDOTS))
+        flags |= CONV_ESCAPEDOTS;
+
+    if ((volinfo->v_casefold & AFPVOL_MTOUUPPER))
+        flags |= CONV_TOUPPER;
+    else if ((volinfo->v_casefold & AFPVOL_MTOULOWER))
+        flags |= CONV_TOLOWER;
+
+    if ((volinfo->v_flags & AFPVOL_EILSEQ)) {
+        flags |= CONV__EILSEQ;
+    }
+
+    m = mpath;
+    u = upath;
+
+    inplen = strlen(m);
+    outlen = MAXPATHLEN;
+
+    if ((size_t)-1 == (outlen = convert_charset(CH_UTF8_MAC,
+                                                volinfo->v_volcharset,
+                                                volinfo->v_maccharset,
+                                                m, inplen, u, outlen, &flags)) ) {
+        dbd_log( LOGSTD, "conversion from UTF8-MAC to %s for %s failed.",
+                 volinfo->v_volcodepage, mpath);
+           return NULL;
+    }
+
+    return( upath );
+}
+
+/* 
+   Check for wrong encoding e.g. "." at the beginning is not CAP encoded (:2e) although volume is default !AFPVOL_USEDOTS.
+   We do it by roundtripiping from volcharset to UTF8-MAC and back and then compare the result.
+*/
+static int check_name_encoding(char *uname)
+{
+    char *roundtripped;
+
+    roundtripped = mtoupath(utompath(uname));
+    if (!roundtripped) {
+        dbd_log( LOGSTD, "Error checking encoding for %s/%s", cwdbuf, uname);
+        return -1;
+    }
+
+    if ( STRCMP(uname, !=, roundtripped)) {
+        dbd_log( LOGSTD, "Bad encoding for %s/%s", cwdbuf, uname);
+        return -1;
+    }
+
+    return 0;
+}
+
+/*
+  Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop"
+  Returns pointer to name or NULL.
+*/
+static const char *check_netatalk_dirs(const char *name)
+{
+    int c;
+    
+    for (c=0; netatalk_dirs[c]; c++) {
+        if ((strcmp(name, netatalk_dirs[c])) == 0)
+            return netatalk_dirs[c];
+    }
+    return NULL;
+}
+
+/* 
+   Check for .AppleDouble file, create if missing
+*/
+static int check_adfile(const char *fname, const struct stat *st)
+{
+    int ret;
+    struct adouble ad;
+    char *adname;
+
+    adname = volinfo->ad_path(fname, 0);
+
+    if ((ret = access( adname, F_OK)) != 0) {
+        if (errno != ENOENT) {
+            dbd_log(LOGSTD, "Access error for ad-file '%s/%s': %s",
+                    cwdbuf, adname, strerror(errno));
+            return -1;
+        }
+        /* Missing. Log and create it */
+        dbd_log(LOGSTD, "Missing AppleDoube file '%s/%s'", cwdbuf, adname);
+
+        if (dbd_flags & DBD_FLAGS_SCAN)
+            /* Scan only requested, dont change anything */
+            return 0;
+
+        /* Create ad file */
+        ad_init(&ad, volinfo->v_adouble, volinfo->v_flags);
+        
+        if ((ret = ad_open_metadata( fname, 0, O_CREAT, &ad)) != 0) {
+            dbd_log( LOGSTD, "Error creating AppleDouble file '%s/%s': %s", 
+                     cwdbuf, adname, strerror(errno));
+            return -1;
+        }
+
+        /* Set name in ad-file */
+        ad_setname(&ad, utompath((char *)fname));
+        ad_flush(&ad);
+        ad_close_metadata(&ad);
+
+        chown(adname, st->st_uid, st->st_gid);
+        /* FIXME: should we inherit mode too here ? */
+#if 0
+        chmod(adname, st->st_mode);
+#endif
+    }
+    return 0;
+}
+
+/* 
+   Check for .AppleDouble folder, create if missing
+*/
+static int check_addir(int volroot)
+{
+    int ret;
+    struct stat st;
+    struct adouble ad;
+
+    if ((ret = access(ADv2_DIRNAME, F_OK)) != 0) {
+        if (errno != ENOENT) {
+            dbd_log(LOGSTD, "Access error in directory %s: %s", cwdbuf, strerror(errno));
+            return -1;
+        }
+        /* Missing. Log and create it */
+        dbd_log(LOGSTD, "Missing %s directory %s", ADv2_DIRNAME, cwdbuf);
+
+        if (dbd_flags & DBD_FLAGS_SCAN)
+            /* Scan only requested, dont change anything */
+            return 0;
+
+        /* Create ad dir and set name and id */
+        ad_init(&ad, volinfo->v_adouble, volinfo->v_flags);
+        
+        if ((ret = ad_open_metadata( ".", ADFLAGS_DIR, O_CREAT, &ad)) != 0) {
+            dbd_log( LOGSTD, "Error creating AppleDouble dir in %s: %s", cwdbuf, strerror(errno));
+            return -1;
+        }
+
+        /* Get basename of cwd from cwdbuf */
+        char *mname = utompath(strrchr(cwdbuf, '/') + 1);
+
+        /* Update name in ad file */
+        ad_setname(&ad, mname);
+        ad_flush(&ad);
+        ad_close_metadata(&ad);
+        
+        /* Inherit owner/group from "." to ".AppleDouble" and ".Parent" */
+        if ((stat(".", &st)) != 0) {
+            dbd_log( LOGSTD, "Couldnt stat %s: %s", cwdbuf, strerror(errno));
+            return -1;
+        }
+        chown(ADv2_DIRNAME, st.st_uid, st.st_gid);
+        chown(volinfo->ad_path(".", ADFLAGS_DIR), st.st_uid, st.st_gid);
+    }
+
+    return 0;
+}
+
+static int read_addir(void)
+{
+    DIR *dp;
+    struct dirent *ep;
+    struct stat st;
+    static char fname[NAME_MAX] = "../";
+
+    if ((chdir(ADv2_DIRNAME)) != 0) {
+        dbd_log(LOGSTD, "Couldn't chdir to '%s/%s': %s",
+                cwdbuf, ADv2_DIRNAME, strerror(errno));
+        return -1;
+    }
+
+    if ((dp = opendir(".")) == NULL) {
+        dbd_log(LOGSTD, "Couldn't open the directory '%s/%s': %s",
+                cwdbuf, ADv2_DIRNAME, strerror(errno));
+        return -1;
+    }
+
+    while ((ep = readdir(dp))) {
+        /* Check if its "." or ".." */
+        if (DIR_DOT_OR_DOTDOT(ep->d_name))
+            continue;
+
+        if ((stat(ep->d_name, &st)) < 0) {
+            dbd_log( LOGSTD, "Lost file while reading dir '%s/%s/%s', probably removed: %s",
+                     cwdbuf, ADv2_DIRNAME, ep->d_name, strerror(errno));
+            continue;
+        }
+
+        /* Check for dirs */
+        if (S_ISDIR(st.st_mode)) {
+            dbd_log( LOGSTD, "Unexpected directory '%s' in AppleDouble dir '%s/%s'",
+                     ep->d_name, cwdbuf, ADv2_DIRNAME);
+            continue;
+        }
+
+        /* Skip ".Parent" */
+        if (STRCMP(ep->d_name, ==, ".Parent"))
+            continue;
+
+        /* Check for data file */
+        strcpy(fname+3, ep->d_name);
+        if ((access( fname, F_OK)) != 0) {
+            if (errno != ENOENT) {
+                dbd_log(LOGSTD, "Access error for file '%s/%s': %s", 
+                        cwdbuf, ep->d_name, strerror(errno));
+                continue;
+            }
+            /* Orphaned ad-file*/
+            dbd_log(LOGSTD, "Orphaned AppleDoube file '%s/%s/%s'",
+                    cwdbuf, ADv2_DIRNAME, ep->d_name);
+
+            if (dbd_flags & DBD_FLAGS_SCAN)
+                /* Scan only requested, dont change anything */
+                continue;;
+
+            if ((unlink(ep->d_name)) != 0) {
+                dbd_log(LOGSTD, "Error unlinking orphaned AppleDoube file '%s/%s/%s'",
+                        cwdbuf, ADv2_DIRNAME, ep->d_name);
+
+            }
+        }
+    }
+
+    if ((chdir("..")) != 0) {
+        dbd_log(LOGSTD, "Couldn't chdir back to '%s' from AppleDouble dir: %s",
+                cwdbuf, strerror(errno));
+        /* This really is EOT! */
+        exit(1);
+    }
+
+    closedir(dp);
+
+    return 0;
+}
+
+static int dbd_readdir(int volroot, cnid_t did)
+{
+    int cwd, ret = 0, encoding_ok;
+    const char *name;
+    DIR *dp;
+    struct dirent *ep;
+    static struct stat st;      /* Save some stack space */
+
+    /* Check for .AppleDouble folder */
+    if ((check_addir(volroot)) != 0)
+        return -1;
+
+    /* Check AppleDouble files in AppleDouble folder */
+    if ((ret = read_addir()) != 0)
+        return -1;
+
+    if ((dp = opendir (".")) == NULL) {
+        dbd_log(LOGSTD, "Couldn't open the directory: %s",strerror(errno));
+        return -1;
+    }
+
+    while ((ep = readdir (dp))) {
+        /* Check if its "." or ".." */
+        if (DIR_DOT_OR_DOTDOT(ep->d_name))
+            continue;
+
+        /* Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" */
+        if ((name = check_netatalk_dirs(ep->d_name)) != NULL) {
+            if (! volroot)
+                dbd_log(LOGSTD, "Nested %s in %s", name, cwdbuf);
+            continue;
+        }
+
+        /* Skip .AppleDouble dir in this loop */
+        if (STRCMP(ep->d_name, == , ADv2_DIRNAME))
+            continue;
+
+        if ((ret = stat(ep->d_name, &st)) < 0) {
+            dbd_log( LOGSTD, "Lost file while reading dir '%s/%s', probably removed: %s", cwdbuf, ep->d_name, strerror(errno));
+            continue;
+        }
+
+        /**************************************************************************
+           Tests
+        **************************************************************************/
+
+        /* Check encoding */
+        if ( -1 == (encoding_ok = check_name_encoding(ep->d_name)) ) {
+            /* If its a file: skipp all other tests now ! */
+            /* For dirs we skip tests too, but later */
+            if (S_ISREG(st.st_mode))
+                continue;
+        }
+
+        /* Check for appledouble file, create if missing */
+        if (S_ISREG(st.st_mode)) {
+            if ( 0 != check_adfile(ep->d_name, &st))
+                continue;
+        }
+        
+        /**************************************************************************
+          Recursion
+        **************************************************************************/
+        if (S_ISDIR(st.st_mode)) {
+            strcat(cwdbuf, "/");
+            strcat(cwdbuf, ep->d_name);
+            dbd_log( LOGDEBUG, "Entering directory: %s", cwdbuf);
+            if (-1 == (cwd = open(".", O_RDONLY))) {
+                dbd_log( LOGSTD, "Cant open directory '%s': %s", cwdbuf, strerror(errno));
+                continue;
+            }
+            if (0 != chdir(ep->d_name)) {
+                dbd_log( LOGSTD, "Cant chdir to directory '%s': %s", cwdbuf, strerror(errno));
+                close(cwd);
+                continue;
+            }
+
+            ret = dbd_readdir(0, did);
+
+            fchdir(cwd);
+            close(cwd);
+            *(strrchr(cwdbuf, '/')) = 0;
+            if (ret < 0)
+                continue;
+        }
+    }
+
+    /* 
+       Use results of previous checks
+    */
+
+exit_cleanup:
+    closedir(dp);    
+    return ret;
+}
+
+static int scanvol(struct volinfo *vi, dbd_flags_t flags)
+{
+    /* Dont scanvol on no-appledouble vols */
+    if (vi->v_flags & AFPVOL_NOADOUBLE) {
+        dbd_log( LOGSTD, "Volume without AppleDouble support: skipping volume scanning.");
+        return 0;
+    }
+
+    /* Make this stuff accessible from all funcs easily */
+    volinfo = vi;
+    dbd_flags = flags;
+
+    /* Run with umask 0 */
+    umask(0);
+
+    /* chdir to vol */
+    strcpy(cwdbuf, volinfo->v_path);
+    if (cwdbuf[strlen(cwdbuf) - 1] == '/')
+        cwdbuf[strlen(cwdbuf) - 1] = 0;
+    chdir(volinfo->v_path);
+
+    /* Start recursion */
+    if (dbd_readdir(1, 2) < 0)  /* 2 = volumeroot CNID */
+        return -1;
+
+    return 0;
+}
+
+int cmd_dbd_scanvol(DBD *dbd, struct volinfo *volinfo, dbd_flags_t flags)
+{
+    int ret = 0;
+
+    /* We only support unicode volumes ! */
+    if ( volinfo->v_volcharset != CH_UTF8) {
+        dbd_log( LOGSTD, "Not a Unicode volume: %s, %u != %u", volinfo->v_volcodepage, volinfo->v_volcharset, CH_UTF8);
+        return -1;
+    }
+
+    /* open/create dbd, copy rootinfo key */
+    if (NULL == (dbd_rebuild = dbif_init(NULL)))
+        return -1;
+    if (0 != (dbif_open(dbd_rebuild, NULL, 0)))
+        return -1;
+    if (0 != (ret = dbif_copy_rootinfokey(dbd, dbd_rebuild)))
+        goto exit_cleanup;
+
+    dbd_log( LOGSTD, "dumping rebuilddb");
+    dbif_dump(dbd_rebuild, 0);
+
+    /* scanvol */
+    if ( (scanvol(volinfo, flags)) != 0)
+        return -1;
+
+exit_cleanup:
+    dbif_close(dbd_rebuild);
+    return ret;
+}
index 413071fb06f1fe9f2f97d42b2ad2d95411623057..07e79c208134c00831f36788bb1af027cb66fdc7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: db_param.c,v 1.4 2009-04-21 08:55:44 franklahm Exp $
+ * $Id: db_param.c,v 1.5 2009-05-06 11:54:24 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * Copyright (c) Frank Lahm 2009
@@ -152,7 +152,7 @@ struct db_param *db_param_read(char *dir, enum identity id)
         }
 
         /* Config for dbd only */
-        else if (id == DBD ) {
+        else if (id == CNID_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);
index 2690673f684e715b338b6efd7abd95d7a125b735..18b13b5d3aee1b5b95bc84cc31ad43edbebbbb4f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: db_param.h,v 1.3 2009-04-21 08:55:44 franklahm Exp $
+ * $Id: db_param.h,v 1.4 2009-05-06 11:54:24 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -13,7 +13,7 @@
 
 enum identity {
     METAD,
-    DBD
+    CNID_DBD
 };
 
 struct db_param {
index f7a840fbc78d677ba739ab97baf00ddb105a46c4..39384ebf14f2d3ddaee761b7e2786a3b1501a2d6 100644 (file)
@@ -1,5 +1,5 @@
 /* 
-   $Id: dbd.c,v 1.2 2009-04-28 14:09:00 franklahm Exp $
+   $Id: dbd.c,v 1.3 2009-05-06 11:54:24 franklahm Exp $
 
    Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
    
 #include <atalk/logger.h>
 #include <atalk/cnid_dbd_private.h>
 #include <atalk/volinfo.h>
+#include "cmd_dbd.h"
 #include "dbif.h"
 #include "db_param.h"
 
 #define LOCKFILENAME  "lock"
-#define DBOPTIONS (DB_CREATE | DB_INIT_LOCK | DB_INIT_MPOOL | DB_INIT_TXN)
+#define DBOPTIONS (DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN)
 
-enum logtype {LOGSTD, LOGDEBUG};
+static DBD *dbd;
 
 static volatile sig_atomic_t alarmed;
-static int verbose; /* Logging flag */
-static int exclusive;  /* How to open the bdb database */
-static struct volinfo volinfo;
+static int verbose;             /* Logging flag */
+static int exclusive;           /* Exclusive volume access */
 static struct db_param db_param = {
     NULL,                       /* Volume dirpath */
     1,                          /* bdb logfile autoremove */
@@ -58,7 +58,7 @@ static struct db_param db_param = {
 /* 
    Provide some logging
  */
-static void dblog(enum logtype lt, char *fmt, ...)
+void dbd_log(enum logtype lt, char *fmt, ...)
 {
     int len;
     static char logbuffer[1024];
@@ -95,7 +95,7 @@ void set_signal(void)
     sigemptyset(&sv.sa_mask);
     sigaddset(&sv.sa_mask, SIGTERM);
     if (sigaction(SIGTERM, &sv, NULL) < 0) {
-        dblog( LOGSTD, "error in sigaction(SIGTERM): %s", strerror(errno));
+        dbd_log( LOGSTD, "error in sigaction(SIGTERM): %s", strerror(errno));
         exit(EXIT_FAILURE);
     }        
 
@@ -104,19 +104,19 @@ void set_signal(void)
     sigemptyset(&sv.sa_mask);
 
     if (sigaction(SIGINT, &sv, NULL) < 0) {
-        dblog( LOGSTD, "error in sigaction(SIGINT): %s", strerror(errno));
+        dbd_log( LOGSTD, "error in sigaction(SIGINT): %s", strerror(errno));
         exit(EXIT_FAILURE);
     }        
     if (sigaction(SIGABRT, &sv, NULL) < 0) {
-        dblog( LOGSTD, "error in sigaction(SIGABRT): %s", strerror(errno));
+        dbd_log( LOGSTD, "error in sigaction(SIGABRT): %s", strerror(errno));
         exit(EXIT_FAILURE);
     }        
     if (sigaction(SIGHUP, &sv, NULL) < 0) {
-        dblog( LOGSTD, "error in sigaction(SIGHUP): %s", strerror(errno));
+        dbd_log( LOGSTD, "error in sigaction(SIGHUP): %s", strerror(errno));
         exit(EXIT_FAILURE);
     }        
     if (sigaction(SIGQUIT, &sv, NULL) < 0) {
-        dblog( LOGSTD, "error in sigaction(SIGQUIT): %s", strerror(errno));
+        dbd_log( LOGSTD, "error in sigaction(SIGQUIT): %s", strerror(errno));
         exit(EXIT_FAILURE);
     }        
 }
@@ -143,7 +143,7 @@ int get_lock(void)
     struct flock lock;
 
     if ((lockfd = open(LOCKFILENAME, O_RDWR | O_CREAT, 0644)) < 0) {
-        dblog( LOGSTD, "Error opening lockfile: %s", strerror(errno));
+        dbd_log( LOGSTD, "Error opening lockfile: %s", strerror(errno));
         exit(EXIT_FAILURE);
     }
     
@@ -155,11 +155,11 @@ int get_lock(void)
     if (fcntl(lockfd, F_SETLK, &lock) < 0) {
         if (errno == EACCES || errno == EAGAIN) {
             if (exclusive) {
-                dblog( LOGDEBUG, "Database is in use and exlusive was requested", strerror(errno));        
+                dbd_log( LOGSTD, "Database is in use and exlusive was requested", strerror(errno));        
                 exit(EXIT_FAILURE);
             };
         } else {
-            dblog( LOGSTD, "Error getting fcntl F_WRLCK on lockfile: %s", strerror(errno));
+            dbd_log( LOGSTD, "Error getting fcntl F_WRLCK on lockfile: %s", strerror(errno));
             exit(EXIT_FAILURE);
        }
     }
@@ -183,37 +183,50 @@ static void usage ()
 {
     printf("Usage: dbd [-e|-v|-x] -d [-i] | -s | -r [-f] <path to netatalk volume>\n"
            "dbd can dump, scan, reindex and rebuild Netatalk dbd CNID databases.\n"
-           "dbd must run with appropiate permissions i.e. as root.\n\n"
+           "dbd must be run with appropiate permissions i.e. as root.\n\n"
            "Main commands are:\n"
-           "   -d dump\n"
-           "      Dump CNID database\n"
+           "   -d Dump CNID database\n"
            "      Option: -i dump indexes too\n"
-           "   -s scan\n"
-           "      Compare database with volume\n"
-           "   -r rebuild\n"
-           "      Rebuild CNID database\n"
-           "      Option: -f wipe database and rebuild from IDs stored in AppleDouble files\n\n"
+           "   -s Scan volume:\n"
+           "      1. Compare database with volume\n"
+           "      2. Check if .AppleDouble dirs exist\n"
+           "      3. Check if  AppleDouble file exist\n"
+           "      4. Report orphaned AppleDouble files\n"
+           "      5. Check for directories inside AppleDouble directories\n"
+           "      6. Check name encoding by roundtripping, log on error\n"
+           "   -r Rebuild volume:\n"
+           "      1. Sync database with volume\n"
+           "      2. Make sure .AppleDouble dir exist, create if missing\n"
+           "      3. Make sure AppleDouble file exists, create if missing\n"
+           "      4. Delete orphaned AppleDouble files\n"
+           "      5. Check for directories inside AppleDouble directories\n"
+           "      6. Check name encoding by roundtripping, log on error\n"
+           "      Option: -f wipe database and rebuild from IDs stored in AppleDouble files,\n"
+           "                 only available for volumes with 'cachecnid' option\n\n"
            "General options:\n"
            "   -e only work on inactive volumes and lock them (exclusive)\n"
            "   -x rebuild indexes\n"
            "   -v verbose\n"
            "\n"
-           "28-04-2009: -s and -r and not yet implemented\n"
+           "05-05-2009: -s and -r already check/repair the AppleDouble stuff and encoding,\n"
+           "            no CNID database maintanance is done yet\n"
         );
 }
 
 int main(int argc, char **argv)
 {
-    int c, ret, lockfd;
+    int c, lockfd;
     int dump=0, scan=0, rebuild=0, rebuildindexes=0, dumpindexes=0, force=0;
+    dbd_flags_t flags = 0;
     char *volpath;
+    struct volinfo volinfo;
 
     if (geteuid() != 0) {
         usage();
         exit(EXIT_FAILURE);
     }
 
-    while ((c = getopt(argc, argv, ":dsrvxif")) != -1) {
+    while ((c = getopt(argc, argv, ":dsrvxife")) != -1) {
         switch(c) {
         case 'd':
             dump = 1;
@@ -223,6 +236,7 @@ int main(int argc, char **argv)
             break;
         case 's':
             scan = 1;
+            flags = DBD_FLAGS_SCAN;
             break;
         case 'r':
             rebuild = 1;
@@ -238,6 +252,7 @@ int main(int argc, char **argv)
             break;
         case 'f':
             force = 1;
+            flags = DBD_FLAGS_FORCE;
             break;
         case ':':
         case '?':
@@ -260,23 +275,24 @@ int main(int argc, char **argv)
 
     /* Put "/.AppleDB" at end of volpath */
     if ( (strlen(volpath) + strlen("/.AppleDB")) > (PATH_MAX -1) ) {
-        dblog( LOGSTD, "Volume pathname too long");
+        dbd_log( LOGSTD, "Volume pathname too long");
         exit(EXIT_FAILURE);        
     }
     char dbpath[PATH_MAX];
     strncpy(dbpath, volpath, PATH_MAX - 1);
     strcat(dbpath, "/.AppleDB");
 
-    if ( -1 == (ret = loadvolinfo(volpath, &volinfo)) ) {
-        dblog( LOGSTD, "Unkown volume options!");
+    /* cd to .AppleDB dir */
+    int cdir;
+    if ((cdir = open(".", O_RDONLY)) < 0) {
+        dbd_log( LOGSTD, "Can't open dir: %s", strerror(errno));
         exit(EXIT_FAILURE);
     }
-    
     if (chdir(dbpath) < 0) {
-        dblog( LOGSTD, "chdir to %s failed: %s", dbpath, strerror(errno));
+        dbd_log( LOGSTD, "chdir to %s failed: %s", dbpath, strerror(errno));
         exit(EXIT_FAILURE);
     }
-    
+        
     /* 
        Before we do anything else, check if there is an instance of cnid_dbd
        running already and silently exit if yes.
@@ -292,28 +308,51 @@ int main(int argc, char **argv)
     else
         setuplog("default log_debug /dev/tty");
 
+    /* Load .volinfo file */
+    if ( -1 == loadvolinfo(volpath, &volinfo)) {
+        dbd_log( LOGSTD, "Unkown volume options!");
+        exit(EXIT_FAILURE);
+    }
+    if ( -1 == vol_load_charsets(&volinfo)) {
+        dbd_log( LOGSTD, "Error loading charsets!");
+        exit(EXIT_FAILURE);
+    }
+
     /* 
        Lets start with the BerkeleyDB stuff
     */
-    if (dbif_env_init(&db_param, DBOPTIONS) < 0) {
-        dblog( LOGSTD, "error opening database!");
+    if (NULL == (dbd = dbif_init("cnid2.db")))
+        exit(2);
+
+    if (dbif_env_open(dbd, &db_param, DBOPTIONS) < 0) {
+        dbd_log( LOGSTD, "error opening database!");
         exit(EXIT_FAILURE);
     }
 
-    dblog( LOGDEBUG, "Finished opening BerkeleyDB databases including recovery.");
+    dbd_log( LOGDEBUG, "Finished opening BerkeleyDB databases including recovery.");
 
-    if (dbif_open(&db_param, rebuildindexes) < 0) {
-        dbif_close();
+    if (dbif_open(dbd, &db_param, rebuildindexes) < 0) {
+        dbif_close(dbd);
         exit(EXIT_FAILURE);
     }
 
+    if ((fchdir(cdir)) < 0) {
+        dbd_log(LOGSTD, "fchdir: %s", strerror(errno));        
+        goto cleanup;
+    }
+
     if (dump) {
-        if (dbif_dump(dumpindexes) < 0) {
-            dblog( LOGSTD, "Error dumping database");
+        if (dbif_dump(dbd, dumpindexes) < 0) {
+            dbd_log( LOGSTD, "Error dumping database");
+        }
+    } else if (rebuild || scan) {
+        if (cmd_dbd_scanvol(dbd, &volinfo, flags) < 0) {
+            dbd_log( LOGSTD, "Fatal error repairing database. Please rm -r it.");
         }
     }
 
-    if (dbif_close() < 0)
+cleanup:
+    if (dbif_close(dbd) < 0)
         exit(EXIT_FAILURE);
 
     free_lock(lockfd);
index f7b7567b71b52129471317dd177f800981a6f569..a54d86105a3a112e1819b085aed692ad20b334cf 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * $Id: dbd.h,v 1.3 2009-04-21 08:55:44 franklahm Exp $
+ * $Id: dbd.h,v 1.4 2009-05-06 11:54:24 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
+ * Copyright (C) Frank Lahm 2009
  * All Rights Reserved.  See COPYING.
  */
 
 
 #include <atalk/cnid_dbd_private.h>
 
-extern int      dbd_stamp __P((void));
-extern int      dbd_add  __P((struct cnid_dbd_rqst *, struct cnid_dbd_rply *));
-extern int      dbd_get  __P((struct cnid_dbd_rqst *, struct cnid_dbd_rply *));
-extern int      dbd_resolve  __P((struct cnid_dbd_rqst *, struct cnid_dbd_rply *));
-extern int      dbd_lookup  __P((struct cnid_dbd_rqst *, struct cnid_dbd_rply *));
-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_indexes  __P((char *));
+extern int dbd_stamp(DBD *dbd);
+extern int dbd_add(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
+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 *);
+extern int dbd_getstamp(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
+extern int dbd_rebuild_add(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
+extern int dbd_check_indexes(DBD *dbd, char *);
 
 #endif /* CNID_DBD_DBD_H */
index 75d8eefef6448a6333fa9f3839963940d16a3314..0606bf45d5159bd7f3a99814c355791b34cab7da 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd_add.c,v 1.4 2009-05-04 09:09:43 franklahm Exp $
+ * $Id: dbd_add.c,v 1.5 2009-05-06 11:54:24 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -34,7 +34,7 @@
 #include "pack.h"
 #include "dbd.h"
 
-static int add_cnid(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
+static int add_cnid(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
 {
     DBT key, data;
     int rc;
@@ -50,7 +50,7 @@ static int add_cnid(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     memcpy(data.data, &rply->cnid, sizeof(rply->cnid));
 
     /* main database */
-    if ((rc = dbif_put(DBIF_IDX_CNID, &key, &data, DB_NOOVERWRITE))) {
+    if ((rc = dbif_put(dbd, DBIF_CNID, &key, &data, DB_NOOVERWRITE))) {
         /* This could indicate a database error or that the key already exists
          (because of DB_NOOVERWRITE). In that case we still look at some sort of
          database corruption since that is not supposed to happen. */
@@ -65,7 +65,7 @@ static int add_cnid(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
              , (char *)data.data + CNID_NAME_OFS);
             
             rqst->cnid = rply->cnid;
-            rc = dbd_update(rqst, rply);
+            rc = dbd_update(dbd, rqst, rply);
             if (rc < 0) {
                 rply->result = CNID_DBD_RES_ERR_DB;
                 return -1;
@@ -81,7 +81,7 @@ static int add_cnid(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
 }
 
 /* ---------------------- */
-static int get_cnid(struct cnid_dbd_rply *rply)
+static int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply)
 {
     DBT rootinfo_key, rootinfo_data;
     int rc;
@@ -92,7 +92,7 @@ static int get_cnid(struct cnid_dbd_rply *rply)
     rootinfo_key.data = ROOTINFO_KEY;
     rootinfo_key.size = ROOTINFO_KEYLEN;
 
-    if ((rc = dbif_get(DBIF_IDX_CNID, &rootinfo_key, &rootinfo_data, 0)) <= 0) {
+    if ((rc = dbif_get(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0)) <= 0) {
         rply->result = CNID_DBD_RES_ERR_DB;
         return -1;
     }
@@ -112,7 +112,7 @@ static int get_cnid(struct cnid_dbd_rply *rply)
     hint = htonl(id);
     memcpy((char *)rootinfo_data.data +CNID_TYPE_OFS, &hint, sizeof(hint));
 
-    if (dbif_put(DBIF_IDX_CNID, &rootinfo_key, &rootinfo_data, 0) < 0) {
+    if (dbif_put(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0) < 0) {
         rply->result = CNID_DBD_RES_ERR_DB;
         return -1;
     }
@@ -122,7 +122,7 @@ static int get_cnid(struct cnid_dbd_rply *rply)
 
 /* --------------- 
 */
-int dbd_stamp(void) 
+int dbd_stamp(DBD *dbd)
 {
     DBT rootinfo_key, rootinfo_data;
     cnid_t hint;
@@ -134,18 +134,18 @@ int dbd_stamp(void)
     rootinfo_key.data = ROOTINFO_KEY;
     rootinfo_key.size = ROOTINFO_KEYLEN;
 
-    switch (dbif_get(DBIF_IDX_CNID, &rootinfo_key, &rootinfo_data, 0)) {
+    switch (dbif_get(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0)) {
     case 0:
         hint = htonl(CNID_START);
         memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN);
         rootinfo_data.data = buf;
         rootinfo_data.size = ROOTINFO_DATALEN;
-        if (dbif_stamp(stamp, CNID_DEV_LEN) < 0) {
+        if (dbif_stamp(dbd, stamp, CNID_DEV_LEN) < 0) {
             return -1;
         }
-        memcpy((char *)rootinfo_data.data +CNID_TYPE_OFS, &hint, sizeof(hint));
-        memcpy((char *)rootinfo_data.data +CNID_DEV_OFS, stamp, sizeof(stamp));
-        if (dbif_put(DBIF_IDX_CNID, &rootinfo_key, &rootinfo_data, 0) < 0) {
+        memcpy((char *)rootinfo_data.data + CNID_TYPE_OFS, &hint, sizeof(hint));
+        memcpy((char *)rootinfo_data.data + CNID_DEV_OFS, stamp, sizeof(stamp));
+        if (dbif_put(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0) < 0) {
             return -1;
         }
         return 0;
@@ -159,12 +159,12 @@ int dbd_stamp(void)
 }
 
 /* ------------------------ */
-int dbd_add(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
+int dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
 {
     rply->namelen = 0;
 
     /* See if we have an entry already and return it if yes */
-    if (dbd_lookup(rqst, rply) < 0)
+    if (dbd_lookup(dbd, rqst, rply) < 0)
         return -1;
 
     if (rply->result == CNID_DBD_RES_OK) {
@@ -173,7 +173,7 @@ int dbd_add(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
         return 1;
     }
 
-    if (get_cnid(rply) < 0) {
+    if (get_cnid(dbd, rply) < 0) {
         if (rply->result == CNID_DBD_RES_ERR_MAX) {
             LOG(log_error, logtype_cnid, "dbd_add: FATAL: CNID database has reached its limit.");
             /* This will cause an abort/rollback if transactions are used */
@@ -184,7 +184,7 @@ int dbd_add(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
         }
     }
     
-    if (add_cnid(rqst, rply) < 0) {
+    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));
             /* abort/rollback, see above */
index b55a1e5c0754e5b6121cb14c588a7ee4b8468092..3ea137e463dea4ff23aa12a50ae404966062a162 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd_dbcheck.c,v 1.3 2009-04-21 08:55:44 franklahm Exp $
+ * $Id: dbd_dbcheck.c,v 1.4 2009-05-06 11:54:24 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
 #include "dbif.h"
 #include "dbd.h"
 
-int dbd_check_indexes(char *dbdir)
+int dbd_check_indexes(DBD *dbd, char *dbdir)
 {
     u_int32_t c_didname = 0, c_devino = 0, c_cnid = 0;
 
     LOG(log_note, logtype_cnid, "CNID database at `%s' is being checked (quick)", dbdir);
 
-    if (dbif_count(DBIF_IDX_CNID, &c_cnid)) 
+    if (dbif_count(dbd, DBIF_CNID, &c_cnid)) 
         return -1;
 
-    if (dbif_count(DBIF_IDX_DEVINO, &c_devino))
+    if (dbif_count(dbd, DBIF_IDX_DEVINO, &c_devino))
         return -1;
 
     /* bailout after the first error */
@@ -40,7 +40,7 @@ int dbd_check_indexes(char *dbdir)
         return 1;
     }
 
-    if (dbif_count(DBIF_IDX_DIDNAME, &c_didname)) 
+    if (dbif_count(dbd, DBIF_IDX_DIDNAME, &c_didname)) 
         return -1;
     
     if ( c_cnid != c_didname) {
index 49d24860df8c6496e137f8a512829df623773abb..6894c3ba763c97978dc645b9cc947d74f22d50ee 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd_delete.c,v 1.3 2009-05-04 09:09:43 franklahm Exp $
+ * $Id: dbd_delete.c,v 1.4 2009-05-06 11:54:24 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -19,7 +19,7 @@
 #include "dbd.h"
 #include "pack.h"
 
-int dbd_delete(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
+int dbd_delete(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
 {
     DBT key;
     int rc;
@@ -31,7 +31,7 @@ int dbd_delete(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     key.data = (void *) &rqst->cnid;
     key.size = sizeof(rqst->cnid);
 
-    if ((rc = dbif_del(DBIF_IDX_CNID, &key, 0)) < 0) {
+    if ((rc = dbif_del(dbd, DBIF_CNID, &key, 0)) < 0) {
         LOG(log_error, logtype_cnid, "dbd_delete: Unable to delete entry for CNID %u", ntohl(rqst->cnid));
         rply->result = CNID_DBD_RES_ERR_DB;
         return -1;
index 59d819ee0d00cb65a76d9622431eb3e2639e804b..9c07c40519799f4ad3ef94524a2d6c07c3ba0dea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd_get.c,v 1.3 2009-05-04 09:09:43 franklahm Exp $
+ * $Id: dbd_get.c,v 1.4 2009-05-06 11:54:24 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -24,7 +24,7 @@
 
 /* Return CNID for a given did/name. */
 
-int dbd_get(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
+int dbd_get(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
 {
     char start[CNID_DID_LEN + MAXPATHLEN + 1], *buf;
     DBT key, data;
@@ -43,7 +43,7 @@ int dbd_get(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     key.data = start;
     key.size = CNID_DID_LEN + rqst->namelen + 1;
 
-    if ((rc = dbif_get(DBIF_IDX_DIDNAME, &key, &data, 0)) < 0) {
+    if ((rc = dbif_get(dbd, DBIF_IDX_DIDNAME, &key, &data, 0)) < 0) {
         LOG(log_error, logtype_cnid, "dbd_get: Unable to get CNID %u, name %s", ntohl(rqst->did), rqst->name);
         rply->result = CNID_DBD_RES_ERR_DB;
         return -1;
index 328e80b458faa2868ebdbb179d111a94a7c178ff..b7fc936aa893c2df3cfaa4b4cc5020882cf0f01a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd_getstamp.c,v 1.3 2009-04-21 08:55:44 franklahm Exp $
+ * $Id: dbd_getstamp.c,v 1.4 2009-05-06 11:54:24 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -21,7 +21,7 @@
 
 /* Return the unique stamp associated with this database */
 
-int dbd_getstamp(struct cnid_dbd_rqst *rqst _U_, struct cnid_dbd_rply *rply)
+int dbd_getstamp(DBD *dbd, struct cnid_dbd_rqst *rqst _U_, struct cnid_dbd_rply *rply)
 {
     DBT key, data;
     int rc;
@@ -35,7 +35,7 @@ int dbd_getstamp(struct cnid_dbd_rqst *rqst _U_, struct cnid_dbd_rply *rply)
     key.data = ROOTINFO_KEY;
     key.size = ROOTINFO_KEYLEN;
 
-    if ((rc = dbif_get(DBIF_IDX_CNID, &key, &data, 0)) < 0) {
+    if ((rc = dbif_get(dbd, DBIF_CNID, &key, &data, 0)) < 0) {
         LOG(log_error, logtype_cnid, "dbd_getstamp: Error getting rootinfo record");
         rply->result = CNID_DBD_RES_ERR_DB;
         return -1;
index 4a008beb7e94650093a51138977cea8fe8534842..c46b746d3458e63c86cf10cadc3f830c74d98d51 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd_lookup.c,v 1.5 2009-05-04 09:09:43 franklahm Exp $
+ * $Id: dbd_lookup.c,v 1.6 2009-05-06 11:54:24 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -27,7 +27,7 @@
  *  up the database if there's a problem.
  */
 
-int dbd_lookup(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)
 {
     unsigned char *buf;
     DBT key, devdata, diddata;
@@ -62,7 +62,7 @@ int dbd_lookup(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     key.data = buf + CNID_DEVINO_OFS;
     key.size = CNID_DEVINO_LEN;
 
-    if ((rc = dbif_get(DBIF_IDX_DEVINO, &key, &devdata, 0))  < 0) {
+    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);
         rply->result = CNID_DBD_RES_ERR_DB;
@@ -80,7 +80,7 @@ int dbd_lookup(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     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) {
+    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);
         rply->result = CNID_DBD_RES_ERR_DB;
@@ -124,7 +124,7 @@ int dbd_lookup(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
         */
         if (!memcmp(dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) ||
                    type_didname != rqst->type) {
-            if (dbd_delete(rqst, rply) < 0) {
+            if (dbd_delete(dbd, rqst, rply) < 0) {
                 return -1;
             }
         }
@@ -139,7 +139,7 @@ int dbd_lookup(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
             /* 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(rqst, rply) < 0) {
+            if (dbd_delete(dbd, rqst, rply) < 0) {
                 return -1;
             }
         }
@@ -152,7 +152,7 @@ int dbd_lookup(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
         return 1;
     }
     /* Fix up the database. assume it was a file move and rename */
-    rc = dbd_update(rqst, rply);
+    rc = dbd_update(dbd, rqst, rply);
     if (rc >0) {
         rply->cnid = rqst->cnid;
     }
index 3b2a26e03a1385653c4c3a91b2522514420c5936..45b030718616b4c70da11b200eb935085326f914 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd_rebuild_add.c,v 1.2 2005-04-28 20:49:48 bfernhomberg Exp $
+ * $Id: dbd_rebuild_add.c,v 1.3 2009-05-06 11:54:24 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2005
  * All Rights Reserved.  See COPYING.
@@ -24,7 +24,7 @@
 /* rebuild_add: Enter all fields (including the CNID) into the database and
    update the current cnid, for emergency repairs. */
 
-int dbd_rebuild_add(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
+int dbd_rebuild_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
 {
     DBT key, data;
     cnid_t cur, tmp, id;
@@ -43,7 +43,7 @@ int dbd_rebuild_add(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
 
     /* FIXME: In cnid_cdb.c Bjoern does a lookup here and returns the CNID found if sucessful. Why? */
 
-    if (dbif_put(DBIF_IDX_CNID, &key, &data, 0) < 0) {
+    if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) < 0) {
        rply->result = CNID_DBD_RES_ERR_DB;
        return -1;
     }
@@ -51,7 +51,7 @@ int dbd_rebuild_add(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     key.data = ROOTINFO_KEY;   
     key.size = ROOTINFO_KEYLEN;
     
-    if (dbif_get(DBIF_IDX_CNID, &key, &data, 0) <= 0) {
+    if (dbif_get(dbd, DBIF_CNID, &key, &data, 0) <= 0) {
        /* FIXME: If we cannot find ROOTINFO_KEY, should this be considered
            fatal or should we just return 0 and roll back? */
        rply->result = CNID_DBD_RES_ERR_DB;
@@ -65,7 +65,7 @@ int dbd_rebuild_add(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     if (id > cur) {
        data.size = ROOTINFO_DATALEN;
        memcpy((char *) data.data + CNID_TYPE_OFS, &rqst->cnid, sizeof(cnid_t));
-       if (dbif_put(DBIF_IDX_CNID, &key, &data, 0) < 0) {
+       if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) < 0) {
            rply->result = CNID_DBD_RES_ERR_DB;
            return -1;
        }
index 14f22cf4d24973d3ae132eed1b5597eaf5a72380..6008d152dc10e1d6f550fe915ade078f7094c0cb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd_resolve.c,v 1.3 2009-05-04 09:09:43 franklahm Exp $
+ * $Id: dbd_resolve.c,v 1.4 2009-05-06 11:54:24 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -21,7 +21,7 @@
 
 /* Return the did/name pair corresponding to a CNID. */
 
-int dbd_resolve(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
+int dbd_resolve(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
 {
     DBT key, data;
     int rc;
@@ -34,7 +34,7 @@ int dbd_resolve(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     key.data = (void *) &rqst->cnid;
     key.size = sizeof(cnid_t);
 
-    if ((rc = dbif_get(DBIF_IDX_CNID, &key, &data, 0)) < 0) {
+    if ((rc = dbif_get(dbd, DBIF_CNID, &key, &data, 0)) < 0) {
         LOG(log_error, logtype_cnid, "dbd_resolve: DB Error resolving CNID %u", ntohl(rqst->cnid));
         rply->result = CNID_DBD_RES_ERR_DB;
         return -1;
index 8fb79622a0d30d7a8edf0ce00e1aeab688b91620..2ac5be107d5f242fd93d044c30510edcf1db553d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbd_update.c,v 1.4 2009-05-04 09:09:43 franklahm Exp $
+ * $Id: dbd_update.c,v 1.5 2009-05-06 11:54:24 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * All Rights Reserved.  See COPYING.
@@ -32,7 +32,7 @@
       other secondary index.
 */   
    
-int dbd_update(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
+int dbd_update(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
 {
     DBT key,pkey, data;
     int rc;
@@ -53,7 +53,7 @@ int dbd_update(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
 
     data.data = getbuf;
     data.size = CNID_HEADER_LEN + MAXPATHLEN + 1;
-    if ((rc = dbif_pget(DBIF_IDX_DEVINO, &key, &pkey, &data, 0)) < 0 ) {
+    if ((rc = dbif_pget(dbd, DBIF_IDX_DEVINO, &key, &pkey, &data, 0)) < 0 ) {
         goto err_db;
     }
     else if  (rc > 0) {
@@ -61,7 +61,7 @@ int dbd_update(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
         LOG(log_debug, logtype_cnid, "dbd_update: Deleting %u corresponding to dev/ino 0x%llx/0x%llx from cnid2.db",
             ntohl(tmpcnid), ntoh64((unsigned long long int)rqst->dev), ntoh64((unsigned long long int)rqst->ino));
 
-        if ((rc = dbif_del(DBIF_IDX_CNID, &pkey, 0)) < 0 ) {
+        if ((rc = dbif_del(dbd, DBIF_CNID, &pkey, 0)) < 0 ) {
             goto err_db;
         }
         else if (!rc) {
@@ -77,17 +77,17 @@ int dbd_update(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     key.size = CNID_DID_LEN + rqst->namelen +1;
     memset(&pkey, 0, sizeof(pkey));
 
-    if ((rc = dbif_pget(DBIF_IDX_DIDNAME, &key, &pkey, &data, 0)) < 0) {
+    if ((rc = dbif_pget(dbd, DBIF_IDX_DIDNAME, &key, &pkey, &data, 0)) < 0) {
         goto err_db;
     }
     else if  (rc > 0) {
 
-       memcpy(&tmpcnid, pkey.data, sizeof(cnid_t));
-
-       LOG(log_debug, logtype_cnid, "dbd_update: Deleting %u corresponding to did %u name %s from cnid2.db",
-           ntohl(tmpcnid), ntohl(rqst->did), rqst->name);
-
-        if ((rc = dbif_del(DBIF_IDX_CNID, &pkey, 0)) < 0) {
+        memcpy(&tmpcnid, pkey.data, sizeof(cnid_t));
+        
+        LOG(log_debug, logtype_cnid, "dbd_update: Deleting %u corresponding to did %u name %s from cnid2.db",
+            ntohl(tmpcnid), ntohl(rqst->did), rqst->name);
+    
+        if ((rc = dbif_del(dbd, DBIF_CNID, &pkey, 0)) < 0) {
             goto err_db;
         }
         else if (!rc) {
@@ -108,7 +108,7 @@ int dbd_update(struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
     memcpy(data.data, &rqst->cnid, sizeof(rqst->cnid));
     data.size = CNID_HEADER_LEN + rqst->namelen + 1;
 
-    if (dbif_put(DBIF_IDX_CNID, &key, &data, 0) < 0)
+    if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) < 0)
         goto err_db;
 
     LOG(log_info, logtype_cnid, "dbd_update: Updated cnid2.db with dev/ino 0x%llx/0x%llx did %u name %s cnid %u",
index 36131442945e78ed248b2c1375e14d006c0d829b..5b02b536cafefc9aff2c2e0c42f074259f6e5019 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dbif.c,v 1.7 2009-04-28 13:01:24 franklahm Exp $
+ * $Id: dbif.c,v 1.8 2009-05-06 11:54:24 franklahm Exp $
  *
  * Copyright (C) Joerg Lenneis 2003
  * Copyright (C) Frank Lahm 2009
 
 #define DB_ERRLOGFILE "db_errlog"
 
-static DB_ENV *db_env = NULL;
-static DB_TXN *db_txn = NULL;
-static FILE   *db_errlog = NULL;
-
-static struct db_table {
-    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},
-};
-
 static char *old_dbfiles[] = {"cnid.db", NULL};
 
-/* --------------- */
-static int  db_compat_associate (DB *p, DB *s,
-                                 int (*callback)(DB *, const DBT *,const DBT *, DBT *),
-                                 u_int32_t flags)
-{
-    return p->associate(p, NULL, s, callback, flags);
-}
-
-/* --------------- */
-static int db_compat_open(DB *db, char *file, char *name, DBTYPE type, int mode)
-{
-    int ret;
-
-    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));
-        return -1;
-    } else {
-        return 0;
-    }
-}
-
 /* --------------- */
 static int upgrade_required()
 {
@@ -91,7 +52,7 @@ static int upgrade_required()
 }
 
 /* --------------- */
-int dbif_stamp(void *buffer, int size)
+int dbif_stamp(DBD *dbd, void *buffer, int size)
 {
     struct stat st;
     int         rc;
@@ -99,8 +60,8 @@ int dbif_stamp(void *buffer, int size)
     if (size < 8)
         return -1;
 
-    if ((rc = stat(db_table[0].name, &st)) < 0) {
-        LOG(log_error, logtype_cnid, "error stating database %s: %s", db_table[0].name, db_strerror(rc));
+    if ((rc = stat(dbd->db_table[DBIF_CNID].name, &st)) < 0) {
+        LOG(log_error, logtype_cnid, "error stating database %s: %s", dbd->db_table[DBIF_CNID].name, db_strerror(rc));
         return -1;
     }
     memset(buffer, 0, size);
@@ -109,12 +70,47 @@ int dbif_stamp(void *buffer, int size)
     return 0;
 }
 
+/* --------------- */
+DBD *dbif_init(const char *filename)
+{
+    DBD *dbd;
+
+    if ( NULL == (dbd = calloc(sizeof(DBD), 1)) )
+        return NULL;
+
+    /* filename == NULL means in memory db */
+    if (filename) {
+        dbd->db_filename = strdup(filename);
+        if (NULL == dbd->db_filename) {
+            free(dbd);
+            return NULL;
+        }
+    }
+    
+    dbd->db_table[DBIF_CNID].name        = "cnid2.db";
+    dbd->db_table[DBIF_IDX_DEVINO].name  = "devino.db";
+    dbd->db_table[DBIF_IDX_DIDNAME].name = "didname.db";
+
+    dbd->db_table[DBIF_CNID].type        = DB_BTREE;
+    dbd->db_table[DBIF_IDX_DEVINO].type  = DB_BTREE;
+    dbd->db_table[DBIF_IDX_DIDNAME].type = DB_BTREE;
+
+    if (filename == NULL) {
+        /* Without an environment we must pass DB_CREATE to db->open */
+        dbd->db_table[DBIF_CNID].openflags        = DB_CREATE;
+        dbd->db_table[DBIF_IDX_DEVINO].openflags  = DB_CREATE;
+        dbd->db_table[DBIF_IDX_DIDNAME].openflags = DB_CREATE;
+    }
+
+    return dbd;
+}
+
 /* --------------- */
 /*
  *  We assume our current directory is already the BDB homedir. Otherwise
  *  opening the databases will not work as expected.
  */
-int dbif_env_init(struct db_param *dbp, uint32_t dbenv_oflags)
+int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags)
 {
     int ret;
     char **logfiles = NULL;
@@ -126,83 +122,86 @@ int dbif_env_init(struct db_param *dbp, uint32_t dbenv_oflags)
         return -1;
     }
 
-    if ((db_errlog = fopen(DB_ERRLOGFILE, "a")) == NULL)
+    if ((dbd->db_errlog = fopen(DB_ERRLOGFILE, "a")) == NULL)
         LOG(log_warning, logtype_cnid, "error creating/opening DB errlogfile: %s", strerror(errno));
 
-    if ((ret = db_env_create(&db_env, 0))) {
+    if ((ret = db_env_create(&dbd->db_env, 0))) {
         LOG(log_error, logtype_cnid, "error creating DB environment: %s",
             db_strerror(ret));
-        db_env = NULL;
+        dbd->db_env = NULL;
         return -1;
     }
 
-    if (db_errlog != NULL) {
-        db_env->set_errfile(db_env, db_errlog);
-        db_env->set_msgfile(db_env, db_errlog);
+    if (dbd->db_errlog != NULL) {
+        dbd->db_env->set_errfile(dbd->db_env, dbd->db_errlog);
+        dbd->db_env->set_msgfile(dbd->db_env, dbd->db_errlog);
     }
 
-    db_env->set_verbose(db_env, DB_VERB_RECOVERY, 1);
+    dbd->db_env->set_verbose(dbd->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, ".", dbenv_oflags | DB_PRIVATE | DB_RECOVER, 0))) {
-        LOG(log_error, logtype_cnid, "error opening DB environment: %s",
-            db_strerror(ret));
-        db_env->close(db_env, 0);
-        db_env = NULL;
-        return -1;
-    }
+    if (dbenv_oflags & DB_RECOVER) {
+        /* Open the database for recovery using DB_PRIVATE option which is faster */
+        if ((ret = dbd->db_env->open(dbd->db_env, ".", dbenv_oflags | DB_PRIVATE, 0))) {
+            LOG(log_error, logtype_cnid, "error opening DB environment: %s",
+                db_strerror(ret));
+            dbd->db_env->close(dbd->db_env, 0);
+            dbd->db_env = NULL;
+            return -1;
+        }
+        dbenv_oflags = (dbenv_oflags & ~DB_RECOVER);
 
-    if (db_errlog != NULL)
-        fflush(db_errlog);
+        if (dbd->db_errlog != NULL)
+            fflush(dbd->db_errlog);
 
-    if ((ret = db_env->close(db_env, 0))) {
-        LOG(log_error, logtype_cnid, "error closing DB environment after recovery: %s",
-            db_strerror(ret));
-        db_env = NULL;
-        return -1;
-    }
+        if ((ret = dbd->db_env->close(dbd->db_env, 0))) {
+            LOG(log_error, logtype_cnid, "error closing DB environment after recovery: %s",
+                db_strerror(ret));
+            dbd->db_env = NULL;
+            return -1;
+        }
 
-    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_create(&dbd->db_env, 0))) {
+            LOG(log_error, logtype_cnid, "error creating DB environment after recovery: %s",
+                db_strerror(ret));
+            dbd->db_env = NULL;
+            return -1;
+        }
     }
 
-    if ((ret = db_env->set_cachesize(db_env, 0, 1024 * dbp->cachesize, 0))) {
+    if ((ret = dbd->db_env->set_cachesize(dbd->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));
-        db_env->close(db_env, 0);
-        db_env = NULL;
+        dbd->db_env->close(dbd->db_env, 0);
+        dbd->db_env = NULL;
         return -1;
     }
 
-    if (db_errlog != NULL) {
-        db_env->set_errfile(db_env, db_errlog);
-        db_env->set_msgfile(db_env, db_errlog);
+    if (dbd->db_errlog != NULL) {
+        dbd->db_env->set_errfile(dbd->db_env, dbd->db_errlog);
+        dbd->db_env->set_msgfile(dbd->db_env, dbd->db_errlog);
     }
-    if ((ret = db_env->open(db_env, ".", dbenv_oflags, 0))) {
+    if ((ret = dbd->db_env->open(dbd->db_env, ".", dbenv_oflags, 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;
+        dbd->db_env->close(dbd->db_env, 0);
+        dbd->db_env = NULL;
         return -1;
     }
 
-    if ((ret = db_env->set_flags(db_env, DB_AUTO_COMMIT, 1))) {
+    if ((ret = dbd->db_env->set_flags(dbd->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;
+        dbd->db_env->close(dbd->db_env, 0);
+        dbd->db_env = NULL;
         return -1;
     }
 
     if (dbp->logfile_autoremove) {
-        if (db_env->log_archive(db_env, &logfiles, 0)) {
+        if (dbd->db_env->log_archive(dbd->db_env, &logfiles, 0)) {
             LOG(log_error, logtype_cnid, "error getting list of stale logfiles: %s",
                 db_strerror(ret));
-            db_env->close(db_env, 0);
-            db_env = NULL;
+            dbd->db_env->close(dbd->db_env, 0);
+            dbd->db_env = NULL;
             return -1;
         }
         if (logfiles != NULL) {
@@ -214,19 +213,19 @@ int dbif_env_init(struct db_param *dbp, uint32_t dbenv_oflags)
         }
 
 #if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 7)
-        if ((ret = db_env->log_set_config(db_env, DB_LOG_AUTO_REMOVE, 1))) {
+        if ((ret = dbd->db_env->log_set_config(dbd->db_env, DB_LOG_AUTO_REMOVE, 1))) {
             LOG(log_error, logtype_cnid, "error setting DB_LOG_AUTO_REMOVE flag: %s",
             db_strerror(ret));
-            db_env->close(db_env, 0);
-            db_env = NULL;
+            dbd->db_env->close(dbd->db_env, 0);
+            dbd->db_env = NULL;
             return -1;
         }
 #else
-        if ((ret = db_env->set_flags(db_env, DB_LOG_AUTOREMOVE, 1))) {
+        if ((ret = dbd->db_env->set_flags(dbd->db_env, DB_LOG_AUTOREMOVE, 1))) {
             LOG(log_error, logtype_cnid, "error setting DB_LOG_AUTOREMOVE flag: %s",
                 db_strerror(ret));
-            db_env->close(db_env, 0);
-            db_env = NULL;
+            dbd->db_env->close(dbd->db_env, 0);
+            dbd->db_env = NULL;
             return -1;
         }
 #endif
@@ -236,37 +235,46 @@ int dbif_env_init(struct db_param *dbp, uint32_t dbenv_oflags)
 }
 
 /* --------------- */
-int dbif_open(struct db_param *dbp _U_, int do_truncate)
+int dbif_open(DBD *dbd, struct db_param *dbp _U_, int do_truncate)
 {
     int ret;
     int i;
     u_int32_t count;
 
     for (i = 0; i != DBIF_DB_CNT; i++) {
-        if ((ret = db_create(&(db_table[i].db), db_env, 0))) {
+        if ((ret = db_create(&dbd->db_table[i].db, dbd->db_env, 0))) {
             LOG(log_error, logtype_cnid, "error creating handle for database %s: %s",
-                db_table[i].name, db_strerror(ret));
+                dbd->db_table[i].name, db_strerror(ret));
             return -1;
         }
 
-        if (db_table[i].general_flags) {
-            if ((ret = db_table[i].db->set_flags(db_table[i].db, db_table[i].general_flags))) {
+        if (dbd->db_table[i].flags) {
+            if ((ret = dbd->db_table[i].db->set_flags(dbd->db_table[i].db,
+                                                      dbd->db_table[i].flags))) {
                 LOG(log_error, logtype_cnid, "error setting flags for database %s: %s",
-                    db_table[i].name, db_strerror(ret));
+                    dbd->db_table[i].name, db_strerror(ret));
                 return -1;
             }
         }
 
-        if (db_compat_open(db_table[i].db, db_table[0].name, db_table[i].name, db_table[i].type, 0664) < 0)
+        if (dbd->db_table[i].db->open(dbd->db_table[i].db,
+                                      dbd->db_txn,
+                                      dbd->db_filename,
+                                      dbd->db_table[i].name,
+                                      dbd->db_table[i].type,
+                                      dbd->db_table[i].openflags,
+                                      0664) < 0) {
+            LOG(log_error, logtype_cnid, "Cant open database");
             return -1;
-        if (db_errlog != NULL)
-            db_table[i].db->set_errfile(db_table[i].db, db_errlog);
+        }
+        if (dbd->db_errlog != NULL)
+            dbd->db_table[i].db->set_errfile(dbd->db_table[i].db, dbd->db_errlog);
 
         if (do_truncate && i > 0) {
             LOG(log_info, logtype_cnid, "Truncating CNID index.");
-            if ((ret = db_table[i].db->truncate(db_table[i].db, NULL, &count, 0))) {
+            if ((ret = dbd->db_table[i].db->truncate(dbd->db_table[i].db, NULL, &count, 0))) {
                 LOG(log_error, logtype_cnid, "error truncating database %s: %s",
-                    db_table[i].name, db_strerror(ret));
+                    dbd->db_table[i].name, db_strerror(ret));
                 return -1;
             }
         }
@@ -275,33 +283,47 @@ int dbif_open(struct db_param *dbp _U_, int do_truncate)
     /* TODO: Implement CNID DB versioning info on new databases. */
 
     /* Associate the secondary with the primary. */
-    LOG(log_debug, logtype_cnid, "Associating DBIF_IDX_DIDNAME index. Possibly reindexing...");
-    if ((ret = db_compat_associate(db_table[0].db, db_table[DBIF_IDX_DIDNAME].db, didname, (do_truncate)?DB_CREATE:0)) != 0) {
+    if (do_truncate)
+        LOG(log_info, logtype_cnid, "Reindexing did/name index...");
+    if ((ret = dbd->db_table[0].db->associate(dbd->db_table[DBIF_CNID].db,
+                                              dbd->db_txn,
+                                              dbd->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;
     }
-    LOG(log_debug, logtype_cnid, "... done.");
-
-    LOG(log_debug, logtype_cnid, "Associating DBIF_IDX_DEVINO index. Possibly reindexing...");
-    if ((ret = db_compat_associate(db_table[0].db, db_table[DBIF_IDX_DEVINO].db, devino, (do_truncate)?DB_CREATE:0)) != 0) {
+    if (do_truncate)
+        LOG(log_info, logtype_cnid, "... done.");
+
+    if (do_truncate)
+        LOG(log_info, logtype_cnid, "Reindexing dev/ino index...");
+    if ((ret = dbd->db_table[0].db->associate(dbd->db_table[0].db, 
+                                              dbd->db_txn,
+                                              dbd->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;
     }
-    LOG(log_debug, logtype_cnid, "... done.");
-
+    if (do_truncate)
+        LOG(log_info, logtype_cnid, "... done.");
+    
     return 0;
 }
 
 /* ------------------------ */
-int dbif_closedb()
+int dbif_closedb(DBD *dbd)
 {
     int i;
     int ret;
     int err = 0;
 
     for (i = DBIF_DB_CNT -1; i >= 0; i--) {
-        if (db_table[i].db != NULL && (ret = db_table[i].db->close(db_table[i].db, 0))) {
-            LOG(log_error, logtype_cnid, "error closing database %s: %s", db_table[i].name, db_strerror(ret));
+        if (dbd->db_table[i].db != NULL && (ret = dbd->db_table[i].db->close(dbd->db_table[i].db, 0))) {
+            LOG(log_error, logtype_cnid, "error closing database %s: %s", dbd->db_table[i].name, db_strerror(ret));
             err++;
         }
     }
@@ -311,22 +333,27 @@ int dbif_closedb()
 }
 
 /* ------------------------ */
-int dbif_close()
+int dbif_close(DBD *dbd)
 {
     int ret;
     int err = 0;
 
-    if (dbif_closedb())
+    if (dbif_closedb(dbd))
         err++;
 
-    if (db_env != NULL && (ret = db_env->close(db_env, 0))) {
+    if (dbd->db_env != NULL && (ret = dbd->db_env->close(dbd->db_env, 0))) {
         LOG(log_error, logtype_cnid, "error closing DB environment: %s", db_strerror(ret));
         err++;
     }
-    if (db_errlog != NULL && fclose(db_errlog) == EOF) {
+    if (dbd->db_errlog != NULL && fclose(dbd->db_errlog) == EOF) {
         LOG(log_error, logtype_cnid, "error closing DB logfile: %s", strerror(errno));
         err++;
     }
+
+    free(dbd->db_filename);
+    free(dbd);
+    dbd = NULL;
+
     if (err)
         return -1;
     return 0;
@@ -342,94 +369,116 @@ int dbif_close()
  *  functions are not expected and therefore error conditions.
  */
 
-int dbif_get(const int dbi, DBT *key, DBT *val, u_int32_t flags)
+int dbif_get(DBD *dbd, const int dbi, DBT *key, DBT *val, u_int32_t flags)
 {
     int ret;
-    DB *db = db_table[dbi].db;
 
-    ret = db->get(db, db_txn, key, val, flags);
+    ret = dbd->db_table[dbi].db->get(dbd->db_table[dbi].db,
+                                     dbd->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));
+        LOG(log_error, logtype_cnid, "error retrieving value from %s: %s",
+            dbd->db_table[dbi].name, db_strerror(errno));
         return -1;
     } else
         return 1;
 }
 
 /* search by secondary return primary */
-int dbif_pget(const int dbi, DBT *key, DBT *pkey, DBT *val, u_int32_t flags)
+int dbif_pget(DBD *dbd, const int dbi, DBT *key, DBT *pkey, DBT *val, u_int32_t flags)
 {
     int ret;
-    DB *db = db_table[dbi].db;
 
-    ret = db->pget(db, db_txn, key, pkey, val, flags);
+    ret = dbd->db_table[dbi].db->pget(dbd->db_table[dbi].db,
+                                      dbd->db_txn,
+                                      key,
+                                      pkey,
+                                      val,
+                                      flags);
 
     if (ret == DB_NOTFOUND || ret == DB_SECONDARY_BAD) {
         return 0;
     }
     if (ret) {
-        LOG(log_error, logtype_cnid, "error retrieving value from %s: %s", db_table[dbi].name, db_strerror(errno));
+        LOG(log_error, logtype_cnid, "error retrieving value from %s: %s",
+            dbd->db_table[dbi].name, db_strerror(errno));
         return -1;
    } else
         return 1;
 }
 
 /* -------------------------- */
-int dbif_put(const int dbi, DBT *key, DBT *val, u_int32_t flags)
+int dbif_put(DBD *dbd, 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));
+    if (dbif_txn_begin(dbd) < 0) {
+        LOG(log_error, logtype_cnid, "error setting key/value in %s: %s",
+            dbd->db_table[dbi].name, db_strerror(errno));
         return -1;
     }
 
-    ret = db->put(db, db_txn, key, val, flags);
-
+    ret = dbd->db_table[dbi].db->put(dbd->db_table[dbi].db,
+                                     dbd->db_txn,
+                                     key,
+                                     val,
+                                     flags);
+    
     if (ret) {
         if ((flags & DB_NOOVERWRITE) && ret == DB_KEYEXIST) {
             return 1;
         } else {
-            LOG(log_error, logtype_cnid, "error setting key/value in %s: %s", db_table[dbi].name, db_strerror(errno));
+            LOG(log_error, logtype_cnid, "error setting key/value in %s: %s",
+                dbd->db_table[dbi].name, db_strerror(errno));
             return -1;
         }
     } else
         return 0;
 }
 
-int dbif_del(const int dbi, DBT *key, u_int32_t flags)
+int dbif_del(DBD *dbd, 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));
+    if (dbif_txn_begin(dbd) < 0) {
+        LOG(log_error, logtype_cnid, "error deleting key/value from %s: %s", 
+            dbd->db_table[dbi].name, db_strerror(errno));
         return -1;
     }
 
-    ret = db->del(db, db_txn, key, flags);
-
+    ret = dbd->db_table[dbi].db->del(dbd->db_table[dbi].db,
+                                     dbd->db_txn,
+                                     key,
+                                     flags);
+    
     if (ret == DB_NOTFOUND || ret == DB_SECONDARY_BAD)
         return 0;
     if (ret) {
-        LOG(log_error, logtype_cnid, "error deleting key/value from %s: %s", db_table[dbi].name, db_strerror(errno));
+        LOG(log_error, logtype_cnid, "error deleting key/value from %s: %s",
+            dbd->db_table[dbi].name, db_strerror(errno));
         return -1;
     } else
         return 1;
 }
 
-int dbif_txn_begin()
+int dbif_txn_begin(DBD *dbd)
 {
     int ret;
 
-    /* If we already have a acitve txn, just return */
-    if (db_txn)
+    /* If we already have an active txn, just return */
+    if (dbd->db_txn)
+        return 0;
+
+    /* If our DBD has no env, just return (-> in memory db) */
+    if (dbd->db_env == NULL)
         return 0;
 
-    ret = db_env->txn_begin(db_env, NULL, &db_txn, 0);
+    ret = dbd->db_env->txn_begin(dbd->db_env, NULL, &dbd->db_txn, 0);
 
     if (ret) {
         LOG(log_error, logtype_cnid, "error starting transaction: %s", db_strerror(errno));
@@ -438,15 +487,19 @@ int dbif_txn_begin()
         return 0;
 }
 
-int dbif_txn_commit()
+int dbif_txn_commit(DBD *dbd)
 {
     int ret;
 
-    if (!db_txn)
+    if (! dbd->db_txn)
         return 0;
 
-    ret = db_txn->commit(db_txn, 0);
-    db_txn = NULL;
+    /* If our DBD has no env, just return (-> in memory db) */
+    if (dbd->db_env == NULL)
+        return 0;
+
+    ret = dbd->db_txn->commit(dbd->db_txn, 0);
+    dbd->db_txn = NULL;
     
     if (ret) {
         LOG(log_error, logtype_cnid, "error committing transaction: %s", db_strerror(errno));
@@ -455,15 +508,19 @@ int dbif_txn_commit()
         return 1;
 }
 
-int dbif_txn_abort()
+int dbif_txn_abort(DBD *dbd)
 {
     int ret;
 
-    if (!db_txn)
+    if (! dbd->db_txn)
         return 0;
 
-    ret = db_txn->abort(db_txn);
-    db_txn = NULL;
+    /* If our DBD has no env, just return (-> in memory db) */
+    if (dbd->db_env == NULL)
+        return 0;
+
+    ret = dbd->db_txn->abort(dbd->db_txn);
+    dbd->db_txn = NULL;
     
     if (ret) {
         LOG(log_error, logtype_cnid, "error aborting transaction: %s", db_strerror(errno));
@@ -472,10 +529,10 @@ int dbif_txn_abort()
         return 0;
 }
 
-int dbif_txn_checkpoint(u_int32_t kbyte, u_int32_t min, u_int32_t flags)
+int dbif_txn_checkpoint(DBD *dbd, u_int32_t kbyte, u_int32_t min, u_int32_t flags)
 {
     int ret;
-    ret = db_env->txn_checkpoint(db_env, kbyte, min, flags);
+    ret = dbd->db_env->txn_checkpoint(dbd->db_env, kbyte, min, flags);
     if (ret) {
         LOG(log_error, logtype_cnid, "error checkpointing transaction susystem: %s", db_strerror(errno));
         return -1;
@@ -483,11 +540,11 @@ int dbif_txn_checkpoint(u_int32_t kbyte, u_int32_t min, u_int32_t flags)
         return 0;
 }
 
-int dbif_count(const int dbi, u_int32_t *count)
+int dbif_count(DBD *dbd, const int dbi, u_int32_t *count)
 {
     int ret;
     DB_BTREE_STAT *sp;
-    DB *db = db_table[dbi].db;
+    DB *db = dbd->db_table[dbi].db;
 
     ret = db->stat(db, NULL, &sp, 0);
 
@@ -502,17 +559,47 @@ int dbif_count(const int dbi, u_int32_t *count)
     return 0;
 }
 
-int dbif_dump(int dumpindexes)
+int dbif_copy_rootinfokey(DBD *srcdbd, DBD *destdbd)
+{
+    DBT key, data;
+    int rc;
+
+    memset(&key, 0, sizeof(key));
+    memset(&data, 0, sizeof(data));
+
+    key.data = ROOTINFO_KEY;
+    key.size = ROOTINFO_KEYLEN;
+
+    if ((rc = dbif_get(srcdbd, DBIF_CNID, &key, &data, 0)) <= 0) {
+        LOG(log_error, logtype_cnid, "dbif_copy_rootinfokey: Error getting rootinfo record");
+        return -1;
+    }
+
+    memset(&key, 0, sizeof(key));
+    key.data = ROOTINFO_KEY;
+    key.size = ROOTINFO_KEYLEN;
+
+    if ((rc = dbif_put(destdbd, DBIF_CNID, &key, &data, 0))) {
+        LOG(log_error, logtype_cnid, "dbif_copy_rootinfokey: Error writing rootinfo key");
+        return -1;
+    }
+
+    return 0;
+}
+
+int dbif_dump(DBD *dbd, int dumpindexes)
 {
     int rc;
-    uint32_t max = 0, count = 0, cnid, type, did;
+    uint32_t max = 0, count = 0, cnid, type, did, lastid;
     uint64_t dev, ino;
+    time_t stamp;
     DBC *cur;
     DBT key = { 0 }, data = { 0 };
-    DB *db = db_table[DBIF_IDX_CNID].db;
+    DB *db = dbd->db_table[DBIF_CNID].db;
     char *typestring[2] = {"f", "d"};
+    char timebuf[64];
 
-    printf("CNID database:\n");
+    printf("CNID database dump:\n");
 
     rc = db->cursor(db, NULL, &cur, 0);
     if (rc) {
@@ -530,6 +617,11 @@ int dbif_dump(int dumpindexes)
 
         /* Rootinfo node ? */
         if (cnid == 0) {
+            memcpy(&stamp, data.data + 4, sizeof(time_t));
+            memcpy(&lastid, data.data + 20, sizeof(cnid_t));
+            lastid = ntohl(lastid);
+            strftime(timebuf, sizeof(timebuf), "%b %d %Y %H:%M:%S", localtime(&stamp));
+            printf("dbd stamp: 0x%08x (%s), next free CNID: %u\n", (unsigned int)stamp, timebuf, lastid + 1);
         } else {
             /* dev */
             memcpy(&dev, data.data + CNID_DEV_OFS, 8);
@@ -572,7 +664,7 @@ int dbif_dump(int dumpindexes)
         /* DBIF_IDX_DEVINO */
         printf("\ndev/inode index:\n");
         count = 0;
-        db = db_table[DBIF_IDX_DEVINO].db;
+        db = dbd->db_table[DBIF_IDX_DEVINO].db;
         rc = db->cursor(db, NULL, &cur, 0);
         if (rc) {
             LOG(log_error, logtype_cnid, "Couldn't create cursor: %s", db_strerror(errno));
@@ -617,7 +709,7 @@ int dbif_dump(int dumpindexes)
         /* Now dump DBIF_IDX_DIDNAME */
         printf("\ndid/name index:\n");
         count = 0;
-        db = db_table[DBIF_IDX_DIDNAME].db;
+        db = dbd->db_table[DBIF_IDX_DIDNAME].db;
         rc = db->cursor(db, NULL, &cur, 0);
         if (rc) {
             LOG(log_error, logtype_cnid, "Couldn't create cursor: %s", db_strerror(errno));
index 0953f72f81730d50fe50894a24f7f2db40c2eb6f..ea6083d5b50cca1f5dc83e057397a9e8ff16931d 100644 (file)
@@ -1,10 +1,47 @@
 /*
- * $Id: dbif.h,v 1.4 2009-04-28 13:01:24 franklahm Exp $
- *
- * Copyright (C) Joerg Lenneis 2003
- * Copyright (C) Frank Lahm 2009
- * All Rights Reserved.  See COPYING.
- */
+  $Id: dbif.h,v 1.5 2009-05-06 11:54:24 franklahm Exp $
+  Copyright (C) Joerg Lenneis 2003
+  Copyright (C) Frank Lahm 2009
+  All Rights Reserved.  See COPYING.
+
+
+  API usage
+  =========
+
+  Initialisation
+  --------------
+  1. Provide storage for a DBD * handle
+     DBD *dbd;
+  2. Call dbif_init with a filename to receive a DBD handle:
+     dbd = dbif_init("cnid2.db");
+     Pass NULL to create an in-memory db.
+     Note: the DBD type is NOT from BerkeleyDB ! We've defined it.
+  3. Optional:
+     Call dbif_env_open to open an dbd environment, chdir to it beforehand
+  4. Call dbif_open to finally open the CNID database itself
+  
+  Querying the CNID database
+  --------------------------
+  Call dbif_[get|pget|put|del]. They map to the corresponding BerkeleyDB calls
+  with the same names.
+
+  Transactions
+  ------------
+  We use AUTO_COMMIT for the BDB database accesses. 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 from
+  dbif_put or dbif_del.
+  Thus you shouldn't call dbif_txn_[begin|abort|commit], they're used internally.
+
+  Checkpoiting
+  ------------
+  Call dbif_txn_checkpoint.
+
+  Closing
+  -------
+  Call dbif_close.
+*/
 
 #ifndef CNID_DBD_DBIF_H
 #define CNID_DBD_DBIF_H 1
 #include "db_param.h"
 
 #define DBIF_DB_CNT 3
-
-#define DBIF_IDX_CNID      0
+#define DBIF_CNID          0
 #define DBIF_IDX_DEVINO    1
 #define DBIF_IDX_DIDNAME   2
 
-extern int dbif_stamp(void *, int);
-extern int dbif_env_init(struct db_param *, uint32_t);
-extern int dbif_open(struct db_param *, int);
-extern int dbif_close(void);
-extern int dbif_closedb(void);
-extern int dbif_get(const int, DBT *, DBT *, u_int32_t);
-extern int dbif_pget(const int, DBT *, DBT *, DBT *, u_int32_t);
-extern int dbif_put(const int, DBT *, DBT *, u_int32_t);
-extern int dbif_del(const int, DBT *, u_int32_t);
+/* Structures */
+typedef struct {
+    char     *name;
+    DB       *db;
+    uint32_t flags;
+    uint32_t openflags;
+    DBTYPE   type;
+} db_table;
+
+typedef struct {
+    DB_ENV   *db_env;
+    DB_TXN   *db_txn;
+    char     *db_filename;
+    FILE     *db_errlog;
+    db_table db_table[3];
+} DBD;
+
+/* Functions */
+extern DBD *dbif_init(const char *dbname);
+extern int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags);
+extern int dbif_open(DBD *dbd, struct db_param *dbp, int do_truncate);
+extern int dbif_close(DBD *dbd);
+
+extern int dbif_get(DBD *, const int, DBT *, DBT *, u_int32_t);
+extern int dbif_pget(DBD *, const int, DBT *, DBT *, DBT *, u_int32_t);
+extern int dbif_put(DBD *, const int, DBT *, DBT *, u_int32_t);
+extern int dbif_del(DBD *, const int, DBT *, u_int32_t);
 
-extern int dbif_count(const int, u_int32_t *);
+extern int dbif_count(DBD *, const int, u_int32_t *);
+extern int dbif_stamp(DBD *, void *, int);
+extern int dbif_copy_rootinfokey(DBD *srcdbd, DBD *destdbd);
+extern int dbif_txn_begin(DBD *);
+extern int dbif_txn_commit(DBD *);
+extern int dbif_txn_abort(DBD *);
+extern int dbif_txn_checkpoint(DBD *, u_int32_t, u_int32_t, u_int32_t);
 
-extern int dbif_txn_begin(void);
-extern int dbif_txn_commit(void);
-extern int dbif_txn_abort(void);
-extern int dbif_txn_checkpoint(u_int32_t, u_int32_t, u_int32_t);
+extern int dbif_dump(DBD *, int dumpindexes);
 
-extern int dbif_dump(int dumpindexes);
 #endif
index 4a3f42c80e32f535baca7e232b03deb488a85baa..0a3806f13429f293ecba123612d0f6eaab6c8576 100644 (file)
@@ -1,22 +1,11 @@
 /*
- * $Id: main.c,v 1.5 2009-04-28 13:01:24 franklahm Exp $
+ * $Id: main.c,v 1.6 2009-05-06 11:54:24 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 */
@@ -57,7 +46,9 @@
    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)
+#define DBOPTIONS (DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN | DB_RECOVER)
+
+static DBD *dbd;
 
 static int exit_sig = 0;
 
@@ -147,28 +138,28 @@ static int loop(struct db_param *dbp)
                 ret = 1;
                 break;
             case CNID_DBD_OP_ADD:
-                ret = dbd_add(&rqst, &rply);
+                ret = dbd_add(dbd, &rqst, &rply);
                 break;
             case CNID_DBD_OP_GET:
-                ret = dbd_get(&rqst, &rply);
+                ret = dbd_get(dbd, &rqst, &rply);
                 break;
             case CNID_DBD_OP_RESOLVE:
-                ret = dbd_resolve(&rqst, &rply);
+                ret = dbd_resolve(dbd, &rqst, &rply);
                 break;
             case CNID_DBD_OP_LOOKUP:
-                ret = dbd_lookup(&rqst, &rply);
+                ret = dbd_lookup(dbd, &rqst, &rply);
                 break;
             case CNID_DBD_OP_UPDATE:
-                ret = dbd_update(&rqst, &rply);
+                ret = dbd_update(dbd, &rqst, &rply);
                 break;
             case CNID_DBD_OP_DELETE:
-                ret = dbd_delete(&rqst, &rply);
+                ret = dbd_delete(dbd, &rqst, &rply);
                 break;
             case CNID_DBD_OP_GETSTAMP:
-                ret = dbd_getstamp(&rqst, &rply);
+                ret = dbd_getstamp(dbd, &rqst, &rply);
                 break;
             case CNID_DBD_OP_REBUILD_ADD:
-                ret = dbd_rebuild_add(&rqst, &rply);
+                ret = dbd_rebuild_add(dbd, &rqst, &rply);
                 break;
             default:
                 LOG(log_error, logtype_cnid, "loop: unknown op %d", rqst.op);
@@ -177,15 +168,15 @@ static int loop(struct db_param *dbp)
             }
             
             if ((cret = comm_snd(&rply)) < 0 || ret < 0) {
-                dbif_txn_abort();
+                dbif_txn_abort(dbd);
                 return -1;
             }
             
             if (ret == 0 || cret == 0) {
-                if (dbif_txn_abort() < 0)
+                if (dbif_txn_abort(dbd) < 0)
                     return -1;
             } else {
-                ret = dbif_txn_commit();
+                ret = dbif_txn_commit(dbd);
                 if (  ret < 0)
                     return -1;
                 else if ( ret > 0 )
@@ -200,7 +191,7 @@ static int loop(struct db_param *dbp)
         */
         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)
+            if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0)
                 return -1;
             count = 0;
             time_next_flush = now + dbp->flush_interval;
@@ -216,7 +207,7 @@ static int loop(struct db_param *dbp)
         */
         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)
+            if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0)
                 return -1;
             count = 0;
         }
@@ -345,35 +336,38 @@ int main(int argc, char *argv[])
        only shut down after one second of inactivity. */
     block_sigs_onoff(1);
 
-    if ((dbp = db_param_read(dir, DBD)) == NULL)
+    if ((dbp = db_param_read(dir, CNID_DBD)) == NULL)
         exit(1);
     LOG(log_maxdebug, logtype_cnid, "Finished parsing db_param config file");
 
-    if (dbif_env_init(dbp, DBOPTIONS) < 0)
+    if (NULL == (dbd = dbif_init("cnid2.db")))
+        exit(2);
+
+    if (dbif_env_open(dbd, dbp, DBOPTIONS) < 0)
         exit(2); /* FIXME: same exit code as failure for dbif_open() */
     LOG(log_debug, logtype_cnid, "Finished initializing BerkeleyDB environment");
 
-    if (dbif_open(dbp, 0) < 0) {
-        dbif_close();
+    if (dbif_open(dbd, dbp, 0) < 0) {
+        dbif_close(dbd);
         exit(2);
     }
     LOG(log_debug, logtype_cnid, "Finished opening BerkeleyDB databases");
 
-    if (dbd_stamp() < 0) {
-        dbif_close();
+    if (dbd_stamp(dbd) < 0) {
+        dbif_close(dbd);
         exit(5);
     }
     LOG(log_maxdebug, logtype_cnid, "Finished checking database stamp");
 
     if (comm_init(dbp, ctrlfd, clntfd) < 0) {
-        dbif_close();
+        dbif_close(dbd);
         exit(3);
     }
 
     if (loop(dbp) < 0)
         err++;
 
-    if (dbif_close() < 0)
+    if (dbif_close(dbd) < 0)
         err++;
 
     free_lock(lockfd);