Commit 046fb469 authored by Kevin J. McCarthy's avatar Kevin J. McCarthy

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.
parent ea9aee03
......@@ -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 --
......
......@@ -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>
......
......@@ -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
......@@ -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
......
......@@ -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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment