use camel debug to add some debug here.
authorNot Zed <NotZed@Ximian.com>
Tue, 23 Mar 2004 08:48:50 +0000 (08:48 +0000)
committerMichael Zucci <zucchi@src.gnome.org>
Tue, 23 Mar 2004 08:48:50 +0000 (08:48 +0000)
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.

camel/ChangeLog
camel/Makefile.am
camel/camel-debug.c [new file with mode: 0644]
camel/camel-debug.h [new file with mode: 0644]
camel/camel-exception.c
camel/camel.c
camel/providers/imap/camel-imap-folder.c

index dd0cf84..6ba3a3b 100644 (file)
@@ -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.
index 07bfdba..4432d0e 100644 (file)
@@ -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 (file)
index 0000000..7c16c9a
--- /dev/null
@@ -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 (file)
index 0000000..7ebf1eb
--- /dev/null
@@ -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 */
index 95e3766..c67ab66 100644 (file)
 #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;
index 8241b5b..09ba07c 100644 (file)
@@ -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();
index 7db367a..f2b6207 100644 (file)
@@ -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;