diff options
Diffstat (limited to 'mail/mutt-devel/files/extra-patch-maildir-header-cache')
-rw-r--r-- | mail/mutt-devel/files/extra-patch-maildir-header-cache | 703 |
1 files changed, 557 insertions, 146 deletions
diff --git a/mail/mutt-devel/files/extra-patch-maildir-header-cache b/mail/mutt-devel/files/extra-patch-maildir-header-cache index 170d52e44c10..807b3f21b466 100644 --- a/mail/mutt-devel/files/extra-patch-maildir-header-cache +++ b/mail/mutt-devel/files/extra-patch-maildir-header-cache @@ -1,20 +1,21 @@ ---- Makefile.am.orig Fri Mar 5 15:34:57 2004 -+++ Makefile.am Fri Mar 5 15:35:55 2004 +diff -Nru a/Makefile.am b/Makefile.am +--- a/Makefile.am 2004-08-18 10:08:12 +02:00 ++++ b/Makefile.am 2004-08-18 10:08:12 +02:00 @@ -20,2 +20,3 @@ mutt_SOURCES = $(BUILT_SOURCES) \ + hcache.c \ addrbook.c alias.c attach.c base64.c browser.c buffy.c color.c \ diff -Nru a/configure.in b/configure.in ---- configure.in.orig Sat Jun 12 09:49:17 2004 -+++ configure.in Sat Jun 12 09:50:18 2004 -@@ -773,6 +773,80 @@ +--- a/configure.in 2004-08-18 10:08:12 +02:00 ++++ b/configure.in 2004-08-18 10:08:12 +02:00 +@@ -768,6 +768,80 @@ fi]) +dnl -- start cache -- -+AC_ARG_ENABLE(hcache, [ --enable-hcache Enable header caching for Maildir folders], ++AC_ARG_ENABLE(hcache, [ --enable-hcache Enable header caching], +[if test x$enableval = xyes; then -+ AC_DEFINE(USE_HCACHE, 1, [Enable header caching for Maildir style mailboxes]) ++ AC_DEFINE(USE_HCACHE, 1, [Enable header caching]) + + OLDCPPFLAGS="$CPPFLAGS" + OLDLIBS="$LIBS" @@ -44,17 +45,17 @@ diff -Nru a/configure.in b/configure.in + for v in `echo $BDB_VERSIONS`; do + CPPFLAGS="$OLDCPPFLAGS -I$BDB_INCLUDE_DIR" + LIBS="$OLDLIBS -L$BDB_LIB_DIR -l$v" -+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ -+ #include <stdlib.h> ++ AC_TRY_LINK([ ++ #include <stdlib.h> + #include <db.h> -+ ]],[[ ++ ],[ + DB *db = NULL; + db->open(db,NULL,NULL,NULL,0,0,0); -+ ]])],[ ++ ],[ + ac_cv_dbcreate=yes + BDB_LIB="$v" + break -+ ]) ++ ]) + done + test x$BDB_LIB != x && break + done @@ -89,25 +90,26 @@ diff -Nru a/configure.in b/configure.in AC_SUBST(MUTT_LIB_OBJECTS) AC_SUBST(LIBIMAP) diff -Nru a/globals.h b/globals.h ---- globals.h 2004-06-10 14:03:44 +02:00 -+++ globals.h 2004-06-10 14:03:44 +02:00 +--- a/globals.h 2004-08-18 10:08:12 +02:00 ++++ b/globals.h 2004-08-18 10:08:12 +02:00 @@ -63,6 +63,10 @@ WHERE char *Locale; WHERE char *MailcapPath; WHERE char *Maildir; +#if USE_HCACHE -+WHERE char *MaildirCache; -+WHERE short MaildirCachePageSize; ++WHERE char *HeaderCache; ++WHERE short HeaderCachePageSize; +#endif WHERE char *MhFlagged; WHERE char *MhReplied; WHERE char *MhUnseen; diff -Nru a/hcache.c b/hcache.c ---- hcache.c.orig Sat Jun 12 09:52:31 2004 -+++ hcache.c Sat Jun 12 09:52:56 2004 -@@ -0,0 +1,676 @@ +--- /dev/null Wed Dec 31 16:00:00 196900 ++++ b/hcache.c 2004-08-18 10:08:12 +02:00 +@@ -0,0 +1,794 @@ +/* + * Copyright (C) 2004 Thomas Glanzmann <sithglan@stud.uni-erlangen.de> ++ * Copyright (C) 2004 Tobias Werth <sitowert@stud.uni-erlangen.de> + * Copyright (C) 2004 Brian Fundakowski Feldman <green@FreeBSD.org> + * + * This program is free software; you can redistribute it and/or modify @@ -138,10 +140,39 @@ diff -Nru a/hcache.c b/hcache.c +#include <errno.h> +#include <fcntl.h> +#include "mutt.h" ++#ifdef USE_IMAP ++#include "message.h" ++#endif +#include "mime.h" +#include "mx.h" +#include "lib.h" + ++#if HAVE_GDBM ++static struct ++header_cache ++{ ++ GDBM_FILE db; ++ char *folder; ++ unsigned int crc; ++} HEADER_CACHE; ++#elif HAVE_DB4 ++static struct ++header_cache ++{ ++ DB_ENV *env; ++ DB *db; ++ unsigned int crc; ++ int fd; ++ char lockfile[_POSIX_PATH_MAX]; ++} HEADER_CACHE; ++#endif ++ ++typedef union ++{ ++ struct timeval timeval; ++ unsigned long long uid_validity; ++} validate; ++ +static unsigned char * +dump_int(unsigned int i, unsigned char *d, int *off) +{ @@ -170,7 +201,24 @@ diff -Nru a/hcache.c b/hcache.c + return d; + } + -+ size = strlen(c) + 1; ++ size = mutt_strlen(c) + 1; ++ d = dump_int(size, d, off); ++ safe_realloc(&d, *off + size); ++ memcpy(d + *off, c, size); ++ *off += size; ++ ++ return d; ++} ++ ++static unsigned char * ++dump_char_size(char *c, unsigned char *d, int *off, ssize_t size) ++{ ++ if (c == NULL) { ++ size = 0; ++ d = dump_int(size, d, off); ++ return d; ++ } ++ + d = dump_int(size, d, off); + safe_realloc(&d, *off + size); + memcpy(d + *off, c, size); @@ -195,14 +243,6 @@ diff -Nru a/hcache.c b/hcache.c + *off += size; +} + -+static void -+skip_char(const unsigned char *d, int *off) -+{ -+ unsigned int size; -+ restore_int(&size, d, off); -+ *off += size; -+} -+ +static unsigned char * +dump_address(ADDRESS *a, unsigned char *d, int *off) +{ @@ -247,7 +287,6 @@ diff -Nru a/hcache.c b/hcache.c + } + + *a = NULL; -+ return; +} + +static unsigned char * @@ -284,7 +323,43 @@ diff -Nru a/hcache.c b/hcache.c + } + + *l = NULL; -+ return; ++} ++ ++static unsigned char * ++dump_buffer(BUFFER *b, unsigned char *d, int *off) ++{ ++ if (! b) { ++ d = dump_int(0, d, off); ++ return d; ++ } else { ++ d = dump_int(1, d, off); ++ } ++ ++ d = dump_char_size(b->data, d, off, b->dsize + 1); ++ d = dump_int(b->dptr - b->data, d, off); ++ d = dump_int(b->dsize, d, off); ++ d = dump_int(b->destroy, d, off); ++ ++ return d; ++} ++ ++static void ++restore_buffer(BUFFER **b, const unsigned char *d, int *off) ++{ ++ unsigned int used; ++ unsigned int offset; ++ restore_int(&used, d, off); ++ if (! used) { ++ return; ++ } ++ ++ *b = safe_malloc(sizeof(BUFFER)); ++ ++ restore_char(& (*b)->data, d, off); ++ restore_int(& offset, d, off); ++ (*b)->dptr = (*b)->data + offset; ++ restore_int(& (*b)->dsize, d, off); ++ restore_int((unsigned int *) & (*b)->destroy, d, off); +} + +static unsigned char * @@ -323,7 +398,6 @@ diff -Nru a/hcache.c b/hcache.c + } + + *p = NULL; -+ return; +} + +static unsigned char * @@ -408,7 +482,7 @@ diff -Nru a/hcache.c b/hcache.c + restore_address(& e->mail_followup_to, d, off); + + restore_char(& e->subject, d, off); -+ restore_int(& real_subj_off, d, off); ++ restore_int((unsigned int *) (& real_subj_off), d, off); + if (0 <= real_subj_off) { + e->real_subj = e->subject + real_subj_off; + } else { @@ -424,42 +498,72 @@ diff -Nru a/hcache.c b/hcache.c + restore_list(& e->userhdrs, d, off); +} + ++static ++unsigned int crc32(unsigned int crc, unsigned char const *p, size_t len) ++{ ++ int i; ++ while (len--) { ++ crc ^= *p++; ++ for (i = 0; i < 8; i++) ++ crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); ++ } ++ return crc; ++} + -+/* This function transforms a header into a char so that it is useable by -+ * gdbm_store */ ++static int ++generate_crc32() ++{ ++ int crc = 0; ++ ++ crc = crc32(crc, (unsigned char const *) "HCACHE V1", mutt_strlen("HCACHE V1")); + +#if HAVE_LANGINFO_CODESET -+int -+mutt_hcache_charset_matches(const char *d) ++ crc = crc32(crc, (unsigned char const *) Charset, mutt_strlen(Charset)); ++ crc = crc32(crc, (unsigned char const *) "HAVE_LANGINFO_CODESET", mutt_strlen("HAVE_LANGINFO_CODESET")); ++#endif ++ ++#if EXACT_ADDRESS ++ crc = crc32(crc, (unsigned char const *) "EXACT_ADDRESS", mutt_strlen("EXACT_ADDRESS")); ++#endif ++ return crc; ++} ++ ++static int ++crc32_matches(const char *d, unsigned int crc) +{ -+ int matches; -+ int off = sizeof(struct timeval); -+ char *charset = NULL; ++ int off = sizeof(validate); ++ unsigned int mycrc = 0; ++ ++ if (! d) { ++ return 0; ++ } + -+ restore_char(&charset, (unsigned char *) d, &off); -+ matches = (0 == mutt_strcmp(charset, Charset)); -+ FREE(&charset); ++ restore_int(&mycrc, (unsigned char *) d, &off); + -+ return (matches); ++ return (crc == mycrc); +} -+#endif /* HAVE_LANGINFO_CODESET */ + ++/* This function transforms a header into a char so that it is useable by ++ * db_store */ +static void * -+mutt_hcache_dump(HEADER *h, int *off) ++mutt_hcache_dump(void *_db, HEADER *h, int *off, unsigned long long uid_validity) +{ ++ struct header_cache *db = _db; + unsigned char *d = NULL; -+ struct timeval now; + *off = 0; + -+ d = safe_malloc(sizeof(struct timeval)); -+ gettimeofday(&now, NULL); -+ memcpy(d, &now, sizeof(struct timeval)); -+ *off += sizeof(struct timeval); ++ d = safe_malloc(sizeof(validate)); + -+#if HAVE_LANGINFO_CODESET -+ d = dump_char(Charset, d, off); -+#endif /* HAVE_LANGINFO_CODESET */ ++ if (uid_validity) { ++ memcpy(d, &uid_validity, sizeof(long long)); ++ } else { ++ struct timeval now; ++ gettimeofday(&now, NULL); ++ memcpy(d, &now, sizeof(struct timeval)); ++ } ++ *off += sizeof(validate); + ++ d = dump_int(db->crc, d, off); + + safe_realloc(&d, *off + sizeof(HEADER)); + memcpy(d + *off, h, sizeof(HEADER)); @@ -478,12 +582,11 @@ diff -Nru a/hcache.c b/hcache.c + int off = 0; + HEADER *h = mutt_new_header(); + -+ /* skip timeval */ -+ off += sizeof(struct timeval); ++ /* skip validate */ ++ off += sizeof(validate); + -+#if HAVE_LANGINFO_CODESET -+ skip_char(d, &off); -+#endif /* HAVE_LANGINFO_CODESET */ ++ /* skip crc */ ++ off += sizeof(unsigned int); + + memcpy(h, d + off, sizeof(HEADER)); + off += sizeof(HEADER); @@ -496,45 +599,39 @@ diff -Nru a/hcache.c b/hcache.c + + restore_char(&h->maildir_flags, d, &off); + -+ h->old = (*oh)->old; -+ h->path = safe_strdup((*oh)->path); -+ mutt_free_header (oh); ++ /* this is needed for maildir style mailboxes */ ++ if (oh) { ++ h->old = (*oh)->old; ++ h->path = safe_strdup((*oh)->path); ++ mutt_free_header (oh); ++ } + + return h; +} + -+static size_t mutt_hcache_keylen (const char *fn) -+{ -+ const char * p = strchr (fn, ':'); -+ return p ? (size_t) (p - fn) : strlen (fn); -+} -+ +#if HAVE_GDBM -+static struct -+header_cache -+{ -+ GDBM_FILE db; -+ char *folder; -+} HEADER_CACHE; + +void * +mutt_hcache_open(const char *path, const char *folder) +{ -+ struct header_cache *h = malloc(sizeof(HEADER_CACHE)); ++ struct header_cache *h = safe_calloc(1, sizeof(HEADER_CACHE)); + h->db = NULL; + h->folder = safe_strdup (folder); ++ h->crc = generate_crc32(); + + if (! path || path[0] == '\0') { ++ FREE(& h->folder); ++ FREE(& h); + return NULL; + } + -+ h->db = gdbm_open((char *) path, (int) MaildirCachePageSize, GDBM_WRCREAT, 00600, NULL); ++ h->db = gdbm_open((char *) path, (int) HeaderCachePageSize, GDBM_WRCREAT, 00600, NULL); + if (h->db) { + return h; + } + + /* if rw failed try ro */ -+ h->db = gdbm_open((char *) path, (int) MaildirCachePageSize, GDBM_READER, 00600, NULL); ++ h->db = gdbm_open((char *) path, (int) HeaderCachePageSize, GDBM_READER, 00600, NULL); + if(h->db) { + return h; + } else { @@ -560,7 +657,7 @@ diff -Nru a/hcache.c b/hcache.c +} + +void * -+mutt_hcache_fetch(void *db, const char *filename) ++mutt_hcache_fetch(void *db, const char *filename, size_t (*keylen)(const char *fn)) +{ + struct header_cache *h = db; + datum key; @@ -572,18 +669,23 @@ diff -Nru a/hcache.c b/hcache.c + } + + strncpy(path, h->folder, sizeof(path)); -+ strncat(path, filename, sizeof(path) - strlen(path)); ++ strncat(path, filename, sizeof(path) - mutt_strlen(path)); + + key.dptr = path; -+ key.dsize = mutt_hcache_keylen(path); ++ key.dsize = keylen(path); + + data = gdbm_fetch(h->db, key); + ++ if (! crc32_matches(data.dptr, h->crc)) { ++ free(data.dptr); ++ return NULL; ++ } ++ + return data.dptr; +} + +int -+mutt_hcache_store(void *db, const char *filename, HEADER *header) ++mutt_hcache_store(void *db, const char *filename, HEADER *header, unsigned long long uid_validity, size_t (*keylen)(const char *fn)) +{ + struct header_cache *h = db; + datum key; @@ -596,12 +698,12 @@ diff -Nru a/hcache.c b/hcache.c + } + + strncpy(path, h->folder, sizeof(path)); -+ strncat(path, filename, sizeof(path) - strlen(path)); ++ strncat(path, filename, sizeof(path) - mutt_strlen(path)); + + key.dptr = path; -+ key.dsize = mutt_hcache_keylen(path); ++ key.dsize = keylen(path); + -+ data.dptr = mutt_hcache_dump(header, &data.dsize); ++ data.dptr = mutt_hcache_dump(db, header, &data.dsize, uid_validity); + + ret = gdbm_store(h->db, key, data, GDBM_REPLACE); + @@ -611,7 +713,7 @@ diff -Nru a/hcache.c b/hcache.c +} + +int -+mutt_hcache_delete(void *db, const char *filename) ++mutt_hcache_delete(void *db, const char *filename, size_t (*keylen)(const char *fn)) +{ + datum key; + struct header_cache *h = db; @@ -622,22 +724,15 @@ diff -Nru a/hcache.c b/hcache.c + } + + strncpy(path, h->folder, sizeof(path)); -+ strncat(path, filename, sizeof(path) - strlen(path)); ++ strncat(path, filename, sizeof(path) - mutt_strlen(path)); + + key.dptr = path; -+ key.dsize = mutt_hcache_keylen(path); ++ key.dsize = keylen(path); + + return gdbm_delete(h->db, key); +} +#elif HAVE_DB4 + -+static struct -+header_cache -+{ -+ DB_ENV *env; -+ DB *db; -+} HEADER_CACHE; -+ +static void +mutt_hcache_dbt_init(DBT *dbt, void *data, size_t len) +{ @@ -661,15 +756,32 @@ diff -Nru a/hcache.c b/hcache.c + struct stat sb; + u_int32_t createflags = DB_CREATE; + int ret; -+ struct header_cache *h = malloc(sizeof(HEADER_CACHE)); ++ struct header_cache *h = calloc(1, sizeof(HEADER_CACHE)); ++ ++ h->crc = generate_crc32(); + + if (! path || path[0] == '\0') { + FREE(& h); + return NULL; + } + ++ snprintf (h->lockfile, _POSIX_PATH_MAX, "%s-lock-hack", path); ++ ++ h->fd = open(h->lockfile, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); ++ if (h->fd < 0) { ++ FREE (&h); ++ return NULL; ++ } ++ ++ if (mx_lock_file(h->lockfile, h->fd, 1, 0, 5)) { ++ close(h->fd); ++ FREE (&h); ++ return NULL; ++ } ++ + ret = db_env_create(&h->env, 0); + if (ret) { ++ mx_unlock_file(h->lockfile, h->fd, 0); + FREE(& h); + return NULL; + } @@ -679,6 +791,7 @@ diff -Nru a/hcache.c b/hcache.c + ret = db_create(&h->db, h->env, 0); + if (ret) { + h->env->close(h->env, 0); ++ mx_unlock_file(h->lockfile, h->fd, 0); + FREE(& h); + return NULL; + } @@ -686,13 +799,14 @@ diff -Nru a/hcache.c b/hcache.c + + if (stat(path, &sb) != 0 && errno == ENOENT) { + createflags |= DB_EXCL; -+ h->db->set_pagesize(h->db, (int) MaildirCachePageSize); ++ h->db->set_pagesize(h->db, (int) HeaderCachePageSize); + } + + ret = h->db->open(h->db, NULL, path, folder, DB_BTREE, createflags, 0600); + if (ret) { + h->db->close(h->db, 0); + h->env->close(h->env, 0); ++ mx_unlock_file(h->lockfile, h->fd, 0); + FREE(& h); + return NULL; + } @@ -712,12 +826,12 @@ diff -Nru a/hcache.c b/hcache.c + + h->db->close(h->db, 0); + h->env->close(h->env, 0); -+ ++ mx_unlock_file(h->lockfile, h->fd, 0); + FREE(& h); +} + +void * -+mutt_hcache_fetch(void *db, const char *filename) ++mutt_hcache_fetch(void *db, const char *filename, size_t (*keylen)(const char *fn)) +{ + DBT key; + DBT data; @@ -729,17 +843,22 @@ diff -Nru a/hcache.c b/hcache.c + + filename++; /* skip '/' */ + -+ mutt_hcache_dbt_init(&key, (void *) filename, mutt_hcache_keylen(filename)); ++ mutt_hcache_dbt_init(&key, (void *) filename, keylen(filename)); + mutt_hcache_dbt_empty_init(&data); + data.flags = DB_DBT_MALLOC; + + h->db->get(h->db, NULL, &key, &data, 0); + ++ if (! crc32_matches(data.data, h->crc)) { ++ free(data.data); ++ return NULL; ++ } ++ + return data.data; +} + +int -+mutt_hcache_store(void *db, const char *filename, HEADER *header) ++mutt_hcache_store(void *db, const char *filename, HEADER *header, unsigned long long uid_validity, size_t (*keylen)(const char *fn)) +{ + DBT key; + DBT data; @@ -752,11 +871,11 @@ diff -Nru a/hcache.c b/hcache.c + + filename++; /* skip '/' */ + -+ mutt_hcache_dbt_init(&key, (void *) filename, mutt_hcache_keylen(filename)); ++ mutt_hcache_dbt_init(&key, (void *) filename, keylen(filename)); + + mutt_hcache_dbt_empty_init(&data); + data.flags = DB_DBT_USERMEM; -+ data.data = mutt_hcache_dump(header, (signed int *) &data.size); ++ data.data = mutt_hcache_dump(db, header, (signed int *) &data.size, uid_validity); + data.ulen = data.size; + + ret = h->db->put(h->db, NULL, &key, &data, 0); @@ -767,7 +886,7 @@ diff -Nru a/hcache.c b/hcache.c +} + +int -+mutt_hcache_delete(void *db, const char *filename) ++mutt_hcache_delete(void *db, const char *filename, size_t (*keylen)(const char *fn)) +{ + DBT key; + struct header_cache *h = db; @@ -778,31 +897,323 @@ diff -Nru a/hcache.c b/hcache.c + + filename++; /* skip '/' */ + -+ mutt_hcache_dbt_init(&key, (void *) filename, mutt_hcache_keylen(filename)); ++ mutt_hcache_dbt_init(&key, (void *) filename, keylen(filename)); + return h->db->del(h->db, NULL, &key, 0); +} +#endif +diff -Nru a/imap/imap.c b/imap/imap.c +--- a/imap/imap.c 2004-08-18 10:08:12 +02:00 ++++ b/imap/imap.c 2004-08-18 10:08:12 +02:00 +@@ -602,6 +602,17 @@ + if ((pc = imap_get_flags (&(idata->flags), pc)) == NULL) + goto fail; + } ++#ifdef USE_HCACHE ++ /* save UIDVALIDITY for the header cache */ ++ else if (ascii_strncasecmp("OK [UIDVALIDITY", pc, 14) == 0) ++ { ++ dprint(2, (debugfile, "Getting mailbox UIDVALIDITY\n")); ++ pc += 3; ++ pc = imap_next_word(pc); ++ ++ sscanf(pc, "%u", &(idata->uid_validity)); ++ } ++#endif + else + { + pc = imap_next_word (pc); +diff -Nru a/imap/imap_private.h b/imap/imap_private.h +--- a/imap/imap_private.h 2004-08-18 10:08:12 +02:00 ++++ b/imap/imap_private.h 2004-08-18 10:08:12 +02:00 +@@ -179,6 +179,9 @@ + unsigned int newMailCount; + IMAP_CACHE cache[IMAP_CACHE_LEN]; + int noclose : 1; ++#ifdef USE_HCACHE ++ unsigned long long uid_validity; ++#endif + + /* all folder flags - system flags AND keywords */ + LIST *flags; +diff -Nru a/imap/message.c b/imap/message.c +--- a/imap/message.c 2004-08-18 10:08:12 +02:00 ++++ b/imap/message.c 2004-08-18 10:08:12 +02:00 +@@ -39,6 +39,12 @@ + static int msg_parse_fetch (IMAP_HEADER* h, char* s); + static char* msg_parse_flags (IMAP_HEADER* h, char* s); + ++#if USE_HCACHE ++static int msg_fetch_header_fetch (CONTEXT* ctx, IMAP_HEADER* h, char* buf, ++ FILE* fp); ++static size_t imap_hcache_keylen (const char *fn); ++#endif /* USE_HCACHE */ ++ + /* imap_read_headers: + * Changed to read many headers instead of just one. It will return the + * msgno of the last message read. It will return a value other than +@@ -57,8 +63,18 @@ + int fetchlast = 0; + const char *want_headers = "DATE FROM SUBJECT TO CC MESSAGE-ID REFERENCES CONTENT-TYPE IN-REPLY-TO REPLY-TO LINES X-LABEL"; + ++#if USE_HCACHE ++ void *hc = NULL; ++ unsigned long long *uid_validity = NULL; ++ char uid_buf[64]; ++#endif /* USE_HCACHE */ ++ + ctx = idata->ctx; + ++#if USE_HCACHE ++ hc = mutt_hcache_open (HeaderCache, ctx->path); ++#endif /* USE_HCACHE */ ++ + if (mutt_bit_isset (idata->capabilities,IMAP4REV1)) + { + snprintf (hdrreq, sizeof (hdrreq), "BODY.PEEK[HEADER.FIELDS (%s)]", +@@ -73,6 +89,9 @@ + { /* Unable to fetch headers for lower versions */ + mutt_error _("Unable to fetch headers from this IMAP server version."); + mutt_sleep (2); /* pause a moment to let the user see the error */ ++#if USE_HCACHE ++ mutt_hcache_close (hc); ++#endif /* USE_HCACHE */ + return -1; + } + +@@ -83,6 +102,9 @@ + { + mutt_error (_("Could not create temporary file %s"), tempfile); + mutt_sleep (2); ++#if USE_HCACHE ++ mutt_hcache_close (hc); ++#endif /* USE_HCACHE */ + return -1; + } + unlink (tempfile); +@@ -95,14 +117,88 @@ + idata->reopen &= ~IMAP_NEWMAIL_PENDING; + idata->newMailCount = 0; + ++#if USE_HCACHE ++ snprintf (buf, sizeof (buf), ++ "FETCH %d:%d (UID FLAGS)", msgbegin + 1, msgend + 1); ++ fetchlast = msgend + 1; ++ ++ imap_cmd_start (idata, buf); ++ ++ for (msgno = msgbegin; msgno <= msgend ; msgno++) ++ { ++ if (ReadInc && (!msgno || ((msgno+1) % ReadInc == 0))) ++ mutt_message (_("Evaluating cache... [%d/%d]"), msgno + 1, ++ msgend + 1); ++ ++ rewind (fp); ++ memset (&h, 0, sizeof (h)); ++ h.data = safe_calloc (1, sizeof (IMAP_HEADER_DATA)); ++ do ++ { ++ mfhrc = 0; ++ ++ rc = imap_cmd_step (idata); ++ if (rc != IMAP_CMD_CONTINUE) ++ break; ++ ++ if ((mfhrc = msg_fetch_header_fetch (idata->ctx, &h, idata->cmd.buf, fp)) == -1) ++ continue; ++ else if (mfhrc < 0) ++ break; ++ ++ /* make sure we don't get remnants from older larger message headers */ ++ fputs ("\n\n", fp); ++ ++ sprintf(uid_buf, "/%u", h.data->uid); /* XXX --tg 21:41 04-07-11 */ ++ uid_validity = (unsigned long long *) mutt_hcache_fetch (hc, uid_buf, &imap_hcache_keylen); ++ ++ if (uid_validity != NULL ++ && *uid_validity == idata->uid_validity) { ++ ctx->hdrs[msgno] = mutt_hcache_restore((unsigned char *) uid_validity, 0); ++ ctx->hdrs[msgno]->index = h.sid - 1; ++ if (h.sid != ctx->msgcount + 1) ++ dprint (1, (debugfile, "imap_read_headers: msgcount and sequence ID are inconsistent!")); ++ /* messages which have not been expunged are ACTIVE (borrowed from mh ++ * folders) */ ++ ctx->hdrs[msgno]->active = 1; ++ ctx->hdrs[msgno]->read = h.read; ++ ctx->hdrs[msgno]->old = h.old; ++ ctx->hdrs[msgno]->deleted = h.deleted; ++ ctx->hdrs[msgno]->flagged = h.flagged; ++ ctx->hdrs[msgno]->replied = h.replied; ++ ctx->hdrs[msgno]->changed = h.changed; ++ /* ctx->hdrs[msgno]->received is restored from mutt_hcache_restore */ ++ ctx->hdrs[msgno]->data = (void *) (h.data); ++ ++ ctx->msgcount++; ++ } ++ rewind (fp); ++ ++ FREE(&uid_validity); ++ ++ } ++ while ((rc != IMAP_CMD_OK) && ((mfhrc == -1) || ++ ((msgno + 1) >= fetchlast))); ++ } ++ ++ fetchlast = msgbegin; ++#endif /* USE_HCACHE */ ++ + for (msgno = msgbegin; msgno <= msgend ; msgno++) + { + if (ReadInc && (!msgno || ((msgno+1) % ReadInc == 0))) + mutt_message (_("Fetching message headers... [%d/%d]"), msgno + 1, + msgend + 1); + ++ if (ctx->hdrs[msgno]) ++ continue; ++ + if (msgno + 1 > fetchlast) + { ++ fetchlast = msgno + 1; ++ while((fetchlast <= msgend) && (! ctx->hdrs[fetchlast])) ++ fetchlast++; ++ + /* + * Make one request for everything. This makes fetching headers an + * order of magnitude faster if you have a large mailbox. +@@ -112,11 +208,9 @@ + */ + snprintf (buf, sizeof (buf), + "FETCH %d:%d (UID FLAGS INTERNALDATE RFC822.SIZE %s)", msgno + 1, +- msgend + 1, hdrreq); ++ fetchlast, hdrreq); + + imap_cmd_start (idata, buf); +- +- fetchlast = msgend + 1; + } + + /* freshen fp, h */ +@@ -170,6 +264,11 @@ + /* content built as a side-effect of mutt_read_rfc822_header */ + ctx->hdrs[msgno]->content->length = h.content_length; + ++#if USE_HCACHE ++ sprintf(uid_buf, "/%u", h.data->uid); ++ mutt_hcache_store(hc, uid_buf, ctx->hdrs[msgno], idata->uid_validity, &imap_hcache_keylen); ++#endif /* USE_HCACHE */ ++ + ctx->msgcount++; + } + while ((rc != IMAP_CMD_OK) && ((mfhrc == -1) || +@@ -179,7 +278,9 @@ + { + imap_free_header_data ((void**) &h.data); + fclose (fp); +- ++#if USE_HCACHE ++ mutt_hcache_close (hc); ++#endif /* USE_HCACHE */ + return -1; + } + +@@ -194,6 +295,10 @@ + } + } + ++#if USE_HCACHE ++ mutt_hcache_close (hc); ++#endif /* USE_HCACHE */ ++ + fclose(fp); + + if (ctx->msgcount > oldmsgcount) +@@ -724,6 +829,7 @@ + return s; + } + ++ + /* msg_fetch_header: import IMAP FETCH response into an IMAP_HEADER. + * Expects string beginning with * n FETCH. + * Returns: +@@ -782,6 +888,56 @@ + + return rc; + } ++ ++#if USE_HCACHE ++static size_t imap_hcache_keylen (const char *fn) ++{ ++ return mutt_strlen(fn); ++} ++ ++/* msg_fetch_header: import IMAP FETCH response into an IMAP_HEADER. ++ * Expects string beginning with * n FETCH. ++ * Returns: ++ * 0 on success ++ * -1 if the string is not a fetch response ++ * -2 if the string is a corrupt fetch response */ ++static int msg_fetch_header_fetch (CONTEXT* ctx, IMAP_HEADER* h, char* buf, FILE* fp) ++{ ++ IMAP_DATA* idata; ++ long bytes; ++ int rc = -1; /* default now is that string isn't FETCH response*/ ++ ++ idata = (IMAP_DATA*) ctx->data; ++ ++ if (buf[0] != '*') ++ return rc; ++ ++ /* skip to message number */ ++ buf = imap_next_word (buf); ++ h->sid = atoi (buf); ++ ++ /* find FETCH tag */ ++ buf = imap_next_word (buf); ++ if (ascii_strncasecmp ("FETCH", buf, 5)) ++ return rc; ++ ++ rc = -2; /* we've got a FETCH response, for better or worse */ ++ if (!(buf = strchr (buf, '('))) ++ return rc; ++ buf++; ++ ++ if (msg_parse_fetch (h, buf) < 0) { ++ return -2; ++ } ++ ++ if (!(buf = strchr (buf, ')'))) ++ return rc; ++ buf++; ++ ++ return 0; ++} ++#endif /* USE_HCACHE */ ++ + + /* msg_has_flag: do a caseless comparison of the flag against a flag list, + * return 1 if found or flag list has '\*', 0 otherwise */ diff -Nru a/init.h b/init.h ---- init.h 2004-06-10 14:03:44 +02:00 -+++ init.h 2004-06-10 14:03:44 +02:00 -@@ -981,6 +981,28 @@ +--- a/init.h 2004-08-18 10:08:12 +02:00 ++++ b/init.h 2004-08-18 10:08:12 +02:00 +@@ -981,6 +981,30 @@ ** \fBDON'T CHANGE THIS SETTING UNLESS YOU ARE REALLY SURE WHAT YOU ARE ** DOING!\fP */ +#if USE_HCACHE -+ { "maildir_cache", DT_PATH, R_NONE, UL &MaildirCache, 0 }, ++ ++ { "header_cache", DT_PATH, R_NONE, UL &HeaderCache, 0 }, + /* + ** .pp -+ ** Path to the maildir cache file. If unset no cache will be used. ++ ** Path to the header cache file. If unset no cache will be used. Otherwise ++ ** the cache will be enabled for Maildir and IMAP mailboxes. + */ -+ { "maildir_cache_verify", DT_BOOL, R_NONE, OPTHCACHEVERIFY, 1 }, ++ { "maildir_header_cache_verify", DT_BOOL, R_NONE, OPTHCACHEVERIFY, 1 }, + /* + ** .pp -+ ** Check for programs other than mutt having modified maildir -+ ** files when the header cache is in use. This incurs one stat(2) -+ ** per message every time the folder is opened. ++ ** Check for Maildir unaware programs other than mutt having modified maildir ++ ** files when the header cache is in use. This incurs one stat(2) per ++ ** message every time the folder is opened. + */ -+ { "maildir_cache_page_size", DT_NUM, R_NONE, UL &MaildirCachePageSize, 16384 }, ++ { "header_cache_pagesize", DT_NUM, R_NONE, UL &HeaderCachePageSize, 16384 }, + /* + ** .pp + ** Change the maildir header cache database page size. Too large @@ -815,8 +1226,8 @@ diff -Nru a/init.h b/init.h /* ** .pp diff -Nru a/main.c b/main.c ---- main.c 2004-06-10 14:03:44 +02:00 -+++ main.c 2004-06-10 14:03:44 +02:00 +--- a/main.c 2004-08-18 10:08:12 +02:00 ++++ b/main.c 2004-08-18 10:08:12 +02:00 @@ -411,6 +411,12 @@ "-HAVE_GETADDRINFO " #endif @@ -831,13 +1242,20 @@ diff -Nru a/main.c b/main.c #ifdef ISPELL diff -Nru a/mh.c b/mh.c ---- mh.c 2004-06-10 14:03:44 +02:00 -+++ mh.c 2004-06-10 14:03:44 +02:00 -@@ -779,11 +779,65 @@ +--- a/mh.c 2004-08-18 10:08:12 +02:00 ++++ b/mh.c 2004-08-18 10:08:12 +02:00 +@@ -779,11 +779,68 @@ return r; } +#if USE_HCACHE ++ ++static size_t maildir_hcache_keylen (const char *fn) ++{ ++ const char * p = strchr (fn, ':'); ++ return p ? (size_t) (p - fn) : mutt_strlen(fn); ++} ++ /* * This function does the second parsing pass for a maildir-style @@ -854,14 +1272,14 @@ diff -Nru a/mh.c b/mh.c + struct stat lastchanged; + int ret; + -+ hc = mutt_hcache_open (MaildirCache, ctx->path); ++ hc = mutt_hcache_open (HeaderCache, ctx->path); + + for (p = md; p; p = p->next) { + if (! (p && p->h && !p->header_parsed)) { + continue; + } + -+ data = mutt_hcache_fetch (hc, p->h->path + 3); ++ data = mutt_hcache_fetch (hc, p->h->path + 3, &maildir_hcache_keylen); + when = (struct timeval *) data; + + snprintf(fn, sizeof (fn), "%s/%s", ctx->path, p->h->path); @@ -875,18 +1293,14 @@ diff -Nru a/mh.c b/mh.c + + if (data != NULL + && ret == 0 -+ && lastchanged.st_mtime <= when->tv_sec -+#if HAVE_LANGINFO_CODESET -+ && mutt_hcache_charset_matches (data) -+#endif /* HAVE_LANGINFO_CODESET */ -+ ) { ++ && lastchanged.st_mtime <= when->tv_sec) { + p->h = mutt_hcache_restore ((unsigned char *)data, &p->h); + maildir_parse_flags (p->h, fn); + + } else if (maildir_parse_message (ctx->magic, fn, p->h->old, p->h)) { + maildir_parse_flags(p->h, fn); + p->header_parsed = 1; -+ mutt_hcache_store (hc, p->h->path + 3, p->h); ++ mutt_hcache_store (hc, p->h->path + 3, p->h, 0, &maildir_hcache_keylen); + } else { + mutt_free_header (&p->h); + } @@ -899,7 +1313,7 @@ diff -Nru a/mh.c b/mh.c void maildir_delayed_parsing (CONTEXT * ctx, struct maildir *md) { -@@ -801,7 +855,7 @@ +@@ -801,7 +858,7 @@ } } @@ -908,7 +1322,7 @@ diff -Nru a/mh.c b/mh.c /* Read a MH/maildir style mailbox. * -@@ -1293,6 +1347,9 @@ +@@ -1293,6 +1350,9 @@ { char path[_POSIX_PATH_MAX], tmp[_POSIX_PATH_MAX]; int i, j; @@ -918,33 +1332,33 @@ diff -Nru a/mh.c b/mh.c if (ctx->magic == M_MH) i = mh_check_mailbox (ctx, index_hint); -@@ -1302,6 +1359,11 @@ +@@ -1302,6 +1362,11 @@ if (i != 0) return i; +#if USE_HCACHE + if (ctx->magic == M_MAILDIR) -+ hc = mutt_hcache_open(MaildirCache, ctx->path); ++ hc = mutt_hcache_open(HeaderCache, ctx->path); +#endif /* USE_HCACHE */ + for (i = 0; i < ctx->msgcount; i++) { if (ctx->hdrs[i]->deleted -@@ -1310,7 +1372,13 @@ +@@ -1310,7 +1375,13 @@ snprintf (path, sizeof (path), "%s/%s", ctx->path, ctx->hdrs[i]->path); if (ctx->magic == M_MAILDIR || (option (OPTMHPURGE) && ctx->magic == M_MH)) + { +#if USE_HCACHE + if (ctx->magic == M_MAILDIR) -+ mutt_hcache_delete (hc, ctx->hdrs[i]->path + 3); ++ mutt_hcache_delete (hc, ctx->hdrs[i]->path + 3, &maildir_hcache_keylen); +#endif /* USE_HCACHE */ unlink (path); + } else if (ctx->magic == M_MH) { /* MH just moves files out of the way when you delete them */ -@@ -1332,16 +1400,21 @@ +@@ -1332,16 +1403,21 @@ if (ctx->magic == M_MAILDIR) { if (maildir_sync_message (ctx, i) == -1) @@ -968,7 +1382,7 @@ diff -Nru a/mh.c b/mh.c if (ctx->magic == M_MH) mh_update_sequences (ctx); -@@ -1362,6 +1435,13 @@ +@@ -1362,6 +1438,13 @@ } return 0; @@ -983,8 +1397,8 @@ diff -Nru a/mh.c b/mh.c static char *maildir_canon_filename (char *dest, const char *src, size_t l) diff -Nru a/mutt.h b/mutt.h ---- mutt.h 2004-06-10 14:03:44 +02:00 -+++ mutt.h 2004-06-10 14:03:44 +02:00 +--- a/mutt.h 2004-08-18 10:08:12 +02:00 ++++ b/mutt.h 2004-08-18 10:08:12 +02:00 @@ -345,6 +345,9 @@ OPTFORCENAME, OPTFORWDECODE, @@ -996,9 +1410,9 @@ diff -Nru a/mutt.h b/mutt.h OPTHEADER, OPTHELP, diff -Nru a/protos.h b/protos.h ---- protos.h 2004-06-10 14:03:44 +02:00 -+++ protos.h 2004-06-10 14:03:44 +02:00 -@@ -99,6 +99,19 @@ +--- a/protos.h 2004-08-18 10:08:12 +02:00 ++++ b/protos.h 2004-08-18 10:08:12 +02:00 +@@ -99,6 +99,16 @@ ENVELOPE *mutt_read_rfc822_header (FILE *, HEADER *, short, short); HEADER *mutt_dup_header (HEADER *); @@ -1006,12 +1420,9 @@ diff -Nru a/protos.h b/protos.h +void *mutt_hcache_open(const char *path, const char *folder); +void mutt_hcache_close(void *db); +HEADER *mutt_hcache_restore(const unsigned char *d, HEADER **oh); -+void *mutt_hcache_fetch(void *db, const char *filename); -+int mutt_hcache_store(void *db, const char *filename, HEADER *h); -+int mutt_hcache_delete(void *db, const char *filename); -+#if HAVE_LANGINFO_CODESET -+int mutt_hcache_charset_matches(const char *d); -+#endif /* HAVE_LANGINFO_CODESET */ ++void *mutt_hcache_fetch(void *db, const char *filename, size_t (*keylen)(const char *fn)); ++int mutt_hcache_store(void *db, const char *filename, HEADER *h, unsigned long long uid_validity, size_t (*keylen)(const char *fn)); ++int mutt_hcache_delete(void *db, const char *filename, size_t (*keylen)(const char *fn)); +#endif /* USE_HCACHE */ + + @@ -1021,4 +1432,4 @@ diff -Nru a/protos.h b/protos.h --- PATCHES.orig Tue Nov 6 19:59:33 2001 +++ PATCHES Tue Nov 6 19:59:42 2001 @@ -1,0 +1 @@ -+maildir-header-cache.19 ++patch-1.5.6.tg.hcache.0 |