commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. release-2.2-551-gd16a3de


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-551-gd16a3de
Date: Mon, 26 Dec 2011 08:49:00 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=d16a3de50d8c43f7b45f18db1704fa784ee4cb7b

The branch, master has been updated
       via  d16a3de50d8c43f7b45f18db1704fa784ee4cb7b (commit)
      from  babd0be48657946dcf3589060b707dd3cfe0844c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit d16a3de50d8c43f7b45f18db1704fa784ee4cb7b
Author: Sergey Poznyakoff <address@hidden>
Date:   Sun Dec 25 11:00:12 2011 +0200

    imap mbox: minor improvements.
    
    * libproto/imap/mbox.c: Add some debugging messages.
    (_imap_mbx_gensync): New function shared among _imap_mbx_sync and
    _imap_mbx_expunge. It aggregates message numbers with same flags
    to separate message sets, thereby reducing the number of STORE
    commands sent to the server.

-----------------------------------------------------------------------

Summary of changes:
 libproto/imap/mbox.c |  240 +++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 199 insertions(+), 41 deletions(-)

diff --git a/libproto/imap/mbox.c b/libproto/imap/mbox.c
index 934551a..609c86c 100644
--- a/libproto/imap/mbox.c
+++ b/libproto/imap/mbox.c
@@ -157,7 +157,9 @@ __imap_msg_get_stream (struct _mu_imap_message *imsg, 
size_t msgno,
   if (!(imsg->flags & _MU_IMAP_MSG_CACHED))
     {
       char *msgset;
-         
+      
+      mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE1,
+               (_("caching message %lu"), (unsigned long) msgno));
       if (!imbx->cache)
        {
          rc = mu_temp_file_stream_create (&imbx->cache, NULL, 0);
@@ -183,7 +185,14 @@ __imap_msg_get_stream (struct _mu_imap_message *imsg, 
size_t msgno,
                                          _save_message, &clos);
          free (msgset);
          if (rc == 0 && !_imap_mbx_errno (imbx))
-           imsg->message_size = clos.size;
+           {
+             mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE1,
+                       (_("cached message %lu: offset=%lu, size=%lu"),
+                        (unsigned long) msgno,
+                        (unsigned long) imsg->offset,
+                        (unsigned long) clos.size));
+             imsg->message_size = clos.size;
+           }
        }
 
       if (rc)
@@ -360,6 +369,9 @@ _imap_hdr_fill (void *data, char **pbuf, size_t *plen)
   rc = mu_asprintf (&msgset, "%lu", msgno);
   if (rc == 0)
     {
+      mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE1,
+               (_("message %lu: reading headers"),
+                (unsigned long) msgno));
       rc = _imap_fetch_with_callback (imap, msgset, "BODY.PEEK[HEADER]",
                                      _save_message, &clos);
       free (msgset);
@@ -720,6 +732,8 @@ _imap_mbx_open (mu_mailbox_t mbox, int flags)
   rc = mu_mailbox_get_url (mbox, &url);
   if (rc)
     return rc;
+  mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE1,
+           (_("opening mailbox %s"), mu_url_to_string (url)));
   rc = mu_url_sget_path (url, &mbox_name);
   if (rc == MU_ERR_NOENT)
     mbox_name = "INBOX";
@@ -758,6 +772,8 @@ _imap_mbx_close (mu_mailbox_t mbox)
   mu_folder_t folder = mbox->folder;
   mu_imap_t imap = folder->data;
 
+  mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE1,
+           (_("closing mailbox %s"), mu_url_to_string (mbox->url)));
   if (mu_imap_capability_test (imap, "UNSELECT", NULL) == 0)
     rc = mu_imap_unselect (imap);
   else
@@ -820,76 +836,216 @@ _imap_uidvalidity (mu_mailbox_t mbox, unsigned long *pn)
   return 0;
 }
 
+struct attr_tab
+{
+  size_t start;
+  size_t end;
+  int attr_flags;
+};
+
 static int
-_imap_mbx_expunge (mu_mailbox_t mbox)
+attr_tab_cmp (void const *a, void const *b)
 {
-  struct _mu_imap_mailbox *imbx = mbox->data;
-  mu_folder_t folder = mbox->folder;
-  mu_imap_t imap = folder->data;
-  size_t i;
-  char *msgset;
-  int rc;
-  int delflg = 0;
+  struct attr_tab const *ta = a;
+  struct attr_tab const *tb = b;
+
+  if (ta->attr_flags < tb->attr_flags)
+    return -1;
+  else if (ta->attr_flags > tb->attr_flags)
+    return 1;
+
+  if (ta->start < tb->start)
+    return -1;
+  else if (ta->start > tb->start)
+    return 1;
+  return 0;
+} 
+
+static int
+aggregate_attributes (struct _mu_imap_mailbox *imbx,
+                     struct attr_tab **ptab, size_t *pcnt)
+{
+  size_t i, j;
+  size_t count;
+  struct attr_tab *tab;
   
+  /* Pass 1: Count modified attributes */
+  count = 0;
   for (i = 0; i < imbx->msgs_cnt; i++)
     {
       if (imbx->msgs[i].flags & _MU_IMAP_MSG_ATTRCHG)
+       count++;
+    }
+
+  if (count == 0)
+    {
+      *ptab = NULL;
+      *pcnt = 0;
+      return 0;
+    }
+  
+  /* Pass 2: Create and populate expanded array */
+  tab = calloc (count, sizeof (*tab));
+  if (!tab)
+    return ENOMEM;
+  for (i = j = 0; i < imbx->msgs_cnt; i++)
+    {
+      if (imbx->msgs[i].flags & _MU_IMAP_MSG_ATTRCHG)
        {
-         rc = mu_asprintf (&msgset, "%lu", i + 1);
-         if (rc)
-           break;
-         rc = mu_imap_store_flags (imap, 0, msgset,
-                                   MU_IMAP_STORE_SET|MU_IMAP_STORE_SILENT,
-                                   imbx->msgs[i].attr_flags);
-         delflg |= imbx->msgs[i].attr_flags & MU_ATTRIBUTE_DELETED;
-         free (msgset);
-         if (rc)
-           break;
+         tab[j].start = tab[j].end = i;
+         tab[j].attr_flags = imbx->msgs[i].attr_flags;
+         j++;
        }
     }
+  
+  /* Sort the array */
+  qsort (tab, count, sizeof (tab[0]), attr_tab_cmp);
 
-  if (rc)
-    return rc;
+  /* Pass 3: Coalesce message ranges */
+  for (i = j = 0; i < count; i++)
+    {
+      if (i == j)
+       continue;
+      else if ((tab[i].attr_flags == tab[j].attr_flags) &&
+              (tab[i].start == tab[j].end + 1))
+       tab[j].end++;
+      else
+       tab[++j] = tab[i];
+    }
 
-  if (delflg)
-    rc = mu_imap_expunge (imap);
-  
+  *ptab = tab;
+  *pcnt = j + 1;
+  return 0;
+}
+
+static int
+flush_attributes (mu_imap_t imap, mu_stream_t str, int attr_flags)
+{
+  int rc;
+  mu_transport_t trans[2];
+                     
+  mu_stream_write (str, "", 1, NULL);
+  if (mu_stream_err (str))
+    return mu_stream_last_error (str);
+
+  rc = mu_stream_ioctl (str, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, trans);
+  if (rc == 0)
+    rc = mu_imap_store_flags (imap, 0, (char*)trans[0],
+                             MU_IMAP_STORE_SET|MU_IMAP_STORE_SILENT,
+                             attr_flags);
   return rc;
 }
 
 static int
-_imap_mbx_sync (mu_mailbox_t mbox)
+_imap_mbx_gensync (mu_mailbox_t mbox, int *pdel)
 {
   struct _mu_imap_mailbox *imbx = mbox->data;
   mu_folder_t folder = mbox->folder;
   mu_imap_t imap = folder->data;
-  size_t i;
+  size_t i, j;
   char *msgset;
   int rc;
+  int delflg = 0;
+  struct attr_tab *tab;
+  size_t count;
   
-  if (!imbx->msgs)
-    return 0; 
-
-  for (i = 0; i < imbx->msgs_cnt; i++)
+  rc = aggregate_attributes (imbx, &tab, &count);
+  if (rc)
     {
-      if (imbx->msgs[i].flags & _MU_IMAP_MSG_ATTRCHG)
+      /* Too bad, but try to use naive approach */
+      for (i = 0; i < imbx->msgs_cnt; i++)
        {
-         rc = mu_asprintf (&msgset, "%lu", i + 1);
-         if (rc)
-           break;
-         rc = mu_imap_store_flags (imap, 0, msgset,
-                                   MU_IMAP_STORE_SET|MU_IMAP_STORE_SILENT,
-                                   imbx->msgs[i].attr_flags);
-         free (msgset);
-         if (rc)
-           break;
+         if (imbx->msgs[i].flags & _MU_IMAP_MSG_ATTRCHG)
+           {
+             rc = mu_asprintf (&msgset, "%lu", i + 1);
+             if (rc)
+               break;
+             rc = mu_imap_store_flags (imap, 0, msgset,
+                                       MU_IMAP_STORE_SET|MU_IMAP_STORE_SILENT,
+                                       imbx->msgs[i].attr_flags);
+             delflg |= imbx->msgs[i].attr_flags & MU_ATTRIBUTE_DELETED;
+             free (msgset);
+             if (rc)
+               break;
+           }
        }
     }
+  else
+    {
+      mu_stream_t str;
+
+      rc = mu_memory_stream_create (&str, MU_STREAM_RDWR);
+      if (rc == 0)
+       {
+         for (i = j = 0; i < count; i++)
+           {
+             if (j < i)
+               {
+                 if (tab[j].attr_flags != tab[i].attr_flags)
+                   {
+                     rc = flush_attributes (imap, str, tab[j].attr_flags);
+                     delflg |= tab[j].attr_flags & MU_ATTRIBUTE_DELETED;
+                     if (rc)
+                       break;
+                     mu_stream_truncate (str, 0);
+                     j = i;
+                   }
+                 else
+                   mu_stream_printf (str, ",");
+               }
+             if (tab[i].end == tab[i].start)
+               mu_stream_printf (str, "%lu", (unsigned long)tab[i].start+1);
+             else
+               mu_stream_printf (str, "%lu:%lu",
+                                 (unsigned long)tab[i].start+1,
+                                 (unsigned long)tab[i].end+1);
+           }
+
+         if (j < i)
+           {
+             rc = flush_attributes (imap, str, tab[j].attr_flags);
+             delflg |= tab[j].attr_flags & MU_ATTRIBUTE_DELETED;
+           }
+         mu_stream_unref (str);
+       }
+      free (tab);
+    }
+
+  if (rc)
+    return rc;
+
+  if (pdel)
+    *pdel = delflg;
+  
+  return 0;
+}
+
+static int
+_imap_mbx_expunge (mu_mailbox_t mbox)
+{
+  int rc, del = 0;
   
+  mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE1,
+           (_("expunging mailbox %s"), mu_url_to_string (mbox->url)));
+  rc = _imap_mbx_gensync (mbox, &del);
+  if (rc == 0 && del)
+    {
+      mu_folder_t folder = mbox->folder;
+      mu_imap_t imap = folder->data;
+      rc = mu_imap_expunge (imap);
+    }
   return rc;
 }
 
 static int
+_imap_mbx_sync (mu_mailbox_t mbox)
+{
+  mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE1,
+           (_("synchronizing mailbox %s"), mu_url_to_string (mbox->url)));
+  return _imap_mbx_gensync (mbox, NULL);
+}
+
+static int
 _imap_mbx_append_message (mu_mailbox_t mbox, mu_message_t msg)
 {
   int rc;
@@ -1030,6 +1186,8 @@ _imap_mbx_scan (mu_mailbox_t mbox, size_t msgno, size_t 
*pcount)
   int rc;
   static char _imap_scan_items[] = "(UID FLAGS ENVELOPE RFC822.SIZE BODY)";
   
+  mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE1,
+           (_("scanning mailbox %s"), mu_url_to_string (mbox->url)));
   rc = mu_asprintf (&msgset, "%lu:*", (unsigned long) msgno);
   if (rc)
     return rc;


hooks/post-receive
-- 
GNU Mailutils



reply via email to

[Prev in Thread] Current Thread [Next in Thread]