From: Kevin McCarthy Date: Wed, 8 Feb 2017 03:36:37 +0000 (-0800) Subject: Add Kyoto Cabinet support to the header cache. X-Git-Tag: mutt-1-8-rel~23 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=046fb4690154f6d5bc515ec5fb058c668953f6be;p=mutt Add Kyoto Cabinet support to the header cache. Retain the defaults as they are, although we might switch to Kyoto Cabinet for the next major release. --- diff --git a/configure.ac b/configure.ac index c7fc4156..8905b723 100644 --- a/configure.ac +++ b/configure.ac @@ -882,6 +882,7 @@ AC_ARG_WITH(qdbm, AS_HELP_STRING([--without-qdbm],[Don't use qdbm even if it is AC_ARG_WITH(gdbm, AS_HELP_STRING([--without-gdbm],[Don't use gdbm even if it is available])) AC_ARG_WITH(bdb, AS_HELP_STRING([--with-bdb@<:@=DIR@:>@],[Use BerkeleyDB4 if gdbm is not available])) AC_ARG_WITH(lmdb, AS_HELP_STRING([--with-lmdb@<:@=DIR@:>@],[Use LMDB if gdbm is not available])) +AC_ARG_WITH(kyotocabinet, AS_HELP_STRING([--with-kyotocabinet@<:@=DIR@:>@],[Use kyotocabinet if gdbm is not available])) db_found=no if test x$enable_hcache = xyes @@ -935,6 +936,15 @@ then db_requested=lmdb fi fi + if test -n "$with_kyotocabinet" && test "$with_kyotocabinet" != "no" + then + if test "$db_requested" != "auto" + then + AC_MSG_ERROR([more than one header cache engine requested.]) + else + db_requested=kc + fi + fi dnl -- Tokyo Cabinet -- if test "$with_tokyocabinet" != "no" \ @@ -1107,9 +1117,32 @@ then fi fi + dnl -- Kyoto Cabinet -- + if test x$with_kyotocabinet != xno && test $db_found = no \ + && test "$db_requested" = auto -o "$db_requested" = kc + then + if test -n "$with_kyotocabinet" && test "$with_kyotocabinet" != "yes" + then + CPPFLAGS="$CPPFLAGS -I$with_kyotocabinet/include" + LDFLAGS="$LDFLAGS -L$with_kyotocabinet/lib" + fi + + AC_CHECK_HEADER(kclangc.h, + AC_CHECK_LIB(kyotocabinet, kcdbopen, + [MUTTLIBS="$MUTTLIBS -lkyotocabinet" + AC_DEFINE(HAVE_KC, 1, [Kyoto Cabinet Support]) + db_found=kc], + [CPPFLAGS="$OLDCPPFLAGS" + LDFLAGS="$OLDLDFLAGS"])) + if test "$db_requested" != auto && test "$db_found" != "$db_requested" + then + AC_MSG_ERROR([Kyoto Cabinet could not be used. Check config.log for details.]) + fi + fi + if test $db_found = no then - AC_MSG_ERROR([You need Tokyo Cabinet, QDBM, GDBM or Berkeley DB4 for hcache]) + AC_MSG_ERROR([You need Tokyo Cabinet, Kyoto Cabinet, QDBM, GDBM, LMDB or Berkeley DB4 for hcache]) fi fi dnl -- end cache -- diff --git a/doc/manual.xml.head b/doc/manual.xml.head index 89c13649..36e2bf00 100644 --- a/doc/manual.xml.head +++ b/doc/manual.xml.head @@ -8118,7 +8118,7 @@ per message.) Header caching can be enabled via the configure script and the --enable-hcache option. It's not turned on by default because external database libraries are required: one of -tokyocabinet, qdbm, gdbm or bdb must be present. +tokyocabinet, kyotocabinet, lmdb, qdbm, gdbm or bdb must be present. diff --git a/hcache.c b/hcache.c index 86c8a829..6e139732 100644 --- a/hcache.c +++ b/hcache.c @@ -28,6 +28,8 @@ #include #elif HAVE_TC #include +#elif HAVE_KC +#include #elif HAVE_GDBM #include #elif HAVE_DB4 @@ -69,6 +71,13 @@ struct header_cache char *folder; unsigned int crc; }; +#elif HAVE_KC +struct header_cache +{ + KCDB *db; + char *folder; + unsigned int crc; +}; #elif HAVE_GDBM struct header_cache { @@ -804,6 +813,9 @@ mutt_hcache_fetch_raw (header_cache_t *h, const char *filename, #elif HAVE_TC void *data; int sp; +#elif HAVE_KC + void *data; + size_t sp; #elif HAVE_GDBM datum key; datum data; @@ -843,6 +855,10 @@ mutt_hcache_fetch_raw (header_cache_t *h, const char *filename, #elif HAVE_TC data = tcbdbget(h->db, path, ksize, &sp); + return data; +#elif HAVE_KC + data = kcdbget(h->db, path, ksize, &sp); + return data; #elif HAVE_GDBM key.dptr = path; @@ -939,6 +955,8 @@ mutt_hcache_store_raw (header_cache_t* h, const char* filename, void* data, return vlput(h->db, path, ksize, data, dlen, VL_DOVER); #elif HAVE_TC return tcbdbput(h->db, path, ksize, data, dlen); +#elif HAVE_KC + return kcdbset(h->db, path, ksize, data, dlen); #elif HAVE_GDBM key.dptr = path; key.dsize = ksize; @@ -1091,6 +1109,67 @@ mutt_hcache_delete(header_cache_t *h, const char *filename, return tcbdbout(h->db, path, ksize); } +#elif HAVE_KC +static int +hcache_open_kc (struct header_cache* h, const char* path) +{ + char fullpath[_POSIX_PATH_MAX]; + + /* Kyoto cabinet options are discussed at + * http://fallabs.com/kyotocabinet/spex.html + * - rcomp is by default lex, so there is no need to specify it. + * - opts=l enables linear collision chaining as opposed to using a binary tree. + * this isn't suggested unless you are tuning the number of buckets. + * - opts=c enables compression + */ + snprintf (fullpath, sizeof(fullpath), "%s#type=kct%s", path, + option(OPTHCACHECOMPRESS) ? "#opts=c" : ""); + h->db = kcdbnew(); + if (!h->db) + return -1; + if (kcdbopen(h->db, fullpath, KCOWRITER | KCOCREATE)) + return 0; + else + { + dprint (2, (debugfile, "kcdbopen failed for %s: %s (ecode %d)\n", fullpath, + kcdbemsg (h->db), kcdbecode (h->db))); + kcdbdel(h->db); + return -1; + } +} + +void +mutt_hcache_close(header_cache_t *h) +{ + if (!h) + return; + + if (!kcdbclose(h->db)) + dprint (2, (debugfile, "kcdbclose failed for %s: %s (ecode %d)\n", h->folder, + kcdbemsg (h->db), kcdbecode (h->db))); + kcdbdel(h->db); + FREE(&h->folder); + FREE(&h); +} + +int +mutt_hcache_delete(header_cache_t *h, const char *filename, + size_t(*keylen) (const char *fn)) +{ + 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 kcdbremove(h->db, path, ksize); +} + #elif HAVE_GDBM static int hcache_open_gdbm (struct header_cache* h, const char* path) @@ -1373,6 +1452,8 @@ mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer) hcache_open = hcache_open_qdbm; #elif HAVE_TC hcache_open= hcache_open_tc; +#elif HAVE_KC + hcache_open= hcache_open_kc; #elif HAVE_GDBM hcache_open = hcache_open_gdbm; #elif HAVE_DB4 @@ -1475,4 +1556,11 @@ const char *mutt_hcache_backend (void) { return "tokyocabinet " _TC_VERSION; } +#elif HAVE_KC +const char *mutt_hcache_backend (void) +{ + static char backend[SHORT_STRING]; + snprintf(backend, sizeof(backend), "kyotocabinet %s", KCVERSION); + return backend; +} #endif diff --git a/init.h b/init.h index 2cffbc2e..cd6f7154 100644 --- a/init.h +++ b/init.h @@ -984,12 +984,12 @@ struct option_t MuttVars[] = { ** Header caching can greatly improve speed when opening POP, IMAP ** MH or Maildir folders, see ``$caching'' for details. */ -#if defined(HAVE_QDBM) || defined(HAVE_TC) +#if defined(HAVE_QDBM) || defined(HAVE_TC) || defined(HAVE_KC) { "header_cache_compress", DT_BOOL, R_NONE, OPTHCACHECOMPRESS, 1 }, /* ** .pp - ** When mutt is compiled with qdbm or tokyocabinet as header cache backend, - ** this option determines whether the database will be compressed. + ** When mutt is compiled with qdbm, tokyocabinet, or kyotocabinet as header + ** cache backend, this option determines whether the database will be compressed. ** Compression results in database files roughly being one fifth ** of the usual diskspace, but the decompression can result in a ** slower opening of cached folder(s) which in general is still diff --git a/mutt.h b/mutt.h index 2d524780..10d5ab6d 100644 --- a/mutt.h +++ b/mutt.h @@ -360,7 +360,7 @@ enum OPTFORWQUOTE, #ifdef USE_HCACHE OPTHCACHEVERIFY, -#if defined(HAVE_QDBM) || defined(HAVE_TC) +#if defined(HAVE_QDBM) || defined(HAVE_TC) || defined(HAVE_KC) OPTHCACHECOMPRESS, #endif /* HAVE_QDBM */ #endif