Rocco Rutte:
authorpdmef <pdmef@e385b8ad-14ed-0310-8656-cc95a2468c6d>
Sat, 14 May 2005 17:07:02 +0000 (17:07 +0000)
committerpdmef <pdmef@e385b8ad-14ed-0310-8656-cc95a2468c6d>
Sat, 14 May 2005 17:07:02 +0000 (17:07 +0000)
include qdbm support

git-svn-id: svn://svn.berlios.de/mutt-ng/trunk@291 e385b8ad-14ed-0310-8656-cc95a2468c6d

ChangeLog.mutt-ng
UPGRADING
configure.in
hcache.c
init.h
mutt.h

index 734f1b5..5854f3a 100644 (file)
@@ -1,5 +1,9 @@
 Changes specific to mutt-ng:
 
+2005-05-14:
+  * header caching update: support for qdbm (which supports compressed
+    database files) has been added
+
 2005-04-18:
   * sidebar updates: eventually counting can be disabled and
     $sidebar_newmail_only works way better
index 5122cc0..015a92b 100644 (file)
--- a/UPGRADING
+++ b/UPGRADING
@@ -10,6 +10,14 @@ This document is not the place for verbose documentation; it only offers
 the necessary keywords to look them up in the manual, ChangeLog or other
 sources of information.
 
+2005-05-14:
+
+  New Configuration Variables:
+    - $header_cache_compress - compress header cache database with qdbm
+      when switching to qdbm, please make sure to _first_ _completely_
+      remove the old header cache (files) as you need to start off from
+      scratch; compressed qdbm require much less space (only ~1/5)
+
 2005-04-18:
 
   New Configuration Variables:
index aad23c2..84fceb3 100644 (file)
@@ -825,10 +825,34 @@ AC_ARG_ENABLE(hcache, AC_HELP_STRING([--enable-hcache], [Enable header caching])
     OLDLIBS="$LIBS"
 
     need_md5="yes"
+
+    ac_prefer_qdbm=yes
+    AC_ARG_WITH(qdbm, AC_HELP_STRING([--without-qdbm], [Don't use qdbm even if it is available]),
+        ac_prefer_qdbm=$withval)
+    if test x$ac_prefer_qdbm != xno; then
+        ac_cv_vlopen=no
+        QDBM_DIRS="$mutt_cv_prefix /usr/local /usr"
+        AC_MSG_CHECKING([for vlopen])
+        for d in $QDBM_DIRS; do
+          if test x$ac_cv_vlopen = xno && test -d "$d/include" && test -d "$d/lib"; then
+            QDBM_INC="-I$d/include"
+            QDBM_LIB="-L$d/lib"
+            CPPFLAGS="$OLDCPPFLAGS $QDBM_INC"
+            LIBS="$OLDLIBS $QDBM_LIB -lqdbm"
+            AC_TRY_LINK([#include <villa.h>],[vlopen(0,0,0);],[ac_cv_vlopen=yes])
+          fi
+        done
+        if test x$ac_cv_vlopen = xyes; then
+          AC_MSG_RESULT(yes)
+        else
+          AC_MSG_RESULT(no)
+        fi
+    fi
+
     ac_prefer_gdbm=yes
     AC_ARG_WITH(gdbm, AC_HELP_STRING([--without-gdbm], [Don't use gdbm even if it is available]),
         ac_prefer_gdbm=$withval)
-    if test x$ac_prefer_gdbm != xno; then
+    if test x$ac_prefer_gdbm != xno -a x$ac_cv_vlopen != xyes; then
         ac_cv_gdbmopen=no
         GDBM_DIRS="$mutt_cv_prefix /usr/local /usr"
         AC_MSG_CHECKING([for gdbm_open])
@@ -851,7 +875,7 @@ AC_ARG_ENABLE(hcache, AC_HELP_STRING([--enable-hcache], [Enable header caching])
     ac_bdb_prefix=yes
     AC_ARG_WITH(bdb, AC_HELP_STRING([--with-bdb[=DIR]], [Use BerkeleyDB4 if gdbm is not available ]),
         ac_bdb_prefix=$withval)
-    if test x$ac_bdb_prefix != xno -a x$ac_cv_gdbmopen != xyes; then
+    if test x$ac_bdb_prefix != xno -a x$ac_cv_gdbmopen != xyes -a x$ac_cv_vlopen != xyes; then
         test x$ac_bdb_prefix = xyes && ac_bdb_prefix="$mutt_cv_prefix /opt/csw/bdb4 /opt /usr/local /usr"
         for d in $ac_bdb_prefix; do
             bdbpfx="$bdbpfx $d"
@@ -897,7 +921,11 @@ AC_ARG_ENABLE(hcache, AC_HELP_STRING([--enable-hcache], [Enable header caching])
         fi
     fi
 
-    if test x$ac_cv_gdbmopen = xyes; then
+    if test x$ac_cv_vlopen = xyes; then
+        CPPFLAGS="$OLDCPPFLAGS $QDBM_INC"
+        LIBS="$OLDLIBS $QDBM_LIB -lqdbm"
+        AC_DEFINE(HAVE_QDBM, 1, [QDBM Support])
+    elif test x$ac_cv_gdbmopen = xyes; then
         CPPFLAGS="$OLDCPPFLAGS $GDBM_INC"
         LIBS="$OLDLIBS $GDBM_LIB -lgdbm";
         AC_DEFINE(HAVE_GDBM, 1, [GDBM Support])
@@ -906,7 +934,7 @@ AC_ARG_ENABLE(hcache, AC_HELP_STRING([--enable-hcache], [Enable header caching])
         LIBS="$OLDLIBS -L$BDB_LIB_DIR -l$BDB_LIB"
         AC_DEFINE(HAVE_DB4, 1, [Sleepycat DB4 Support])
     else
-        AC_MSG_ERROR(You need Sleepycat DB4 or GDBM for --enable-hcache)
+        AC_MSG_ERROR(You need QDBM, GDBM or Sleepycat DB4 for --enable-hcache)
     fi
 fi])
 dnl -- end cache --
index 5d7ef9b..c6892ff 100644 (file)
--- a/hcache.c
+++ b/hcache.c
 
 #ifdef USE_HCACHE
 
-#if HAVE_GDBM
+#if HAVE_QDBM
+#include <depot.h>
+#include <cabin.h>
+#include <villa.h>
+#elif HAVE_GDBM
 #include <gdbm.h>
 #elif HAVE_DB4
 #include <db.h>
 #include "md5.h"
 
 #include "lib/mem.h"
+#include "lib/debug.h"
 
-#if HAVE_GDBM
+#if HAVE_QDBM
+static struct
+  header_cache {
+  VILLA *db;
+  char *folder;
+  unsigned int crc;
+} HEADER_CACHE;
+#elif HAVE_GDBM
 static struct
   header_cache {
   GDBM_FILE db;
@@ -600,7 +612,139 @@ HEADER *mutt_hcache_restore (const unsigned char *d, HEADER ** oh)
   return h;
 }
 
-#if HAVE_GDBM
+#if HAVE_QDBM
+void *
+mutt_hcache_open(const char *path, const char *folder)
+{
+  struct header_cache *h = safe_calloc(1, sizeof (HEADER_CACHE));
+  int    flags = 0;
+#if 0 /* FIXME */
+  int pagesize = atoi(HeaderCachePageSize) ? atoi(HeaderCachePageSize) : 16384;
+#endif
+  h->db = NULL;
+  h->folder = safe_strdup(folder);
+  h->crc = generate_crc32();
+
+  if (!path || path[0] == '\0')
+  {
+    FREE(&h->folder);
+    FREE(&h);
+    return NULL;
+  }
+
+  path = mutt_hcache_per_folder(path, folder);
+
+  if (option(OPTHCACHECOMPRESS))
+    flags = VL_OZCOMP;
+
+  h->db = vlopen(path, flags | VL_OWRITER | VL_OCREAT, VL_CMPLEX);
+  if (h->db)
+    return h;
+
+  /* if rw failed try ro */
+  h->db = vlopen(path, flags | VL_OREADER, VL_CMPLEX);
+  if (h->db)
+    return h;
+  else
+  {
+    FREE(&h->folder);
+    FREE(&h);
+
+    return NULL;
+  }
+}
+
+void
+mutt_hcache_close(void *db)
+{
+  struct header_cache *h = db;
+
+  if (!h)
+    return;
+
+  vlclose(h->db);
+  FREE(&h->folder);
+  FREE(&h);
+}
+
+void *
+mutt_hcache_fetch(void *db, const char *filename,
+                 size_t(*keylen) (const char *fn))
+{
+  struct header_cache *h = db;
+  char path[_POSIX_PATH_MAX];
+  int ksize;
+  char *data = NULL;
+
+  if (!h)
+    return NULL;
+
+  strncpy(path, h->folder, sizeof (path));
+  safe_strcat(path, sizeof (path), filename);
+
+  ksize = strlen(h->folder) + keylen(path + strlen(h->folder));
+
+  data = vlget(h->db, path, ksize, NULL);
+
+  if (! crc32_matches(data, h->crc))
+  {
+    if (data) { 
+      FREE(&data);
+    }
+    return NULL;
+  }
+
+  return data;
+}
+
+int
+mutt_hcache_store(void *db, const char *filename, HEADER * header,
+                 unsigned long uid_validity,
+                 size_t(*keylen) (const char *fn))
+{
+  struct header_cache *h = db;
+  char path[_POSIX_PATH_MAX];
+  int ret;
+  int ksize, dsize;
+  char *data = NULL;
+
+  if (!h)
+    return -1;
+
+  strncpy(path, h->folder, sizeof (path));
+  safe_strcat(path, sizeof (path), filename);
+
+  ksize = strlen(h->folder) + keylen(path + strlen(h->folder));
+
+  data  = mutt_hcache_dump(db, header, &dsize, uid_validity);
+
+  ret = vlput(h->db, path, ksize, data, dsize, VL_DOVER);
+
+  FREE(&data);
+
+  return ret;
+}
+
+int
+mutt_hcache_delete(void *db, const char *filename,
+                  size_t(*keylen) (const char *fn))
+{
+  struct header_cache *h = db;
+  char path[_POSIX_PATH_MAX];
+  int ksize;
+
+  if (!h)
+    return -1;
+
+  strncpy(path, h->folder, sizeof (path));
+  safe_strcat(path, sizeof (path), filename);
+
+  ksize = strlen(h->folder) + keylen(path + strlen(h->folder));
+
+  return vlout(h->db, path, ksize);
+}
+
+#elif HAVE_GDBM
 
 void *mutt_hcache_open (const char *path, const char *folder)
 {
diff --git a/init.h b/init.h
index 494616b..34601d3 100644 (file)
--- a/init.h
+++ b/init.h
@@ -1261,8 +1261,8 @@ struct option_t MuttVars[] = {
    ** .pp
    ** If $$header_cache points to a directory it will contain a header cache
    ** database  per folder. If $$header_cache points to a file that file will
-   ** be a single global header cache. By default it is \fIunset\fP and so no
-   ** header caching will be done.
+   ** be a single global header cache. By default it is \fIunset\fP so no
+   ** header caching will be used.
    */
   {"maildir_header_cache_verify", DT_BOOL, R_NONE, OPTHCACHEVERIFY, 1},
   /*
@@ -1285,9 +1285,18 @@ struct option_t MuttVars[] = {
    ** Too large
    ** or too small of a page size for the common header can waste
    ** space, memory effectiveness, or CPU time. The default should be more or
-   ** less the best you can get. For details google after Mutt-ng maildir header
+   ** less the best you can get. For details google for mutt header
    ** cache (first hit).
    */
+#if HAVE_QDBM
+  { "header_cache_compress", DT_BOOL, R_NONE, OPTHCACHECOMPRESS, 0 },
+  /*
+  ** .pp
+  ** If enabled the header cache will be compressed. So only one fifth of the usual
+  ** diskspace is used, but the uncompression can result in a slower open of the
+  ** cached folder.
+  */
+#endif /* HAVE_QDBM */
 #endif /* USE_HCACHE */
   {"maildir_trash", DT_BOOL, R_NONE, OPTMAILDIRTRASH, 0},
   /*
diff --git a/mutt.h b/mutt.h
index 39b1508..8018203 100644 (file)
--- a/mutt.h
+++ b/mutt.h
@@ -366,6 +366,9 @@ enum {
   OPTFORWQUOTE,
 #if USE_HCACHE
   OPTHCACHEVERIFY,
+#if HAVE_QDBM
+  OPTHCACHECOMPRESS,
+#endif /* HAVE_QDBM */
 #endif
   OPTHDRS,
   OPTHEADER,