balsa r8051 - in trunk: . libbalsa libbalsa/imap



Author: pawels
Date: Fri Jan 16 18:43:43 2009
New Revision: 8051
URL: http://svn.gnome.org/viewvc/balsa?rev=8051&view=rev

Log:
* libbalsa/files.c: simplify conditional code.
* libbalsa/mailbox_imap.c: the only way to make sure that the
  exist handler does not trigger imap operations and a related
  deadlock is to process it entirely in an idle handler. Fetch
  message data using seqnos, otherwise we can get surprising EXPUNGE
  notifications.
* libbalsa/imap/imap-handle.c: some imap servers send data in the
  same packet as the IDLE prompt. Process it immediately.


Modified:
   trunk/ChangeLog
   trunk/libbalsa/files.c
   trunk/libbalsa/imap/imap-handle.c
   trunk/libbalsa/mailbox_imap.c

Modified: trunk/libbalsa/files.c
==============================================================================
--- trunk/libbalsa/files.c	(original)
+++ trunk/libbalsa/files.c	Fri Jan 16 18:43:43 2009
@@ -146,10 +146,7 @@
     GdkPixbuf *pixbuf = NULL;
     gint width, height;
     const gchar * filename = NULL;
-#if HAVE_GIO
-    GtkIconTheme *icon_theme;
-#elif HAVE_GNOME
-    const char *icon_file;
+#if HAVE_GIO || HAVE_GNOME
     GtkIconTheme *icon_theme;
 #endif
 

Modified: trunk/libbalsa/imap/imap-handle.c
==============================================================================
--- trunk/libbalsa/imap/imap-handle.c	(original)
+++ trunk/libbalsa/imap/imap-handle.c	Fri Jan 16 18:43:43 2009
@@ -328,43 +328,13 @@
   return old_timeout;
 }
 
-/* imap_handle_idle_enable: enables calling IDLE command after seconds
-   of inactivity. IDLE support consists of three subroutines:
-
-1. imap_handle_idle_{enable,disable}() switch to and from the IDLE
-   mode.  switching to the mode is done by registering an idle
-   callback idle_start() with 30 seconds delay time.
-
-2. idle start() sends the IDLE command and registers idle_process() to
-   be notified whenever data is available on the specified descriptor.
-
-3. async_process() processes the data sent from the server. It is used
-   by IDLE and STORE commands, for example. */
-
+/** Called with a locked handle. */
 static gboolean
-async_process(GIOChannel *source, GIOCondition condition, gpointer data)
+async_process_real(ImapMboxHandle *h)
 {
-  ImapMboxHandle *h = (ImapMboxHandle*)data;
   ImapResponse rc = IMR_UNTAGGED;
-  int retval;
   unsigned async_cmd;
-  gboolean retval_async;
-
-  g_return_val_if_fail(h, FALSE);
-
-  if(HANDLE_TRYLOCK(h) != 0) 
-    return FALSE;/* async data on already locked handle? Don't try again. */
-  if(ASYNC_DEBUG) printf("async_process() ENTER\n");
-  if(h->state == IMHS_DISCONNECTED) {
-    if(ASYNC_DEBUG) printf("async_process() on disconnected\n");
-    HANDLE_UNLOCK(h);
-    return FALSE;
-  }
-  if( (condition & G_IO_HUP) == G_IO_HUP) {
-      imap_handle_disconnect(h);
-      HANDLE_UNLOCK(h);
-      return FALSE;
-  }
+  int retval;
 
   async_cmd = cmdi_get_pending(h->cmd_info);
   if(ASYNC_DEBUG) printf("async_process() enter loop\n");
@@ -377,7 +347,6 @@
              "Last message was: \"%s\" - shutting down connection.\n",
              rc, h->last_msg);
       imap_handle_disconnect(h);
-      HANDLE_UNLOCK(h);
       return FALSE;
     }
     async_cmd = cmdi_get_pending(h->cmd_info);
@@ -398,7 +367,46 @@
     printf("async_process() sio: %d rc: %d returns %d (%d cmds in queue)\n",
            retval, rc, !h->idle_issued && async_cmd == 0,
            g_list_length(h->cmd_info));
-  retval_async = h->idle_issued || async_cmd != 0;
+  return h->idle_issued || async_cmd != 0;
+}
+
+/* imap_handle_idle_enable: enables calling IDLE command after seconds
+   of inactivity. IDLE support consists of three subroutines:
+
+1. imap_handle_idle_{enable,disable}() switch to and from the IDLE
+   mode.  switching to the mode is done by registering an idle
+   callback idle_start() with 30 seconds delay time.
+
+2. idle start() sends the IDLE command and registers idle_process() to
+   be notified whenever data is available on the specified descriptor.
+
+3. async_process() processes the data sent from the server. It is used
+   by IDLE and STORE commands, for example. */
+
+static gboolean
+async_process(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+  ImapMboxHandle *h = (ImapMboxHandle*)data;
+  gboolean retval_async;
+
+  g_return_val_if_fail(h, FALSE);
+
+  if(ASYNC_DEBUG) printf("async_process() ENTER\n");
+  if(HANDLE_TRYLOCK(h) != 0) 
+    return FALSE;/* async data on already locked handle? Don't try again. */
+  if(ASYNC_DEBUG) printf("async_process() LOCKED\n");
+  if(h->state == IMHS_DISCONNECTED) {
+    if(ASYNC_DEBUG) printf("async_process() on disconnected\n");
+    HANDLE_UNLOCK(h);
+    return FALSE;
+  }
+  if( (condition & G_IO_HUP) == G_IO_HUP) {
+      imap_handle_disconnect(h);
+      HANDLE_UNLOCK(h);
+      return FALSE;
+  }
+  retval_async = async_process_real(h);
+
   HANDLE_UNLOCK(h);
   return retval_async;
 }
@@ -435,11 +443,16 @@
     h->iochannel = g_io_channel_unix_new(h->sd);
     g_io_channel_set_encoding(h->iochannel, NULL, NULL);
   }
+  if(ASYNC_DEBUG) printf("async_process() registered\n");
   h->async_watch_id = g_io_add_watch(h->iochannel, G_IO_IN|G_IO_HUP,
 				     async_process, h);
   h->idle_enable_id = 0;
   h->idle_issued = 1;
 
+  /* In principle, IMAP server can send some data in the same packet
+     as the RESPOND line. GMail does it. Process it. */
+  async_process_real(h);
+
   HANDLE_UNLOCK(h);
   return FALSE;
 }

Modified: trunk/libbalsa/mailbox_imap.c
==============================================================================
--- trunk/libbalsa/mailbox_imap.c	(original)
+++ trunk/libbalsa/mailbox_imap.c	Fri Jan 16 18:43:43 2009
@@ -754,30 +754,21 @@
 }
 
 static gboolean
-update_counters_and_filter(void *data)
+imap_exists_idle(gpointer data)
 {
-    LibBalsaMailbox *mailbox= (LibBalsaMailbox*)data;
+    LibBalsaMailboxImap *mimap = (LibBalsaMailboxImap*)data;
+    LibBalsaMailbox *mailbox = LIBBALSA_MAILBOX(mimap);
+    unsigned cnt;
 
+    printf("Exists_idle ENTER\n");
     libbalsa_lock_mailbox(mailbox);
     gdk_threads_enter();
-    libbalsa_mailbox_run_filters_on_reception(mailbox);
-    lbm_imap_get_unseen(LIBBALSA_MAILBOX_IMAP(mailbox));
-    gdk_threads_leave();
-    libbalsa_unlock_mailbox(mailbox);
-    g_object_unref(G_OBJECT(mailbox));
-    return FALSE;
-}
-
-static void
-imap_exists_cb(ImapMboxHandle *handle, LibBalsaMailboxImap *mimap)
-{
-    unsigned cnt;
-    LibBalsaMailbox *mailbox = LIBBALSA_MAILBOX(mimap);
-    libbalsa_lock_mailbox(mailbox);
 
     mimap->sort_field = -1;	/* Invalidate. */
-    cnt = imap_mbox_handle_get_exists(mimap->handle);
-    if(cnt != mimap->messages_info->len) {
+
+    if(mimap->handle && /* was it closed in meantime? */
+       (cnt = imap_mbox_handle_get_exists(mimap->handle))
+       != mimap->messages_info->len) {
         unsigned i;
         struct message_info a = {0};
         GNode *sibling = NULL;
@@ -811,8 +802,6 @@
             }
         } 
 
-        gdk_threads_enter();
-
         if (mailbox->msg_tree)
             sibling = g_node_last_child(mailbox->msg_tree);
         for(i=mimap->messages_info->len+1; i <= cnt; i++) {
@@ -823,16 +812,23 @@
         }
         ++mimap->search_stamp;
         
-        gdk_threads_leave();
-    
-        /* we run filters and get unseen messages in a idle callback:
-         * these things do not need to be done immediately and we do 
-         * not want to issue too many new overlapping IMAP requests.
-         */
-        g_object_ref(G_OBJECT(mailbox));
-        g_idle_add(update_counters_and_filter, mailbox);
+	libbalsa_mailbox_run_filters_on_reception(mailbox);
+	lbm_imap_get_unseen(LIBBALSA_MAILBOX_IMAP(mailbox));    
     }
+
+    gdk_threads_leave();
     libbalsa_unlock_mailbox(mailbox);
+    g_object_unref(G_OBJECT(mailbox));
+
+    return FALSE;
+}
+
+static void
+imap_exists_cb(ImapMboxHandle *handle, LibBalsaMailboxImap *mimap)
+{
+    printf("Imap exist callback, registering idle handler\n");
+    g_object_ref(G_OBJECT(mimap));
+    g_idle_add(imap_exists_idle, mimap);
 }
 
 static void
@@ -1100,6 +1096,19 @@
     mbox->sort_field = -1;	/* Invalidate. */
 }
 
+struct SaveToData {
+    FILE *f;
+    gboolean error;
+};
+
+static void
+save_to(unsigned seqno, const char *buf, size_t buflen, void* arg)
+{
+    struct SaveToData *std  = (struct SaveToData*)arg;
+    if(fwrite(buf, 1, buflen, std->f) != buflen)
+	std->error = TRUE;
+}
+
 static FILE*
 get_cache_stream(LibBalsaMailbox *mailbox, guint msgno, gboolean peek)
 {
@@ -1125,11 +1134,14 @@
 #endif
         cache = fopen(path, "wb");
         if(cache) {
+	    struct SaveToData std;
+	    std.f = cache;
+	    std.error = FALSE;
             II(rc,mimap->handle,
-               imap_mbox_handle_fetch_rfc822_uid(mimap->handle, uid,
-                                                 peek, cache));
+               imap_mbox_handle_fetch_rfc822(mimap->handle, 1, &msgno,
+					     peek, save_to, &std));
             fclose(cache);
-	    if(rc != IMR_OK) {
+	    if(std.error || rc != IMR_OK) {
 		printf("Error fetching RFC822 message, removing cache.\n");
 		unlink(path);
 	    }



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