[balsa/56-imap-expunge] mailbox-imap: Handle expunged messages in idle



commit 79e414aadbcf1d5aa01b6c9cbd56ff6701a504fc
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date:   Mon Mar 8 11:35:48 2021 -0500

    mailbox-imap: Handle expunged messages in idle
    
    Handle expunged IMAP messages in an idle callback
    
    * libbalsa/mailbox_imap.c: add an array of expunged messages and
        an idle id to LibBalsaMailboxImap;
      (libbalsa_mailbox_imap_init): initialize them;
      (libbalsa_mailbox_imap_dispose): remove any outstanding idle source;
      (libbalsa_mailbox_imap_finalize): free the array;
      (imap_expunge_cb): populate the array, and if necessary schedule the idle callback;
      (imap_expunge_idle): handle the expunged messages.

 ChangeLog               |  13 +++++++
 libbalsa/mailbox_imap.c | 100 +++++++++++++++++++++++++++++++++---------------
 2 files changed, 83 insertions(+), 30 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 380a3eb89..91f30048e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2021-03-08  Peter Bloomfield  <pbloomfield bellsouth net>
+
+       Handle expunged IMAP messages in an idle callback
+
+       * libbalsa/mailbox_imap.c: add an array of expunged messages and
+           an idle id to LibBalsaMailboxImap;
+         (libbalsa_mailbox_imap_init): initialize them;
+         (libbalsa_mailbox_imap_dispose): remove any outstanding idle source;
+         (libbalsa_mailbox_imap_finalize): free the array;
+         (imap_expunge_cb): populate the array, and if necessary schedule the idle
+           callback;
+         (imap_expunge_idle): handle the expunged messages.
+
 2020-12-21  Pawel Salek  <pawsa0 gmail com>
 
     * NEWS, configure.ac, meson.build: release balsa-2.6.2
diff --git a/libbalsa/mailbox_imap.c b/libbalsa/mailbox_imap.c
index dbe4091d8..10586f999 100644
--- a/libbalsa/mailbox_imap.c
+++ b/libbalsa/mailbox_imap.c
@@ -86,6 +86,9 @@ struct _LibBalsaMailboxImap {
 
     gboolean disconnected;
     struct ImapCacheManager *icm;
+
+    GArray *expunged_seqnos;
+    guint expunged_idle_id;
 };
 
 struct message_info {
@@ -275,6 +278,9 @@ libbalsa_mailbox_imap_init(LibBalsaMailboxImap * mailbox)
     mailbox->sort_ranks = g_array_new(FALSE, FALSE, sizeof(guint));
     mailbox->sort_field = -1;  /* Initially invalid. */
     mailbox->disconnected = FALSE;
+
+    mailbox->expunged_seqnos = g_array_new(FALSE, FALSE, sizeof(guint));
+    mailbox->expunged_idle_id = 0;
 }
 
 static void
@@ -297,6 +303,11 @@ libbalsa_mailbox_imap_dispose(GObject * object)
         mimap->unread_update_id = 0;
     }
 
+    if (mimap->expunged_idle_id != 0) {
+        g_source_remove(mimap->expunged_idle_id);
+        mimap->expunged_idle_id = 0;
+    }
+
     G_OBJECT_CLASS(libbalsa_mailbox_imap_parent_class)->dispose(object);
 }
 
@@ -307,6 +318,7 @@ libbalsa_mailbox_imap_finalize(GObject * object)
 
     g_free(mimap->path);
     g_array_free(mimap->sort_ranks, TRUE);
+    g_array_free(mimap->expunged_seqnos, TRUE);
     g_list_free_full(mimap->acls, (GDestroyNotify) imap_user_acl_free);
     if (mimap->icm != NULL)
         imap_cache_manager_free(mimap->icm);
@@ -884,22 +896,70 @@ imap_exists_cb(ImapMboxHandle *handle, LibBalsaMailboxImap *mimap)
     g_idle_add(imap_exists_idle, g_object_ref(mimap));
 }
 
+static gboolean
+imap_expunge_idle(gpointer user_data)
+{
+    LibBalsaMailboxImap *mimap = user_data;
+    guint j;
+
+    LibBalsaMailbox *mailbox = LIBBALSA_MAILBOX(mimap);
+
+    libbalsa_lock_mailbox(mailbox);
+
+    /* Process the expunged messages in reverse order, so that each
+     * seqno points to the correct msg_info. */
+    g_array_sort(mimap->expunged_seqnos, cmp_msgno);
+    for (j = mimap->expunged_seqnos->len; j > 0; --j) {
+        guint seqno = g_array_index(mimap->expunged_seqnos, guint, j - 1);
+        struct message_info *msg_info;
+        guint i;
+
+        libbalsa_mailbox_msgno_removed(mailbox, seqno);
+
+        msg_info = message_info_from_msgno(mimap, seqno);
+        if (msg_info != NULL) {
+            if (msg_info->message != NULL)
+                g_object_unref(msg_info->message);
+            g_array_remove_index(mimap->messages_info, seqno - 1);
+        }
+
+        if (seqno <= mimap->msgids->len) {
+            gchar *msgid;
+
+            msgid = g_ptr_array_index(mimap->msgids, seqno - 1);
+            g_free(msgid);
+            g_ptr_array_remove_index(mimap->msgids, seqno - 1);
+        }
+
+        for (i = seqno - 1; i < mimap->messages_info->len; i++) {
+            struct message_info *info =
+                &g_array_index(mimap->messages_info, struct message_info, i);
+
+            g_assert(info != NULL);
+            if (info->message != NULL)
+                libbalsa_message_set_msgno(info->message, i + 1);
+        }
+    }
+
+    ++mimap->search_stamp;
+    mimap->sort_field = -1;     /* Invalidate. */
+
+    mimap->expunged_idle_id = 0;
+    g_array_set_size(mimap->expunged_seqnos, 0);
+    libbalsa_unlock_mailbox(mailbox);
+
+    return G_SOURCE_REMOVE;
+}
+
 static void
 imap_expunge_cb(ImapMboxHandle *handle, unsigned seqno,
                 LibBalsaMailboxImap *mimap)
 {
     ImapMessage *imsg;
-    guint i;
-
     LibBalsaMailbox *mailbox = LIBBALSA_MAILBOX(mimap);
-    struct message_info *msg_info;
 
     libbalsa_lock_mailbox(mailbox);
 
-    libbalsa_mailbox_msgno_removed(mailbox, seqno);
-    ++mimap->search_stamp;
-    mimap->sort_field = -1;    /* Invalidate. */
-
     /* Use imap_mbox_handle_get_msg(mimap->handle, seqno)->uid, not
      * IMAP_MESSAGE_UID(msg_info->message), as the latter may try to
      * fetch the message from the server. */
@@ -912,29 +972,9 @@ imap_expunge_cb(ImapMboxHandle *handle, unsigned seqno,
         g_strfreev(pair);
     }
 
-    msg_info = message_info_from_msgno(mimap, seqno);
-    if (msg_info) {
-        if (msg_info->message)
-            g_object_unref(msg_info->message);
-        g_array_remove_index(mimap->messages_info, seqno-1);
-    }
-
-    if (seqno <= mimap->msgids->len) {
-        gchar *msgid;
-
-        msgid = g_ptr_array_index(mimap->msgids, seqno - 1);
-        g_free(msgid);
-        g_ptr_array_remove_index(mimap->msgids, seqno - 1);
-    }
-
-    for (i = seqno - 1; i < mimap->messages_info->len; i++) {
-       struct message_info *info =
-           &g_array_index(mimap->messages_info, struct message_info, i);
-
-        g_assert(info != NULL);
-        if (info->message != NULL)
-            libbalsa_message_set_msgno(info->message, i + 1);
-    }
+    g_array_append_val(mimap->expunged_seqnos, seqno);
+    if (mimap->expunged_idle_id == 0)
+        mimap->expunged_idle_id = g_idle_add(imap_expunge_idle, mimap);
 
     libbalsa_unlock_mailbox(mailbox);
 }


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