From 180f5fa201372d21c505ac638892be3b34a70519 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 12 Jan 2004 00:52:14 +0000 Subject: [PATCH] sync uid database after every message. this is accompanied by a dbm -> db4 migration. patch by theodore, with some final polishing by me. --- configure.in | 24 ++------------------- src/isync.h | 9 ++------ src/maildir.c | 59 +++++++++++++++++++++++++++++++++------------------ src/sync.c | 21 ++++++++++++------ 4 files changed, 56 insertions(+), 57 deletions(-) diff --git a/configure.in b/configure.in index 50f7315..98fa22c 100644 --- a/configure.in +++ b/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 ], - [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 ], - [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) diff --git a/src/isync.h b/src/isync.h index 9955c53..0e1e771 100644 --- a/src/isync.h +++ b/src/isync.h @@ -26,12 +26,7 @@ #include -#if HAVE_LIBDB -# define DB_DBM_HSEARCH 1 -# include -#else -# include -#endif +#include #if HAVE_LIBSSL # include @@ -94,7 +89,7 @@ struct config /* struct representing local mailbox file */ struct mailbox { - DBM *db; + DB *db; char *path; message_t *msgs; int lockfd; diff --git a/src/maildir.c b/src/maildir.c index 8394af8..c509fe2 100644 --- a/src/maildir.c +++ b/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); diff --git a/src/sync.c b/src/sync.c index a417827..250ff09 100644 --- a/src/sync.c +++ b/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; }