Commit 013a498d authored by Thomas Roessler's avatar Thomas Roessler

Make reading maildirs more efficient.

parent 0bd84f19
......@@ -45,6 +45,7 @@ struct maildir
{
HEADER *h;
char *canon_fname;
unsigned header_parsed : 1;
struct maildir *next;
};
......@@ -544,15 +545,20 @@ static void maildir_update_mtime(CONTEXT *ctx)
ctx->mtime = st.st_mtime;
}
static HEADER *maildir_parse_message(int magic, const char *fname, int is_old)
/*
* Actually parse a maildir message. This may also be used to fill
* out a fake header structure generated by lazy maildir parsing.
*/
static HEADER *maildir_parse_message (int magic, const char *fname, int is_old, HEADER *_h)
{
FILE *f;
HEADER *h = NULL;
HEADER *h = _h;
struct stat st;
if ((f = fopen (fname, "r")) != NULL)
{
h = mutt_new_header();
if (!h)
h = mutt_new_header();
h->env = mutt_read_rfc822_header (f, h, 0, 0);
fstat (fileno (f), &st);
......@@ -568,25 +574,37 @@ static HEADER *maildir_parse_message(int magic, const char *fname, int is_old)
if (magic == M_MAILDIR)
{
/* maildir stores its flags in the filename, so ignore the flags in
* the header of the message
/*
* maildir stores its flags in the filename, so ignore the
* flags in the header of the message
*/
h->old = is_old;
maildir_parse_flags(h, fname);
maildir_parse_flags (h, fname);
}
}
return h;
}
/* note that this routine will _not_ modify the context given by ctx. */
/*
* Note that this routine will _not_ modify the context given by
* ctx.
*
* It's used in the first parsing pass on maildir and MH folders.
* In the MH case, this means full parsing of the folder. In the
* maildir case, it means that we only look at flags, and create a
* fake HEADER structure, which may later be filled in by
* maildir_parse_message(), when called from
* maildir_delayed_parsing().
*
*/
static int maildir_parse_entry(CONTEXT *ctx, struct maildir ***last,
static int maildir_parse_entry (CONTEXT *ctx, struct maildir ***last,
const char *subdir, const char *fname,
int *count, int is_old)
{
struct maildir *entry;
HEADER *h;
HEADER *h = NULL;
char buf[_POSIX_PATH_MAX];
if(subdir)
......@@ -594,9 +612,18 @@ static int maildir_parse_entry(CONTEXT *ctx, struct maildir ***last,
else
snprintf(buf, sizeof(buf), "%s/%s", ctx->path, fname);
if((h = maildir_parse_message(ctx->magic, buf, is_old)) != NULL)
if (ctx->magic == M_MH)
h = maildir_parse_message (ctx->magic, buf, is_old, NULL);
else
{
h = mutt_new_header ();
h->old = is_old;
maildir_parse_flags (h, buf);
}
if (h != NULL)
{
if(count)
if (count)
{
(*count)++;
if (!ctx->quiet && ReadInc && ((*count % ReadInc) == 0 || *count == 1))
......@@ -613,6 +640,7 @@ static int maildir_parse_entry(CONTEXT *ctx, struct maildir ***last,
entry = safe_calloc(sizeof(struct maildir), 1);
entry->h = h;
entry->header_parsed = (ctx->magic == M_MH);
**last = entry;
*last = &entry->next;
......@@ -622,6 +650,8 @@ static int maildir_parse_entry(CONTEXT *ctx, struct maildir ***last,
return -1;
}
/* Ignore the garbage files. A valid MH message consists of only
* digits. Deleted message get moved to a filename with a comma before
* it.
......@@ -637,8 +667,8 @@ int mh_valid_message (const char *s)
return 1;
}
static int maildir_parse_dir(CONTEXT *ctx, struct maildir ***last,
const char *subdir, int *count)
static int maildir_parse_dir (CONTEXT *ctx, struct maildir ***last,
const char *subdir, int *count)
{
DIR *dirp;
struct dirent *de;
......@@ -711,10 +741,34 @@ static void maildir_add_to_context(CONTEXT *ctx, struct maildir *md)
static void maildir_move_to_context(CONTEXT *ctx, struct maildir **md)
{
maildir_add_to_context(ctx, *md);
maildir_free_maildir(md);
maildir_add_to_context (ctx, *md);
maildir_free_maildir (md);
}
/*
* This function does the second parsing pass for a maildir-style
* folder.
*/
void maildir_delayed_parsing (CONTEXT *ctx, struct maildir *md)
{
struct maildir *p;
char fn[_POSIX_PATH_MAX];
for (p = md; p; p = p->next)
if (p && p->h && !p->header_parsed)
{
snprintf (fn, sizeof (fn), "%s/%s", ctx->path, p->h->path);
if (maildir_parse_message (ctx->magic, fn, p->h->old, p->h))
p->header_parsed = 1;
else
mutt_free_header (&p->h);
}
}
/* Read a MH/maildir style mailbox.
*
* args:
......@@ -737,7 +791,7 @@ int mh_read_dir (CONTEXT *ctx, const char *subdir)
maildir_update_mtime(ctx);
if(maildir_parse_dir(ctx, &last, subdir, &count) == -1)
if (maildir_parse_dir(ctx, &last, subdir, &count) == -1)
return -1;
if (ctx->magic == M_MH)
......@@ -747,6 +801,9 @@ int mh_read_dir (CONTEXT *ctx, const char *subdir)
mhs_free_sequences (&mhs);
}
if (ctx->magic == M_MAILDIR)
maildir_delayed_parsing (ctx, md);
maildir_move_to_context(ctx, &md);
return 0;
}
......@@ -1379,8 +1436,8 @@ int mh_check_mailbox(CONTEXT *ctx, int *index_hint)
dprint(2, (debugfile, "%s:%d: mh_check_mailbox(): Looking for %s.\n", __FILE__, __LINE__, b1));
if((p = hash_find(fnames, b1)) && p->h &&
mbox_strict_cmp_headers(ctx->hdrs[i], p->h))
if ((p = hash_find(fnames, b1)) && p->h &&
(ctx->magic == M_MAILDIR || mbox_strict_cmp_headers(ctx->hdrs[i], p->h)))
{
/* found the right message */
......@@ -1448,6 +1505,7 @@ int mh_check_mailbox(CONTEXT *ctx, int *index_hint)
occult = 1;
}
}
/* destroy the file name hash */
......@@ -1481,6 +1539,10 @@ int mh_check_mailbox(CONTEXT *ctx, int *index_hint)
mx_update_tables(ctx, 0);
}
/* If this is a maildir folder, do any delayed parsing we need to do. */
if (ctx->magic == M_MAILDIR)
maildir_delayed_parsing (ctx, md);
/* Incorporate new messages */
maildir_move_to_context(ctx, &md);
......
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