Procházet zdrojové kódy

sync uid database after every message. this is accompanied by a dbm ->
db4 migration. patch by theodore, with some final polishing by me.

Oswald Buddenhagen před 21 roky
rodič
revize
180f5fa201
4 změnil soubory, kde provedl 56 přidání a 57 odebrání
  1. 2 22
      configure.in
  2. 2 7
      src/isync.h
  3. 38 21
      src/maildir.c
  4. 14 7
      src/sync.c

+ 2 - 22
configure.in

@@ -33,28 +33,8 @@ if test "x$ob_cv_with_ssl" != xno; then
       ])
 fi
 
-AC_CACHE_CHECK(for dbm_open, ac_cv_dbmopen,
-	[ac_cv_dbmopen=no
-	AC_TRY_LINK([#include <ndbm.h>],
-		[dbm_open(0,0,0);],[ac_cv_dbmopen=yes])])
-if test $ac_cv_dbmopen = no; then
-	AC_CACHE_CHECK([for dbm_open in -ldb], ac_cv_libdb,
-		[save_LIBS="$LIBS"
-		LIBS="$LIBS -ldb"
-		ac_cv_libdb=no
-		AC_TRY_LINK([#define DB_DBM_HSEARCH 1
-#include <db.h>],
-			[dbm_open(0,0,0);],
-			[ac_cv_libdb=yes])
-		LIBS="$save_LIBS"])
-
-	if test $ac_cv_libdb = yes; then
-		LIBS="$LIBS -ldb"
-		AC_DEFINE(HAVE_LIBDB, 1, [Define if you have libdb])
-	else
-		AC_MSG_ERROR([Could not find dbm_open(), you must install libdb])
-	fi
-fi
+AC_CHECK_LIB(db, db_create, [LIBS="$LIBS -ldb"], [AC_MSG_ERROR([Berkley DB not found.])])
+AC_CHECK_HEADER(db.h, , [AC_MSG_ERROR([Berkley DB header file not found.])])
 
 AC_OUTPUT(Makefile src/Makefile debian/Makefile isync.spec)
 

+ 2 - 7
src/isync.h

@@ -26,12 +26,7 @@
 
 #include <sys/types.h>
 
-#if HAVE_LIBDB
-# define DB_DBM_HSEARCH 1
-# include <db.h>
-#else
-# include <ndbm.h>
-#endif
+#include <db.h>
 
 #if HAVE_LIBSSL
 # include <openssl/ssl.h>
@@ -94,7 +89,7 @@ struct config
 /* struct representing local mailbox file */
 struct mailbox
 {
-    DBM *db;
+    DB *db;
     char *path;
     message_t *msgs;
     int lockfd;

+ 38 - 21
src/maildir.c

@@ -125,8 +125,8 @@ maildir_open (const char *path, int flags)
     int count = 0;
     struct stat sb;
     const char *subdirs[] = { "cur", "new", "tmp" };
-    int i;
-    datum key;
+    int i, ret;
+    DBT key, value;
 
     m = calloc (1, sizeof (mailbox_t));
     m->lockfd = -1;
@@ -200,8 +200,18 @@ maildir_open (const char *path, int flags)
     if (read_uid (m->path, "isyncmaxuid", &m->maxuid) == -1)
 	goto err;
 
-    snprintf (buf, sizeof (buf), "%s/isyncuidmap", m->path);
-    m->db = dbm_open (buf, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+    snprintf (buf, sizeof (buf), "%s/isyncuidmap.db", m->path);
+    if (db_create (&m->db, 0, 0)) {
+	    fputs ("dbcreate failed\n", stderr);
+	    goto err;
+    }
+    if ((ret = m->db->set_pagesize (m->db, 4096)) != 0 ||
+	(ret = m->db->set_h_ffactor (m->db, 40)) != 0 ||
+	(ret = m->db->set_h_nelem (m->db, 1)) != 0) {
+	    fputs ("Error configuring database\n", stderr);
+	    goto err;
+    }
+    m->db->open (m->db, buf, 0, DB_HASH, DB_CREATE, S_IRUSR | S_IWUSR);
     if (m->db == NULL)
     {
 	fputs ("ERROR: unable to open UID db\n", stderr);
@@ -237,19 +247,24 @@ maildir_open (const char *path, int flags)
 	    /* determine the UID for this message.  The basename (sans
 	     * flags) is used as the key in the db
 	     */
-	    key.dptr = p->file;
-	    s = strchr (key.dptr, ':');
-	    key.dsize = s ? (size_t) (s - key.dptr) : strlen (key.dptr);
-	    key = dbm_fetch (m->db, key);
-	    if (key.dptr)
-	    {
-		p->uid = *(int *) key.dptr;
+	    memset (&key, 0, sizeof(key));
+	    memset (&value, 0, sizeof(value));
+	    key.data = p->file;
+	    s = strchr (p->file, ':');
+	    key.size = s ? (size_t) (s - p->file) : strlen (p->file);
+	    ret = m->db->get (m->db, 0, &key, &value, 0);
+	    if (ret == DB_NOTFOUND) {
+		/* Every locally generated message triggers this ... */
+		/*printf ("Warning, no UID for message %.*s\n",
+			key.size, p->file);*/
+	    } else if (ret) {
+		fprintf (stderr, "Unexpected error (%d) from db_get(%.*s)\n", 
+			 ret, key.size, p->file);
+	    } else if (ret == 0) {
+		p->uid = *((int *) value.data);
 		if (p->uid > m->maxuid)
 		    m->maxuid = p->uid;
 	    }
-	    else /* XXX remove. every locally generated message triggers this */
-		puts ("Warning, no UID for message");
-
 	    if (s)
 		parse_info (p, s + 1);
 	    if (p->flags & D_DELETED)
@@ -262,7 +277,7 @@ maildir_open (const char *path, int flags)
 
   err:
     if (m->db)
-	dbm_close (m->db);
+	m->db->close (m->db, 0);
     dotlock_unlock (&m->lockfd);
     free (m->path);
     free (m);
@@ -278,7 +293,7 @@ maildir_expunge (mailbox_t * mbox, int dead)
     message_t **cur = &mbox->msgs;
     message_t *tmp;
     char *s;
-    datum key;
+    DBT key;
     char path[_POSIX_PATH_MAX];
 
     while (*cur)
@@ -292,10 +307,12 @@ maildir_expunge (mailbox_t * mbox, int dead)
 	    if (unlink (path))
 		perror (path);
 	    /* remove the message from the UID map */
-	    key.dptr = tmp->file;
-	    s = strchr (key.dptr, ':');
-	    key.dsize = s ? (size_t) (s - key.dptr) : strlen (key.dptr);
-	    dbm_delete (mbox->db, key);
+	    memset (&key, 0, sizeof(key));
+	    key.data = tmp->file;
+	    s = strchr (tmp->file, ':');
+	    key.size = s ? (size_t) (s - tmp->file) : strlen (key.data);
+	    mbox->db->del (mbox->db, 0, &key, 0);
+	    mbox->db->sync (mbox->db, 0);
 	    *cur = (*cur)->next;
 	    free (tmp->file);
 	    free (tmp);
@@ -386,7 +403,7 @@ void
 maildir_close (mailbox_t * mbox)
 {
     if (mbox->db)
-	dbm_close (mbox->db);
+	mbox->db->close (mbox->db, 0);
 
     /* release the mutex on the mailbox */
     dotlock_unlock (&mbox->lockfd);

+ 14 - 7
src/sync.c

@@ -46,17 +46,24 @@ find_msg (message_t * list, unsigned int uid)
 }
 
 static int
-set_uid (DBM * db, const char *f, unsigned int uid)
+set_uid (DB * db, const char *f, unsigned int uid)
 {
     char *s;
-    datum key, val;
+    DBT key, val;
+    int ret;
 
-    key.dptr = (void *) f;
+    memset (&key, 0, sizeof(key));
+    memset (&val, 0, sizeof(val));
+    key.data = (void *) f;
     s = strchr (f, ':');
-    key.dsize = s ? (size_t) (s - key.dptr) : strlen (f);
-    val.dptr = (void *) &uid;
-    val.dsize = sizeof (uid);
-    dbm_store (db, key, val, DBM_REPLACE);
+    key.size = s ? (size_t) (s - f) : strlen (f);
+    val.data = (void *) &uid;
+    val.size = sizeof (uid);
+    ret = db->put (db, 0, &key, &val, 0);
+    if (ret < 0)
+	fprintf (stderr, "Unexpected error (%d) from db_put(%.*s, %d)\n", 
+		 ret, key.size, f, uid);
+    db->sync(db, 0);
     return 0;
 }