]> granicus.if.org Git - mutt/commitdiff
Add Kyoto Cabinet support to the header cache.
authorKevin McCarthy <kevin@8t8.us>
Wed, 8 Feb 2017 03:36:37 +0000 (19:36 -0800)
committerKevin McCarthy <kevin@8t8.us>
Wed, 8 Feb 2017 03:36:37 +0000 (19:36 -0800)
Retain the defaults as they are, although we might switch to Kyoto
Cabinet for the next major release.

configure.ac
doc/manual.xml.head
hcache.c
init.h
mutt.h

index c7fc41567071a9ea55a1b41ae153251096478a88..8905b72367b8f760a2f9be601b273375678716fd 100644 (file)
@@ -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 --
index 89c136494b4ee9796e638942e65cb55c308c5900..36e2bf00f16097fe7d36aeb729e6400542fc9d92 100644 (file)
@@ -8118,7 +8118,7 @@ per message.)
 Header caching can be enabled via the configure script and the
 <emphasis>--enable-hcache</emphasis> 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.
 </para>
 
 <para>
index 86c8a8290af5b6a9ff62add5d9484b2e3760b11c..6e13973267410596f2510bf4e755d2fa7a77449a 100644 (file)
--- a/hcache.c
+++ b/hcache.c
@@ -28,6 +28,8 @@
 #include <villa.h>
 #elif HAVE_TC
 #include <tcbdb.h>
+#elif HAVE_KC
+#include <kclangc.h>
 #elif HAVE_GDBM
 #include <gdbm.h>
 #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 2cffbc2ef8beca5566aeb5c6a15b57f0af85912c..cd6f7154eca48aac8b9353fe445502baf00da82a 100644 (file)
--- 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 2d5247806f5f1d15f5984f6db257437aa848f148..10d5ab6db332907130f852130a8bc33d6de1afff 100644 (file)
--- 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