aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mail/ChangeLog23
-rw-r--r--mail/em-folder-browser.c2
-rw-r--r--mail/em-utils.c130
-rw-r--r--mail/mail-mt.c54
-rw-r--r--mail/mail-mt.h5
5 files changed, 166 insertions, 48 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index 5baa96fed8..445db01311 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,26 @@
+2004-06-16 Not Zed <NotZed@Ximian.com>
+
+ ** See #56479.
+
+ * em-utils.c (em_utils_in_addressbook): use the main thread to
+ setup the addressbook list.
+ (em_utils_in_addressbook): only check against the "completion"
+ sources, not all of them.
+
+2004-06-15 Not Zed <NotZed@Ximian.com>
+
+ * em-folder-browser.c (emfb_mail_stop): call mail_cancel_all to
+ implement the stop button.
+
+ * em-utils.c (emu_addr_sources_refresh): don't unref the group
+ list, otherwise the sources become broken now (?).
+ (em_utils_in_addressbook): add some locking. add cancellation.
+ this is almost certainly going to cause issues.
+
+ * mail-mt.c (mail_cancel_hook_add, mail_cancel_hook_remove)
+ (mail_cancel_all): new functions to implement a global mailer stop
+ button.
+
2004-06-15 Jeffrey Stedfast <fejj@ximian.com>
* mail-ops.c (save_part_save): This code no longer needs to do
diff --git a/mail/em-folder-browser.c b/mail/em-folder-browser.c
index e09329f733..cb4d25b565 100644
--- a/mail/em-folder-browser.c
+++ b/mail/em-folder-browser.c
@@ -632,7 +632,7 @@ emfb_mail_compose(BonoboUIComponent *uid, void *data, const char *path)
static void
emfb_mail_stop(BonoboUIComponent *uid, void *data, const char *path)
{
- camel_operation_cancel(NULL);
+ mail_cancel_all();
}
static void
diff --git a/mail/em-utils.c b/mail/em-utils.c
index b0bed74546..82a5d73f4f 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -1663,42 +1663,41 @@ struct _addr_node {
#define EMU_ADDR_CACHE_TIME (60*30) /* in seconds */
-static GSList *emu_addr_sources;
+static pthread_mutex_t emu_addr_lock = PTHREAD_MUTEX_INITIALIZER;
+static ESourceList *emu_addr_list;
static GHashTable *emu_addr_cache;
-static void
-emu_addr_sources_refresh(void)
+/* runs sync, in main thread */
+static void *
+emu_addr_setup(void *dummy)
{
GError *err = NULL;
- ESourceList *list;
- GSList *g, *s, *groups, *sources;
- g_slist_foreach(emu_addr_sources, (GFunc)g_object_unref, NULL);
- g_slist_free(emu_addr_sources);
- emu_addr_sources = NULL;
+ emu_addr_cache = g_hash_table_new(g_str_hash, g_str_equal);
- if (!e_book_get_addressbooks(&list, &err)) {
+ if (!e_book_get_addressbooks(&emu_addr_list, &err))
g_error_free(err);
- return;
- }
- groups = e_source_list_peek_groups(list);
- for (g=groups;g;g=g_slist_next(g)) {
- sources = e_source_group_peek_sources((ESourceGroup *)g->data);
- for (s=sources;s;s=g_slist_next(s)) {
- emu_addr_sources = g_slist_prepend(emu_addr_sources, g_object_ref(s->data));
- }
- }
+ return NULL;
+}
- g_object_unref(list);
+static void
+emu_addr_cancel_book(void *data)
+{
+ EBook *book = data;
+ GError *err = NULL;
+
+ /* we dunna care if this fails, its just the best we can try */
+ e_book_cancel(book, &err);
+ g_clear_error(&err);
}
gboolean
em_utils_in_addressbook(CamelInternetAddress *iaddr)
{
GError *err = NULL;
- GSList *s;
- int found = FALSE;
+ GSList *s, *g, *addr_sources = NULL;
+ int stop = FALSE, found = FALSE;
EBookQuery *query;
const char *addr;
struct _addr_node *node;
@@ -1708,69 +1707,106 @@ em_utils_in_addressbook(CamelInternetAddress *iaddr)
if (!camel_internet_address_get(iaddr, 0, NULL, &addr))
return FALSE;
+ pthread_mutex_lock(&emu_addr_lock);
+
if (emu_addr_cache == NULL) {
- emu_addr_cache = g_hash_table_new(g_str_hash, g_str_equal);
- emu_addr_sources_refresh();
+ mail_call_main(MAIL_CALL_p_p, emu_addr_setup, NULL);
+ }
+
+ if (emu_addr_list == NULL) {
+ pthread_mutex_unlock(&emu_addr_lock);
+ return FALSE;
}
now = time(0);
- printf("Checking '%s' is in addressbook", addr);
+ d(printf("Checking '%s' is in addressbook", addr));
node = g_hash_table_lookup(emu_addr_cache, addr);
if (node) {
- printf(" -> cached, found %s\n", node->found?"yes":"no");
- if (node->stamp + EMU_ADDR_CACHE_TIME > now)
- return node->found;
- printf(" but expired!\n");
+ d(printf(" -> cached, found %s\n", node->found?"yes":"no"));
+ if (node->stamp + EMU_ADDR_CACHE_TIME > now) {
+ found = node->found;
+ pthread_mutex_unlock(&emu_addr_lock);
+ return found;
+ }
+ d(printf(" but expired!\n"));
} else {
- printf(" -> not found in cache\n");
+ d(printf(" -> not found in cache\n"));
node = g_malloc0(sizeof(*node));
node->addr = g_strdup(addr);
+ g_hash_table_insert(emu_addr_cache, node->addr, node);
}
query = e_book_query_field_test(E_CONTACT_EMAIL, E_BOOK_QUERY_IS, addr);
- for (s = emu_addr_sources;!found && s;s=g_slist_next(s)) {
+ /* FIXME: this aint threadsafe by any measure, but what can you do eh??? */
+
+ for (g = e_source_list_peek_groups(emu_addr_list);g;g=g_slist_next(g)) {
+ for (s = e_source_group_peek_sources((ESourceGroup *)g->data);s;s=g_slist_next(s)) {
+ ESource *src = s->data;
+ const char *completion = e_source_get_property (src, "completion");
+
+ if (completion && !g_ascii_strcasecmp (completion, "true")) {
+ addr_sources = g_slist_prepend(addr_sources, src);
+ g_object_ref(src);
+ }
+ }
+ }
+
+ for (s = addr_sources;!stop && !found && s;s=g_slist_next(s)) {
ESource *source = s->data;
GList *contacts;
EBook *book;
+ void *hook;
- printf(" checking '%s'\n", e_source_get_uri(source));
+ d(printf(" checking '%s'\n", e_source_get_uri(source)));
+ /* could this take a while? no way to cancel it? */
book = e_book_new(source, &err);
- if (!book
- || !e_book_open(book, TRUE, &err)) {
- printf("couldn't load source?\n");
+ if (book == NULL) {
+ g_warning("Unable to create addressbook: %s", err->message);
g_clear_error(&err);
- g_object_unref(book);
continue;
}
- if (!e_book_get_contacts(book, query, &contacts, &err)) {
- printf("Can't get contacts?\n");
- g_clear_error(&err);
+ hook = mail_cancel_hook_add(emu_addr_cancel_book, book);
+
+ /* ignore errors, but cancellation errors we don't try to go further either */
+ if (!e_book_open(book, TRUE, &err)
+ || !e_book_get_contacts(book, query, &contacts, &err)) {
+ stop = err->domain == E_BOOK_ERROR && err->code == E_BOOK_ERROR_CANCELLED;
+ mail_cancel_hook_remove(hook);
g_object_unref(book);
+ g_warning("Can't get contacts: %s", err->message);
+ g_clear_error(&err);
continue;
}
- found = contacts != NULL;
+ mail_cancel_hook_remove(hook);
- printf(" %s\n", found?"found":"not found");
+ if (contacts != NULL) {
+ found = TRUE;
+ g_list_foreach(contacts, (GFunc)g_object_unref, NULL);
+ g_list_free(contacts);
+ }
- g_list_foreach(contacts, (GFunc)g_object_unref, NULL);
- g_list_free(contacts);
+ d(printf(" %s\n", stop?"found":"not found"));
g_object_unref(book);
}
- e_book_query_unref(query);
+ g_slist_free(addr_sources);
- node->found = found;
- node->stamp = now;
+ if (!stop) {
+ node->found = found;
+ node->stamp = now;
+ }
+
+ e_book_query_unref(query);
- g_hash_table_insert(emu_addr_cache, node->addr, node);
+ pthread_mutex_unlock(&emu_addr_lock);
return found;
}
@@ -1779,7 +1815,7 @@ em_utils_in_addressbook(CamelInternetAddress *iaddr)
* em_utils_snoop_type:
* @part:
*
- * Rries to snoop the mime type of a part.
+ * Tries to snoop the mime type of a part.
*
* Return value: NULL if unknown (more likely application/octet-stream).
**/
diff --git a/mail/mail-mt.c b/mail/mail-mt.c
index 1581d283bb..457fd4c43f 100644
--- a/mail/mail-mt.c
+++ b/mail/mail-mt.c
@@ -352,6 +352,60 @@ void mail_msg_wait_all(void)
}
}
+/* **************************************** */
+struct _cancel_hook_data {
+ struct _cancel_hook_data *next;
+ struct _cancel_hook_data *prev;
+
+ GDestroyNotify func;
+ void *data;
+};
+
+static EDList cancel_hook_list = E_DLIST_INITIALISER(cancel_hook_list);
+
+void *mail_cancel_hook_add(GDestroyNotify func, void *data)
+{
+ struct _cancel_hook_data *d;
+
+ d = g_malloc0(sizeof(*d));
+ d->func = func;
+ d->data = data;
+
+ MAIL_MT_LOCK(mail_msg_lock);
+ e_dlist_addtail(&cancel_hook_list, (EDListNode *)d);
+ MAIL_MT_UNLOCK(mail_msg_lock);
+
+ return (void *)d;
+}
+
+void mail_cancel_hook_remove(void *handle)
+{
+ struct _cancel_hook_data *d = handle;
+
+ MAIL_MT_LOCK(mail_msg_lock);
+ e_dlist_remove((EDListNode *)d);
+ MAIL_MT_UNLOCK(mail_msg_lock);
+ g_free(d);
+}
+
+void mail_cancel_all(void)
+{
+ struct _cancel_hook_data *d, *n;
+
+ camel_operation_cancel(NULL);
+
+ /* I can ssee a deadlock coming on ... */
+ MAIL_MT_LOCK(mail_msg_lock);
+ d = (struct _cancel_hook_data *)cancel_hook_list.head;
+ n = d->next;
+ while (n) {
+ d->func(d->data);
+ d = n;
+ n = n->next;
+ }
+ MAIL_MT_UNLOCK(mail_msg_lock);
+}
+
EMsgPort *mail_gui_port;
static GIOChannel *mail_gui_channel;
static guint mail_gui_watch;
diff --git a/mail/mail-mt.h b/mail/mail-mt.h
index b6d402199f..23baf60a56 100644
--- a/mail/mail-mt.h
+++ b/mail/mail-mt.h
@@ -60,6 +60,11 @@ void mail_msg_wait(unsigned int msgid);
void mail_msg_wait_all(void);
int mail_msg_active(unsigned int msgid);
+/* To implement the stop button */
+void *mail_cancel_hook_add(GDestroyNotify func, void *data);
+void mail_cancel_hook_remove(void *handle);
+void mail_cancel_all(void);
+
/* request a string/password */
char *mail_get_password (CamelService *service, const char *prompt,
gboolean secret, gboolean *cache);