From: Thomas Glanzmann Date: Wed, 21 Sep 2005 06:04:36 +0000 (+0000) Subject: QDBM support for the header cache. X-Git-Tag: mutt-1-5-12-rel~351 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=20fcbe686cad1d364c948599f415b4a5925e2293;p=mutt QDBM support for the header cache. --- diff --git a/configure.in b/configure.in index 67c708e9..a314297a 100644 --- a/configure.in +++ b/configure.in @@ -738,10 +738,23 @@ 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 + CPPFLAGS="$OLDCPPFLAGS" + LIBS="$OLDLIBS -lqdbm"; + AC_CACHE_CHECK(for vlopen, ac_cv_vlopen,[ + ac_cv_vlopen=no + AC_TRY_LINK([#include ],[vlopen(0,0,0);],[ac_cv_vlopen=yes]) + ]) + 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 CPPFLAGS="$OLDCPPFLAGS" LIBS="$OLDLIBS -lgdbm"; AC_CACHE_CHECK(for gdbm_open, ac_cv_gdbmopen,[ @@ -753,7 +766,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" @@ -799,7 +812,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" + LIBS="$OLDLIBS -lqdbm"; + AC_DEFINE(HAVE_QDBM, 1, [QDBM Support]) + elif test x$ac_cv_gdbmopen = xyes; then CPPFLAGS="$OLDCPPFLAGS" LIBS="$OLDLIBS -lgdbm"; AC_DEFINE(HAVE_GDBM, 1, [GDBM Support]) diff --git a/hcache.c b/hcache.c index f35aa607..440869ef 100644 --- a/hcache.c +++ b/hcache.c @@ -22,7 +22,11 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ -#if HAVE_GDBM +#if HAVE_QDBM +#include +#include +#include +#elif HAVE_GDBM #include #elif HAVE_DB4 #include @@ -42,7 +46,14 @@ #include "lib.h" #include "md5.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; @@ -615,7 +626,133 @@ 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_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)) + { + 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 abb43bd6..3d9b9e2b 100644 --- a/init.h +++ b/init.h @@ -1077,6 +1077,15 @@ struct option_t MuttVars[] = { ** or 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 09c7e320..205afdbe 100644 --- a/mutt.h +++ b/mutt.h @@ -353,6 +353,9 @@ enum OPTFORWQUOTE, #if USE_HCACHE OPTHCACHEVERIFY, +#if HAVE_QDBM + OPTHCACHECOMPRESS, +#endif /* HAVE_QDBM */ #endif OPTHDRS, OPTHEADER,