balsa r8051 - in trunk: . libbalsa libbalsa/imap
- From: pawels svn gnome org
- To: svn-commits-list gnome org
- Subject: balsa r8051 - in trunk: . libbalsa libbalsa/imap
- Date: Fri, 16 Jan 2009 18:43:43 +0000 (UTC)
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]