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:
 
 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
 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.
 
 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:
 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"
     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)
     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])
         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)
     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"
         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
 
         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])
         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
         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 --
     fi
 fi])
 dnl -- end cache --
index 5d7ef9b..c6892ff 100644 (file)
--- a/hcache.c
+++ b/hcache.c
 
 #ifdef USE_HCACHE
 
 
 #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 <gdbm.h>
 #elif HAVE_DB4
 #include <db.h>
 #include "md5.h"
 
 #include "lib/mem.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;
 static struct
   header_cache {
   GDBM_FILE db;
@@ -600,7 +612,139 @@ HEADER *mutt_hcache_restore (const unsigned char *d, HEADER ** oh)
   return h;
 }
 
   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)
 {
 
 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
    ** .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},
   /*
    */
   {"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
    ** 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).
    */
    ** 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},
   /*
 #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,
   OPTFORWQUOTE,
 #if USE_HCACHE
   OPTHCACHEVERIFY,
+#if HAVE_QDBM
+  OPTHCACHECOMPRESS,
+#endif /* HAVE_QDBM */
 #endif
   OPTHDRS,
   OPTHEADER,
 #endif
   OPTHDRS,
   OPTHEADER,