]> granicus.if.org Git - mutt/commitdiff
Make reading maildirs more efficient.
authorThomas Roessler <roessler@does-not-exist.org>
Thu, 24 Jan 2002 14:03:12 +0000 (14:03 +0000)
committerThomas Roessler <roessler@does-not-exist.org>
Thu, 24 Jan 2002 14:03:12 +0000 (14:03 +0000)
mh.c

diff --git a/mh.c b/mh.c
index 281b4c6113c5e1c15785424e521c0a8c8f60b11b..58d597c1a162eec5faec3188f4880566d44789e1 100644 (file)
--- a/mh.c
+++ b/mh.c
@@ -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);