aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog13
-rw-r--r--camel/Makefile.am2
-rw-r--r--camel/camel-debug.c115
-rw-r--r--camel/camel-debug.h46
-rw-r--r--camel/camel-exception.c6
-rw-r--r--camel/camel.c12
-rw-r--r--camel/providers/imap/camel-imap-folder.c135
7 files changed, 260 insertions, 69 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index dd0cf84034..6ba3a3b09d 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,5 +1,18 @@
2004-03-23 Not Zed <NotZed@Ximian.com>
+ * camel-exception.c (camel_exception_setv): use camel debug to add
+ some debug here.
+
+ * camel.c (camel_init): call camel_debug_init().
+
+ * camel-debug.c (camel_debug_init, camel_debug): new util stuff
+ for extended debug options.
+
+ * providers/imap/camel-imap-folder.c (imap_get_message): if we're
+ supposed to be online, check we are online before proceeding.
+ Actually major restructure so we re-try the fetch a couple of
+ times first before failing. i.e. silent reconnect. See #55381.
+
* providers/imap/camel-imap-store.c (get_folder_info_online):
connect lock around this. was getting a race with mem corruption
otherwise.
diff --git a/camel/Makefile.am b/camel/Makefile.am
index 07bfdbaead..4432d0e4a2 100644
--- a/camel/Makefile.am
+++ b/camel/Makefile.am
@@ -27,6 +27,7 @@ libcamel_la_SOURCES = \
camel-cipher-context.c \
camel-data-cache.c \
camel-data-wrapper.c \
+ camel-debug.c \
camel-digest-folder.c \
camel-digest-store.c \
camel-digest-summary.c \
@@ -128,6 +129,7 @@ libcamelinclude_HEADERS = \
camel-cipher-context.h \
camel-data-cache.h \
camel-data-wrapper.h \
+ camel-debug.h \
camel-digest-folder.h \
camel-digest-store.h \
camel-digest-summary.h \
diff --git a/camel/camel-debug.c b/camel/camel-debug.c
new file mode 100644
index 0000000000..7c16c9a614
--- /dev/null
+++ b/camel/camel-debug.c
@@ -0,0 +1,115 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- *
+ *
+ * Author: Michael Zucchi <notzed@ximian.com>
+ *
+ * Copyright 2004 Novell Inc. (www.novell.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "camel-debug.h"
+
+int camel_verbose_debug;
+
+static GHashTable *debug_table = NULL;
+
+/**
+ * camel_debug_init:
+ * @void:
+ *
+ * Init camel debug. Maintain legacy CAMEL_VERBOSE_DEBUG as well as the
+ * new CAMEL_DEBUG based environment variable interfaces.
+ *
+ * CAMEL_VERBOSE_DEBUG is set to a number to turn debug on.
+ *
+ * CAMEL_DEBUG is set to a comma separated list of modules to debug.
+ * The modules can contain module-specific specifiers after a ':', or
+ * just act as a wildcard for the module or even specifier. e.g. 'imap'
+ * for imap debug, or 'imap:folder' for imap folder debug. Additionaly,
+ * ':folder' can be used for a wildcard for any folder operations.
+ **/
+void camel_debug_init(void)
+{
+ char *d;
+
+ d = getenv("CAMEL_VERBOSE_DEBUG");
+ if (d)
+ camel_verbose_debug = atoi(d);
+
+ d = g_strdup(getenv("CAMEL_DEBUG"));
+ if (d) {
+ char *p;
+
+ debug_table = g_hash_table_new(g_str_hash, g_str_equal);
+ p = d;
+ while (*p) {
+ while (*p && *p != ',')
+ p++;
+ if (*p)
+ *p++ = 0;
+ g_hash_table_insert(debug_table, d, d);
+ d = p;
+ }
+
+ if (g_hash_table_lookup(debug_table, "all"))
+ camel_verbose_debug = 1;
+ }
+}
+
+/**
+ * camel_debug:
+ * @mode:
+ *
+ * Check to see if a debug mode is activated. @mode takes one of two forms,
+ * a fully qualified 'module:target', or a wildcard 'module' name. It
+ * returns a boolean to indicate if the module or module and target is
+ * currently activated for debug output.
+ *
+ * Return value:
+ **/
+gboolean camel_debug(const char *mode)
+{
+ if (camel_verbose_debug)
+ return TRUE;
+
+ if (debug_table) {
+ char *colon;
+ char *fallback;
+
+ if (g_hash_table_lookup(debug_table, mode))
+ return TRUE;
+
+ /* Check for fully qualified debug */
+ colon = strchr(mode, ':');
+ if (colon) {
+ fallback = g_alloca(strlen(mode)+1);
+ strcpy(fallback, mode);
+ colon = (colon-mode) + fallback;
+ /* Now check 'module[:*]' */
+ *colon = 0;
+ if (g_hash_table_lookup(debug_table, fallback))
+ return TRUE;
+ /* Now check ':subsystem' */
+ *colon = ':';
+ if (g_hash_table_lookup(debug_table, colon))
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
diff --git a/camel/camel-debug.h b/camel/camel-debug.h
new file mode 100644
index 0000000000..7ebf1eb9c0
--- /dev/null
+++ b/camel/camel-debug.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- *
+ *
+ * Author: Michael Zucchi <notzed@ximian.com>
+ *
+ * Copyright 2004 Novell Inc. (www.novell.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef CAMEL_DEBUG_H
+#define CAMEL_DEBUG_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus }*/
+
+#include <glib.h>
+
+/* This is how the basic debug checking strings should be done */
+#define CAMEL_DEBUG_IMAP "imap"
+#define CAMEL_DEBUG_IMAP_FOLDER "imap:folder"
+
+void camel_debug_init(void);
+gboolean camel_debug(const char *mode);
+
+/* This interface is deprecated */
+extern int camel_verbose_debug;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* CAMEL_DEBUG_H */
diff --git a/camel/camel-exception.c b/camel/camel-exception.c
index 95e376624a..c67ab66c22 100644
--- a/camel/camel-exception.c
+++ b/camel/camel-exception.c
@@ -25,12 +25,15 @@
#include <config.h>
#endif
+#include <stdio.h>
#include <glib.h>
#include <pthread.h>
#include "camel-exception.h"
#include "e-util/e-memory.h"
+#include "camel-debug.h"
+
/* i dont know why gthread_mutex stuff even exists, this is easier */
/* also, i'm not convinced mutexes are needed here. But it
@@ -204,6 +207,9 @@ camel_exception_setv (CamelException *ex,
{
va_list args;
char *old;
+
+ if (camel_debug("exception"))
+ printf("CamelException.setv(%p, %d, '%s')\n", ex, id, format);
if (!ex)
return;
diff --git a/camel/camel.c b/camel/camel.c
index 8241b5b0ac..09ba07caf4 100644
--- a/camel/camel.c
+++ b/camel/camel.c
@@ -39,8 +39,7 @@
#include "camel-certdb.h"
#include "camel-mime-utils.h"
#include "camel-provider.h"
-
-int camel_verbose_debug = 0;
+#include "camel-debug.h"
static int initialised = FALSE;
@@ -76,13 +75,12 @@ camel_init (const char *configdir, gboolean nss_init)
if (initialised)
return 0;
-
- if (getenv ("CAMEL_VERBOSE_DEBUG"))
- camel_verbose_debug = atoi(getenv("CAMEL_VERBOSE_DEBUG"));
-
+
+ camel_debug_init();
+
/* initialise global camel_object_type */
camel_object_get_type();
-
+
camel_mime_utils_init();
camel_operation_init();
camel_provider_init();
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index 7db367a8cb..f2b62073a2 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -1958,7 +1958,8 @@ imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex)
CamelMessageInfo *mi;
CamelMimeMessage *msg;
CamelStream *stream = NULL;
-
+ int retry;
+
/* If the server doesn't support IMAP4rev1, or we already have
* the whole thing cached, fetch it in one piece.
*/
@@ -1972,74 +1973,84 @@ imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex)
_("Cannot get message: %s\n %s"), uid, _("No such message"));
return NULL;
}
-
- /* If the message is small, fetch it in one piece. */
- if (mi->size < IMAP_SMALL_BODY_SIZE) {
- camel_folder_summary_info_free (folder->summary, mi);
- return get_message_simple (imap_folder, uid, NULL, ex);
- }
-
- /* For larger messages, fetch the structure and build a message
- * with offline parts. (We check mi->content->type rather than
- * mi->content because camel_folder_summary_info_new always creates
- * an empty content struct.)
- */
- if (content_info_incomplete (mi->content)) {
- CamelImapResponse *response;
- GData *fetch_data = NULL;
- char *body, *found_uid;
- int i;
-
- if (camel_disco_store_status (CAMEL_DISCO_STORE (store)) == CAMEL_DISCO_STORE_OFFLINE) {
- camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("This message is not currently available"));
- return NULL;
- }
-
- response = camel_imap_command (store, folder, ex,
- "UID FETCH %s BODY", uid);
- if (!response) {
- camel_folder_summary_info_free (folder->summary, mi);
- return NULL;
- }
-
- for (i = 0, body = NULL; i < response->untagged->len; i++) {
- fetch_data = parse_fetch_response (imap_folder, response->untagged->pdata[i]);
- if (fetch_data) {
- found_uid = g_datalist_get_data (&fetch_data, "UID");
- body = g_datalist_get_data (&fetch_data, "BODY");
- if (found_uid && body && !strcmp (found_uid, uid))
- break;
- g_datalist_clear (&fetch_data);
- fetch_data = NULL;
- body = NULL;
+
+ /* All this mess is so we silently retry a fetch if we fail with
+ service_unavailable, without an (equivalent) mess of gotos */
+ retry = 0;
+ do {
+ msg = NULL;
+ retry++;
+ camel_exception_clear(ex);
+
+ /* If we are online, make sure we're also connected */
+ if (camel_disco_store_status((CamelDiscoStore *)store) == CAMEL_DISCO_STORE_ONLINE
+ && !camel_imap_store_connected(store, ex))
+ goto fail;
+
+ /* If the message is small, fetch it in one piece. */
+ if (mi->size < IMAP_SMALL_BODY_SIZE) {
+ msg = get_message_simple (imap_folder, uid, NULL, ex);
+ } else if (content_info_incomplete (mi->content)) {
+
+ /* For larger messages, fetch the structure and build a message
+ * with offline parts. (We check mi->content->type rather than
+ * mi->content because camel_folder_summary_info_new always creates
+ * an empty content struct.)
+ */
+ CamelImapResponse *response;
+ GData *fetch_data = NULL;
+ char *body, *found_uid;
+ int i;
+
+ if (camel_disco_store_status (CAMEL_DISCO_STORE (store)) == CAMEL_DISCO_STORE_OFFLINE) {
+ camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
+ _("This message is not currently available"));
+ goto fail;
}
- }
- if (body)
- imap_parse_body ((const char **) &body, folder, mi->content);
+ response = camel_imap_command (store, folder, ex, "UID FETCH %s BODY", uid);
+ if (response) {
+ for (i = 0, body = NULL; i < response->untagged->len; i++) {
+ fetch_data = parse_fetch_response (imap_folder, response->untagged->pdata[i]);
+ if (fetch_data) {
+ found_uid = g_datalist_get_data (&fetch_data, "UID");
+ body = g_datalist_get_data (&fetch_data, "BODY");
+ if (found_uid && body && !strcmp (found_uid, uid))
+ break;
+ g_datalist_clear (&fetch_data);
+ fetch_data = NULL;
+ body = NULL;
+ }
+ }
- if (fetch_data)
- g_datalist_clear (&fetch_data);
+ if (body)
+ imap_parse_body ((const char **) &body, folder, mi->content);
- camel_imap_response_free (store, response);
+ if (fetch_data)
+ g_datalist_clear (&fetch_data);
- if (content_info_incomplete (mi->content)) {
- /* FETCH returned OK, but we didn't parse a BODY
- * response. Courier will return invalid BODY
- * responses for invalidly MIMEd messages, so
- * fall back to fetching the entire thing and
- * let the mailer's "bad MIME" code handle it.
- */
- camel_folder_summary_info_free (folder->summary, mi);
- return get_message_simple (imap_folder, uid, NULL, ex);
+ camel_imap_response_free (store, response);
+
+ /* FETCH returned OK, but we didn't parse a BODY
+ * response. Courier will return invalid BODY
+ * responses for invalidly MIMEd messages, so
+ * fall back to fetching the entire thing and
+ * let the mailer's "bad MIME" code handle it.
+ */
+ if (content_info_incomplete (mi->content))
+ msg = get_message_simple (imap_folder, uid, NULL, ex);
+ else
+ msg = get_message (imap_folder, uid, "", mi->content, ex);
+ }
}
- }
-
- msg = get_message (imap_folder, uid, "", mi->content, ex);
+ } while (msg == NULL
+ && retry < 2
+ && camel_exception_get_id(ex) == CAMEL_EXCEPTION_SERVICE_UNAVAILABLE);
+
/* FIXME, this shouldn't be done this way. */
- camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Source",
- store->base_url);
+ if (msg)
+ camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Source", store->base_url);
+fail:
camel_folder_summary_info_free (folder->summary, mi);
return msg;