diff options
-rw-r--r-- | mail/e-mail-store.c | 10 | ||||
-rw-r--r-- | mail/em-folder-tree-model.c | 3 | ||||
-rw-r--r-- | mail/em-folder-utils.c | 2 | ||||
-rw-r--r-- | mail/mail-folder-cache.c | 382 | ||||
-rw-r--r-- | mail/mail-folder-cache.h | 57 | ||||
-rw-r--r-- | mail/mail-send-recv.c | 2 | ||||
-rw-r--r-- | mail/mail-tools.c | 2 | ||||
-rw-r--r-- | mail/mail-vfolder.c | 7 | ||||
-rw-r--r-- | plugins/itip-formatter/itip-formatter.c | 3 |
9 files changed, 304 insertions, 164 deletions
diff --git a/mail/e-mail-store.c b/mail/e-mail-store.c index 749459d462..2cc03ad23c 100644 --- a/mail/e-mail-store.c +++ b/mail/e-mail-store.c @@ -147,9 +147,9 @@ mail_store_note_store_cb (CamelStore *store, if (!store_info->removed) { /* This keeps message counters up-to-date. */ if (store_info->vtrash != NULL) - mail_note_folder (store_info->vtrash); + mail_folder_cache_note_folder (mail_folder_cache_get_default (), store_info->vtrash); if (store_info->vjunk != NULL) - mail_note_folder (store_info->vjunk); + mail_folder_cache_note_folder (mail_folder_cache_get_default (), store_info->vjunk); } store_info_unref (store_info); @@ -177,7 +177,7 @@ mail_store_add (CamelStore *store, em_folder_tree_model_add_store ( default_model, store, store_info->display_name); - mail_note_store ( + mail_folder_cache_note_store (mail_folder_cache_get_default (), store, NULL, mail_store_note_store_cb, store_info_ref (store_info)); @@ -194,7 +194,7 @@ mail_store_add_local_done_cb (CamelStore *store, for (ii = 0; ii < E_MAIL_NUM_LOCAL_FOLDERS; ii++) { folder = e_mail_local_get_folder (ii); if (folder != NULL) - mail_note_folder (folder); + mail_folder_cache_note_folder (mail_folder_cache_get_default (), folder); } } @@ -367,7 +367,7 @@ e_mail_store_remove (CamelStore *store) camel_object_ref (store); g_hash_table_remove (store_table, store); - mail_note_store_remove (store); + mail_folder_cache_note_store_remove (mail_folder_cache_get_default (), store); default_model = em_folder_tree_model_get_default (); em_folder_tree_model_remove_store (default_model, store); diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c index b753cd7a84..4833277a71 100644 --- a/mail/em-folder-tree-model.c +++ b/mail/em-folder-tree-model.c @@ -550,7 +550,8 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, /* HACK2: We do the same to the draft folder */ /* This is duplicated in mail-folder-cache too, should perhaps be functionised */ unread = fi->unread; - if (mail_note_get_folder_from_uri(fi->uri, &folder) && folder) { + if (mail_folder_cache_get_folder_from_uri(mail_folder_cache_get_default (), + fi->uri, &folder) && folder) { is_drafts = em_utils_folder_is_drafts (folder, fi->uri); if (is_drafts || em_utils_folder_is_outbox (folder, fi->uri)) { diff --git a/mail/em-folder-utils.c b/mail/em-folder-utils.c index cf805f3b27..2838e829bd 100644 --- a/mail/em-folder-utils.c +++ b/mail/em-folder-utils.c @@ -448,7 +448,7 @@ em_folder_utils_delete_folder (CamelFolder *folder) return; } - if (mail_folder_cache_get_folder_info_flags (folder, &flags) && (flags & CAMEL_FOLDER_SYSTEM)) + if (mail_folder_cache_get_folder_info_flags (mail_folder_cache_get_default (), folder, &flags) && (flags & CAMEL_FOLDER_SYSTEM)) { e_alert_run_dialog_for_args (parent,"mail:no-delete-special-folder", folder->name, NULL); return; diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c index 59f823f81c..2bba2485d8 100644 --- a/mail/mail-folder-cache.c +++ b/mail/mail-folder-cache.c @@ -14,10 +14,12 @@ * * * Authors: - * Peter Williams <peterw@ximian.com> - * Michael Zucchi <notzed@ximian.com> + * Peter Williams <peterw@ximian.com> + * Michael Zucchi <notzed@ximian.com> + * Jonathon Jongsma <jonathon.jongsma@collabora.co.uk> * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * Copyright (C) 2009 Intel Corporation * */ @@ -71,9 +73,24 @@ /* This code is a mess, there is no reason it should be so complicated. */ -/* note that many things are effectively serialised by having them run in - the main loop thread which they need to do because of corba/gtk calls */ -G_LOCK_DEFINE_STATIC (stores); +G_DEFINE_TYPE (MailFolderCache, mail_folder_cache, G_TYPE_OBJECT) + +#define FOLDER_CACHE_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), MAIL_TYPE_FOLDER_CACHE, MailFolderCachePrivate)) + +struct _MailFolderCachePrivate +{ + guint ping_id; + /* Store to storeinfo table, active stores */ + GHashTable *stores; + GMutex *stores_mutex; + /* List of folder changes to be executed in gui thread */ + GQueue updates; + gint update_id; + /* hack for people who LIKE to have unsent count */ + gint count_sent; + gint count_trash; +}; struct _folder_info { struct _store_info *store_info; /* 'parent' link */ @@ -118,24 +135,13 @@ struct _store_info { GQueue folderinfo_updates; }; + static void folder_changed(CamelObject *o, gpointer event_data, gpointer user_data); static void folder_renamed(CamelObject *o, gpointer event_data, gpointer user_data); static void folder_finalised(CamelObject *o, gpointer event_data, gpointer user_data); -static guint ping_id = 0; static gboolean ping_cb (gpointer user_data); -/* Store to storeinfo table, active stores */ -static GHashTable *stores = NULL; - -/* List of folder changes to be executed in gui thread */ -static GQueue updates = G_QUEUE_INIT; -static gint update_id = -1; - -/* hack for people who LIKE to have unsent count */ -static gint count_sent = FALSE; -static gint count_trash = FALSE; - static void free_update(struct _folder_update *up) { @@ -152,18 +158,19 @@ free_update(struct _folder_update *up) } static void -real_flush_updates (void) +real_flush_updates (gpointer o, gpointer event_data, gpointer data) { EShell *shell; EMFolderTreeModel *default_model; struct _folder_update *up; + MailFolderCache *self = (MailFolderCache*) o; shell = e_shell_get_default (); default_model = em_folder_tree_model_get_default (); - G_LOCK (stores); - while ((up = g_queue_pop_head (&updates)) != NULL) { - G_UNLOCK (stores); + g_mutex_lock (self->priv->stores_mutex); + while ((up = g_queue_pop_head (&self->priv->updates)) != NULL) { + g_mutex_unlock (self->priv->stores_mutex); if (up->remove) { if (up->delete) { @@ -223,31 +230,31 @@ real_flush_updates (void) CamelFolder *folder = camel_store_get_folder (up->store, up->full_name, 0, NULL); if (folder) { - mail_note_folder (folder); + mail_folder_cache_note_folder (self, folder); camel_object_unref (folder); } } free_update(up); - G_LOCK (stores); + g_mutex_lock (self->priv->stores_mutex); } - update_id = -1; - G_UNLOCK (stores); + self->priv->update_id = -1; + g_mutex_unlock (self->priv->stores_mutex); } static void -flush_updates (void) +flush_updates (MailFolderCache *self) { - if (update_id == -1 && !g_queue_is_empty (&updates)) - update_id = mail_async_event_emit ( + if (self->priv->update_id == -1 && !g_queue_is_empty (&self->priv->updates)) + self->priv->update_id = mail_async_event_emit ( mail_async_event, MAIL_ASYNC_GUI, (MailAsyncFunc) real_flush_updates, - NULL, NULL, NULL); + self, NULL, NULL); } static void -unset_folder_info(struct _folder_info *mfi, gint delete, gint unsub) +unset_folder_info(MailFolderCache *self, struct _folder_info *mfi, gint delete, gint unsub) { struct _folder_update *up; @@ -256,9 +263,9 @@ unset_folder_info(struct _folder_info *mfi, gint delete, gint unsub) if (mfi->folder) { CamelFolder *folder = mfi->folder; - camel_object_unhook_event(folder, "folder_changed", folder_changed, NULL); - camel_object_unhook_event(folder, "renamed", folder_renamed, NULL); - camel_object_unhook_event(folder, "finalize", folder_finalised, NULL); + camel_object_unhook_event(folder, "folder_changed", folder_changed, self); + camel_object_unhook_event(folder, "renamed", folder_renamed, self); + camel_object_unhook_event(folder, "finalize", folder_finalised, self); } if ((mfi->flags & CAMEL_FOLDER_NOSELECT) == 0) { @@ -272,8 +279,8 @@ unset_folder_info(struct _folder_info *mfi, gint delete, gint unsub) camel_object_ref(up->store); up->uri = g_strdup(mfi->uri); - g_queue_push_head (&updates, up); - flush_updates(); + g_queue_push_head (&self->priv->updates, up); + flush_updates(self); } } @@ -308,7 +315,7 @@ free_folder_info(struct _folder_info *mfi) * it's correct. */ static void -update_1folder(struct _folder_info *mfi, gint new, const gchar *msg_uid, const gchar *msg_sender, const gchar *msg_subject, CamelFolderInfo *info) +update_1folder(MailFolderCache *self, struct _folder_info *mfi, gint new, const gchar *msg_uid, const gchar *msg_sender, const gchar *msg_subject, CamelFolderInfo *info) { struct _folder_update *up; CamelFolder *folder; @@ -320,10 +327,10 @@ update_1folder(struct _folder_info *mfi, gint new, const gchar *msg_uid, const g gboolean is_drafts = FALSE, is_outbox = FALSE; d(printf("update 1 folder '%s'\n", folder->full_name)); - if ((count_trash && (CAMEL_IS_VTRASH_FOLDER (folder))) + if ((self->priv->count_trash && (CAMEL_IS_VTRASH_FOLDER (folder))) || (is_drafts = em_utils_folder_is_drafts (folder, info ? info->uri : NULL)) || (is_outbox = em_utils_folder_is_outbox (folder, info ? info->uri : NULL)) - || (count_sent && em_utils_folder_is_sent (folder, info ? info->uri : NULL))) { + || (self->priv->count_sent && em_utils_folder_is_sent (folder, info ? info->uri : NULL))) { d(printf(" total count\n")); unread = camel_folder_get_message_count (folder); if (is_drafts || is_outbox) { @@ -362,19 +369,19 @@ update_1folder(struct _folder_info *mfi, gint new, const gchar *msg_uid, const g up->msg_sender = g_strdup (msg_sender); up->msg_subject = g_strdup (msg_subject); camel_object_ref(up->store); - g_queue_push_head (&updates, up); - flush_updates(); + g_queue_push_head (&self->priv->updates, up); + flush_updates(self); } static void -setup_folder(CamelFolderInfo *fi, struct _store_info *si) +setup_folder(MailFolderCache *self, CamelFolderInfo *fi, struct _store_info *si) { struct _folder_info *mfi; struct _folder_update *up; mfi = g_hash_table_lookup(si->folders, fi->full_name); if (mfi) { - update_1folder (mfi, 0, NULL, NULL, NULL, fi); + update_1folder (self, mfi, 0, NULL, NULL, NULL, fi); } else { d(printf("Adding new folder: %s (%s)\n", fi->full_name, fi->uri)); mfi = g_malloc0(sizeof(*mfi)); @@ -396,21 +403,21 @@ setup_folder(CamelFolderInfo *fi, struct _store_info *si) if ((fi->flags & CAMEL_FOLDER_NOSELECT) == 0) up->add = TRUE; - g_queue_push_head (&updates, up); - flush_updates(); + g_queue_push_head (&self->priv->updates, up); + flush_updates(self); } } static void -create_folders(CamelFolderInfo *fi, struct _store_info *si) +create_folders(MailFolderCache *self, CamelFolderInfo *fi, struct _store_info *si) { d(printf("Setup new folder: %s\n %s\n", fi->uri, fi->full_name)); while (fi) { - setup_folder(fi, si); + setup_folder(self, fi, si); if (fi->child) - create_folders(fi->child, si); + create_folders(self, fi->child, si); fi = fi->next; } @@ -433,6 +440,7 @@ folder_changed (CamelObject *o, gpointer event_data, gpointer user_data) gint i; guint32 flags; gchar *uid = NULL, *sender = NULL, *subject = NULL; + MailFolderCache *self = (MailFolderCache*) user_data; d(printf("folder '%s' changed\n", folder->full_name)); @@ -478,14 +486,14 @@ folder_changed (CamelObject *o, gpointer event_data, gpointer user_data) if (new > 0 || !last_newmail) time (&last_newmail); - G_LOCK (stores); - if (stores != NULL - && (si = g_hash_table_lookup(stores, store)) != NULL + g_mutex_lock (self->priv->stores_mutex); + if (self->priv->stores != NULL + && (si = g_hash_table_lookup(self->priv->stores, store)) != NULL && (mfi = g_hash_table_lookup(si->folders, folder->full_name)) != NULL && mfi->folder == folder) { - update_1folder (mfi, new, uid, sender, subject, NULL); + update_1folder (self, mfi, new, uid, sender, subject, NULL); } - G_UNLOCK (stores); + g_mutex_unlock (self->priv->stores_mutex); g_free (uid); g_free (sender); @@ -499,16 +507,17 @@ folder_finalised(CamelObject *o, gpointer event_data, gpointer user_data) CamelStore *store = folder->parent_store; struct _store_info *si; struct _folder_info *mfi; + MailFolderCache *self = (MailFolderCache*) user_data; d(printf("Folder finalised '%s'!\n", ((CamelFolder *)o)->full_name)); - G_LOCK (stores); - if (stores != NULL - && (si = g_hash_table_lookup(stores, store)) != NULL + g_mutex_lock (self->priv->stores_mutex); + if (self->priv->stores != NULL + && (si = g_hash_table_lookup(self->priv->stores, store)) != NULL && (mfi = g_hash_table_lookup(si->folders, folder->full_name)) != NULL && mfi->folder == folder) { mfi->folder = NULL; } - G_UNLOCK (stores); + g_mutex_unlock (self->priv->stores_mutex); } static void @@ -524,7 +533,7 @@ folder_renamed(CamelObject *o, gpointer event_data, gpointer user_data) /* Dont do anything, do it from the store rename event? */ } -void mail_note_folder(CamelFolder *folder) +void mail_folder_cache_note_folder(MailFolderCache *self, CamelFolder *folder) { CamelStore *store = folder->parent_store; struct _store_info *si; @@ -532,30 +541,30 @@ void mail_note_folder(CamelFolder *folder) d(printf("noting folder '%s'\n", folder->full_name)); - G_LOCK (stores); - if (stores == NULL - || (si = g_hash_table_lookup(stores, store)) == NULL + g_mutex_lock (self->priv->stores_mutex); + if (self->priv->stores == NULL + || (si = g_hash_table_lookup(self->priv->stores, store)) == NULL || (mfi = g_hash_table_lookup(si->folders, folder->full_name)) == NULL) { w(g_warning("Noting folder before store initialised")); - G_UNLOCK (stores); + g_mutex_unlock (self->priv->stores_mutex); return; } /* dont do anything if we already have this */ if (mfi->folder == folder) { - G_UNLOCK (stores); + g_mutex_unlock (self->priv->stores_mutex); return; } mfi->folder = folder; - update_1folder (mfi, 0, NULL, NULL, NULL, NULL); + update_1folder (self, mfi, 0, NULL, NULL, NULL, NULL); - G_UNLOCK (stores); + g_mutex_unlock (self->priv->stores_mutex); - camel_object_hook_event(folder, "folder_changed", folder_changed, NULL); - camel_object_hook_event(folder, "renamed", folder_renamed, NULL); - camel_object_hook_event(folder, "finalize", folder_finalised, NULL); + camel_object_hook_event(folder, "folder_changed", folder_changed, self); + camel_object_hook_event(folder, "renamed", folder_renamed, self); + camel_object_hook_event(folder, "finalize", folder_finalised, self); } static void @@ -563,14 +572,15 @@ store_folder_subscribed(CamelObject *o, gpointer event_data, gpointer data) { struct _store_info *si; CamelFolderInfo *fi = event_data; + MailFolderCache *self = (MailFolderCache*) data; d(printf("Store folder subscribed '%s' store '%s' \n", fi->full_name, camel_url_to_string(((CamelService *)o)->url, 0))); - G_LOCK (stores); - si = g_hash_table_lookup(stores, o); + g_mutex_lock (self->priv->stores_mutex); + si = g_hash_table_lookup(self->priv->stores, o); if (si) - setup_folder(fi, si); - G_UNLOCK (stores); + setup_folder(self, fi, si); + g_mutex_unlock (self->priv->stores_mutex); } static void @@ -585,8 +595,9 @@ static void store_folder_opened(CamelObject *o, gpointer event_data, gpointer data) { CamelFolder *folder = event_data; + MailFolderCache *self = (MailFolderCache*) data; - mail_note_folder(folder); + mail_folder_cache_note_folder(self, folder); } static void @@ -596,21 +607,22 @@ store_folder_unsubscribed(CamelObject *o, gpointer event_data, gpointer data) CamelFolderInfo *fi = event_data; struct _folder_info *mfi; CamelStore *store = (CamelStore *)o; + MailFolderCache *self = (MailFolderCache*) data; d(printf("Store Folder deleted: %s\n", fi->full_name)); - G_LOCK (stores); - si = g_hash_table_lookup(stores, store); + g_mutex_lock (self->priv->stores_mutex); + si = g_hash_table_lookup(self->priv->stores, store); if (si) { mfi = g_hash_table_lookup(si->folders, fi->full_name); if (mfi) { g_hash_table_remove(si->folders, mfi->full_name); g_hash_table_remove(si->folders_uri, mfi->uri); - unset_folder_info(mfi, TRUE, TRUE); + unset_folder_info(self, mfi, TRUE, TRUE); free_folder_info(mfi); } } - G_UNLOCK (stores); + g_mutex_unlock (self->priv->stores_mutex); } static void @@ -644,7 +656,7 @@ folder_to_url(CamelStore *store, const gchar *full_name) } static void -rename_folders(struct _store_info *si, const gchar *oldbase, const gchar *newbase, CamelFolderInfo *fi) +rename_folders(MailFolderCache *self, struct _store_info *si, const gchar *oldbase, const gchar *newbase, CamelFolderInfo *fi) { gchar *old, *olduri, *oldfile, *newuri, *newfile; struct _folder_info *mfi; @@ -695,13 +707,13 @@ rename_folders(struct _store_info *si, const gchar *oldbase, const gchar *newbas if ((fi->flags & CAMEL_FOLDER_NOSELECT) == 0) up->add = TRUE; - g_queue_push_tail (&updates, up); - flush_updates(); + g_queue_push_tail (&self->priv->updates, up); + flush_updates(self); #if 0 if (fi->sibling) - rename_folders(si, oldbase, newbase, fi->sibling, folders); + rename_folders(self, si, oldbase, newbase, fi->sibling, folders); if (fi->child) - rename_folders(si, oldbase, newbase, fi->child, folders); + rename_folders(self, si, oldbase, newbase, fi->child, folders); #endif /* rename the meta-data we maintain ourselves */ @@ -754,11 +766,12 @@ store_folder_renamed(CamelObject *o, gpointer event_data, gpointer data) CamelStore *store = (CamelStore *)o; CamelRenameInfo *info = event_data; struct _store_info *si; + MailFolderCache *self = (MailFolderCache*) data; d(printf("Folder renamed: oldbase = '%s' new->full = '%s'\n", info->old_base, info->new->full_name)); - G_LOCK (stores); - si = g_hash_table_lookup(stores, store); + g_mutex_lock (self->priv->stores_mutex); + si = g_hash_table_lookup(self->priv->stores, store); if (si) { GPtrArray *folders = g_ptr_array_new(); CamelFolderInfo *top; @@ -771,13 +784,13 @@ store_folder_renamed(CamelObject *o, gpointer event_data, gpointer data) top = folders->pdata[0]; for (i=0;i<folders->len;i++) { - rename_folders(si, info->old_base, top->full_name, folders->pdata[i]); + rename_folders(self, si, info->old_base, top->full_name, folders->pdata[i]); } g_ptr_array_free(folders, TRUE); } - G_UNLOCK (stores); + g_mutex_unlock (self->priv->stores_mutex); } struct _update_data { @@ -786,12 +799,14 @@ struct _update_data { gboolean (*done)(CamelStore *store, CamelFolderInfo *info, gpointer data); gpointer data; + MailFolderCache *cache; }; static void unset_folder_info_hash(gchar *path, struct _folder_info *mfi, gpointer data) { - unset_folder_info(mfi, FALSE, FALSE); + MailFolderCache *self = (MailFolderCache*) data; + unset_folder_info(self, mfi, FALSE, FALSE); } static void @@ -801,29 +816,29 @@ free_folder_info_hash(gchar *path, struct _folder_info *mfi, gpointer data) } void -mail_note_store_remove(CamelStore *store) +mail_folder_cache_note_store_remove(MailFolderCache *self, CamelStore *store) { struct _store_info *si; g_return_if_fail (CAMEL_IS_STORE(store)); - if (stores == NULL) + if (self->priv->stores == NULL) return; d(printf("store removed!!\n")); - G_LOCK (stores); - si = g_hash_table_lookup(stores, store); + g_mutex_lock (self->priv->stores_mutex); + si = g_hash_table_lookup(self->priv->stores, store); if (si) { GList *link; - g_hash_table_remove(stores, store); + g_hash_table_remove(self->priv->stores, store); - camel_object_unhook_event(store, "folder_opened", store_folder_opened, NULL); - camel_object_unhook_event(store, "folder_created", store_folder_created, NULL); - camel_object_unhook_event(store, "folder_deleted", store_folder_deleted, NULL); - camel_object_unhook_event(store, "folder_renamed", store_folder_renamed, NULL); - camel_object_unhook_event(store, "folder_subscribed", store_folder_subscribed, NULL); - camel_object_unhook_event(store, "folder_unsubscribed", store_folder_unsubscribed, NULL); - g_hash_table_foreach(si->folders, (GHFunc)unset_folder_info_hash, NULL); + camel_object_unhook_event(store, "folder_opened", store_folder_opened, self); + camel_object_unhook_event(store, "folder_created", store_folder_created, self); + camel_object_unhook_event(store, "folder_deleted", store_folder_deleted, self); + camel_object_unhook_event(store, "folder_renamed", store_folder_renamed, self); + camel_object_unhook_event(store, "folder_subscribed", store_folder_subscribed, self); + camel_object_unhook_event(store, "folder_unsubscribed", store_folder_unsubscribed, self); + g_hash_table_foreach(si->folders, (GHFunc)unset_folder_info_hash, self); link = g_queue_peek_head_link (&si->folderinfo_updates); @@ -844,7 +859,7 @@ mail_note_store_remove(CamelStore *store) g_free(si); } - G_UNLOCK (stores); + g_mutex_unlock (self->priv->stores_mutex); } static gboolean @@ -856,17 +871,17 @@ update_folders(CamelStore *store, CamelFolderInfo *fi, gpointer data) d(printf("Got folderinfo for store %s\n", store->parent_object.provider->protocol)); - G_LOCK (stores); - si = g_hash_table_lookup(stores, store); + g_mutex_lock (ud->cache->priv->stores_mutex); + si = g_hash_table_lookup(ud->cache->priv->stores, store); if (si && !ud->cancel) { /* the 'si' is still there, so we can remove ourselves from its list */ /* otherwise its not, and we're on our own and free anyway */ g_queue_remove (&si->folderinfo_updates, ud); if (fi) - create_folders(fi, si); + create_folders(ud->cache, fi, si); } - G_UNLOCK (stores); + g_mutex_unlock (ud->cache->priv->stores_mutex); if (ud->done) res = ud->done (store, fi, ud->data); @@ -943,11 +958,12 @@ ping_store (gpointer key, gpointer val, gpointer user_data) static gboolean ping_cb (gpointer user_data) { - G_LOCK (stores); + MailFolderCache *self = (MailFolderCache*) user_data; + g_mutex_lock (self->priv->stores_mutex); - g_hash_table_foreach (stores, ping_store, NULL); + g_hash_table_foreach (self->priv->stores, ping_store, NULL); - G_UNLOCK (stores); + g_mutex_unlock (self->priv->stores_mutex); return TRUE; } @@ -957,9 +973,9 @@ store_online_cb (CamelStore *store, gpointer data) { struct _update_data *ud = data; - G_LOCK (stores); + g_mutex_lock (ud->cache->priv->stores_mutex); - if (g_hash_table_lookup(stores, store) != NULL && !ud->cancel) { + if (g_hash_table_lookup(ud->cache->priv->stores, store) != NULL && !ud->cancel) { /* re-use the cancel id. we're already in the store update list too */ ud->id = mail_get_folderinfo(store, NULL, update_folders, ud); } else { @@ -968,34 +984,23 @@ store_online_cb (CamelStore *store, gpointer data) g_free(ud); } - G_UNLOCK (stores); + g_mutex_unlock (ud->cache->priv->stores_mutex); } void -mail_note_store(CamelStore *store, CamelOperation *op, - gboolean (*done)(CamelStore *store, CamelFolderInfo *info, gpointer data), gpointer data) +mail_folder_cache_note_store(MailFolderCache *self, CamelStore *store, CamelOperation *op, + NoteDoneFunc done, gpointer data) { struct _store_info *si; struct _update_data *ud; - const gchar *buf; - guint timeout; gint hook = 0; g_return_if_fail (CAMEL_IS_STORE(store)); g_return_if_fail (mail_in_main_thread()); - G_LOCK (stores); + g_mutex_lock (self->priv->stores_mutex); - if (stores == NULL) { - stores = g_hash_table_new(NULL, NULL); - count_sent = getenv("EVOLUTION_COUNT_SENT") != NULL; - count_trash = getenv("EVOLUTION_COUNT_TRASH") != NULL; - buf = getenv ("EVOLUTION_PING_TIMEOUT"); - timeout = buf ? strtoul (buf, NULL, 10) : 600; - ping_id = g_timeout_add_seconds (timeout, ping_cb, NULL); - } - - si = g_hash_table_lookup(stores, store); + si = g_hash_table_lookup(self->priv->stores, store); if (si == NULL) { d(printf("Noting a new store: %p: %s\n", store, camel_url_to_string(((CamelService *)store)->url, 0))); @@ -1005,7 +1010,7 @@ mail_note_store(CamelStore *store, CamelOperation *op, CAMEL_STORE_CLASS(CAMEL_OBJECT_GET_CLASS(store))->compare_folder_name); si->store = store; camel_object_ref((CamelObject *)store); - g_hash_table_insert(stores, store, si); + g_hash_table_insert(self->priv->stores, store, si); g_queue_init (&si->folderinfo_updates); hook = TRUE; } @@ -1014,6 +1019,7 @@ mail_note_store(CamelStore *store, CamelOperation *op, ud->done = done; ud->data = data; ud->cancel = 0; + ud->cache = self; /* We might get a race when setting up a store, such that it is still left in offline mode, after we've gone online. This catches and fixes it up when the shell opens us */ @@ -1039,16 +1045,16 @@ mail_note_store(CamelStore *store, CamelOperation *op, g_queue_push_tail (&si->folderinfo_updates, ud); - G_UNLOCK (stores); + g_mutex_unlock (self->priv->stores_mutex); /* there is potential for race here, but it is safe as we check for the store anyway */ if (hook) { - camel_object_hook_event(store, "folder_opened", store_folder_opened, NULL); - camel_object_hook_event(store, "folder_created", store_folder_created, NULL); - camel_object_hook_event(store, "folder_deleted", store_folder_deleted, NULL); - camel_object_hook_event(store, "folder_renamed", store_folder_renamed, NULL); - camel_object_hook_event(store, "folder_subscribed", store_folder_subscribed, NULL); - camel_object_hook_event(store, "folder_unsubscribed", store_folder_unsubscribed, NULL); + camel_object_hook_event(store, "folder_opened", store_folder_opened, self); + camel_object_hook_event(store, "folder_created", store_folder_created, self); + camel_object_hook_event(store, "folder_deleted", store_folder_deleted, self); + camel_object_hook_event(store, "folder_renamed", store_folder_renamed, self); + camel_object_hook_event(store, "folder_subscribed", store_folder_subscribed, self); + camel_object_hook_event(store, "folder_unsubscribed", store_folder_unsubscribed, self); } } @@ -1074,17 +1080,18 @@ static void storeinfo_find_folder_info(CamelStore *store, struct _store_info *si /* returns TRUE if the uri is available, folderp is set to a reffed folder if the folder has also already been opened */ -gint mail_note_get_folder_from_uri(const gchar *uri, CamelFolder **folderp) +gboolean +mail_folder_cache_get_folder_from_uri(MailFolderCache *self, const gchar *uri, CamelFolder **folderp) { struct _find_info fi = { uri, NULL, NULL }; - if (stores == NULL) + if (self->priv->stores == NULL) return FALSE; fi.url = camel_url_new(uri, NULL); - G_LOCK (stores); - g_hash_table_foreach(stores, (GHFunc)storeinfo_find_folder_info, &fi); + g_mutex_lock (self->priv->stores_mutex); + g_hash_table_foreach(self->priv->stores, (GHFunc)storeinfo_find_folder_info, &fi); if (folderp) { if (fi.fi && fi.fi->folder) { *folderp = fi.fi->folder; @@ -1093,7 +1100,7 @@ gint mail_note_get_folder_from_uri(const gchar *uri, CamelFolder **folderp) *folderp = NULL; } } - G_UNLOCK (stores); + g_mutex_unlock (self->priv->stores_mutex); camel_url_free(fi.url); @@ -1101,27 +1108,118 @@ gint mail_note_get_folder_from_uri(const gchar *uri, CamelFolder **folderp) } gboolean -mail_folder_cache_get_folder_info_flags (CamelFolder *folder, gint *flags) +mail_folder_cache_get_folder_info_flags (MailFolderCache *self, CamelFolder *folder, gint *flags) { gchar *uri = mail_tools_folder_to_url (folder); struct _find_info fi = { uri, NULL, NULL }; - if (stores == NULL) + if (self->priv->stores == NULL) return FALSE; fi.url = camel_url_new (uri, NULL); - G_LOCK (stores); - g_hash_table_foreach(stores, (GHFunc)storeinfo_find_folder_info, &fi); + g_mutex_lock (self->priv->stores_mutex); + g_hash_table_foreach(self->priv->stores, (GHFunc)storeinfo_find_folder_info, &fi); if (flags) { if (fi.fi) { *flags = fi.fi->flags; } } - G_UNLOCK (stores); + g_mutex_unlock (self->priv->stores_mutex); camel_url_free(fi.url); g_free (uri); return fi.fi != NULL; } + + +static void +mail_folder_cache_dispose (GObject *object) +{ + G_OBJECT_CLASS (mail_folder_cache_parent_class)->dispose (object); +} + +static void +mail_folder_cache_finalize (GObject *object) +{ + MailFolderCache *cache = (MailFolderCache*) object; + g_hash_table_destroy (cache->priv->stores); + g_mutex_free (cache->priv->stores_mutex); + + if (cache->priv->ping_id > 0) { + g_source_remove (cache->priv->ping_id); + cache->priv->ping_id = 0; + } + + if (cache->priv->update_id > 0) { + g_source_remove (cache->priv->update_id); + cache->priv->update_id = 0; + } + + G_OBJECT_CLASS (mail_folder_cache_parent_class)->finalize (object); +} + +static void +mail_folder_cache_class_init (MailFolderCacheClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (MailFolderCachePrivate)); + + object_class->dispose = mail_folder_cache_dispose; + object_class->finalize = mail_folder_cache_finalize; +} + +static void +mail_folder_cache_init (MailFolderCache *self) +{ + const gchar *buf; + guint timeout; + + self->priv = FOLDER_CACHE_PRIVATE (self); + + /* initialize values */ + self->priv->stores = g_hash_table_new(NULL, NULL); + self->priv->stores_mutex = g_mutex_new (); + + g_queue_init (&self->priv->updates); + self->priv->update_id = -1; + self->priv->count_sent = getenv("EVOLUTION_COUNT_SENT") != NULL; + self->priv->count_trash = getenv("EVOLUTION_COUNT_TRASH") != NULL; + + buf = getenv ("EVOLUTION_PING_TIMEOUT"); + timeout = buf ? strtoul (buf, NULL, 10) : 600; + self->priv->ping_id = g_timeout_add_seconds (timeout, ping_cb, self); +} + +/** + * mail_folder_cache_new: + * + * You probably don't want to use this. Use mail_folder_cache_get_default() + * instead + */ +MailFolderCache * +mail_folder_cache_new (void) +{ + return g_object_new (MAIL_TYPE_FOLDER_CACHE, NULL); +} + +static MailFolderCache *default_cache = NULL; +G_LOCK_DEFINE_STATIC (default_cache); + +/** + * mail_folder_cache_get_default: + * + * Get the default folder cache object + */ +MailFolderCache * +mail_folder_cache_get_default (void) +{ + G_LOCK (default_cache); + if (!default_cache) + default_cache = g_object_new (MAIL_TYPE_FOLDER_CACHE, NULL); + G_UNLOCK (default_cache); + + return default_cache; +} diff --git a/mail/mail-folder-cache.h b/mail/mail-folder-cache.h index 41f36ac0cf..762152ffdd 100644 --- a/mail/mail-folder-cache.h +++ b/mail/mail-folder-cache.h @@ -14,10 +14,12 @@ * * * Authors: - * Peter Williams <peterw@ximian.com> - * Michael Zucchi <notzed@ximian.com> + * Peter Williams <peterw@ximian.com> + * Michael Zucchi <notzed@ximian.com> + * Jonathon Jongsma <jonathon.jongsma@collabora.co.uk> * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * Copyright (C) 2009 Intel Corporation * */ @@ -26,29 +28,64 @@ #ifndef _MAIL_FOLDER_CACHE_H #define _MAIL_FOLDER_CACHE_H +#include <glib-object.h> #include <camel/camel-store.h> +G_BEGIN_DECLS + +/* Stores information about open folders */ + +#define MAIL_TYPE_FOLDER_CACHE mail_folder_cache_get_type() +#define MAIL_FOLDER_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAIL_TYPE_FOLDER_CACHE, MailFolderCache)) +#define MAIL_FOLDER_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MAIL_TYPE_FOLDER_CACHE, MailFolderCacheClass)) +#define MAIL_IS_FOLDER_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAIL_TYPE_FOLDER_CACHE)) +#define MAIL_IS_FOLDER_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MAIL_TYPE_FOLDER_CACHE)) +#define MAIL_FOLDER_CACHE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MAIL_TYPE_FOLDER_CACHE, MailFolderCacheClass)) + +typedef struct _MailFolderCache MailFolderCache; +typedef struct _MailFolderCacheClass MailFolderCacheClass; +typedef struct _MailFolderCachePrivate MailFolderCachePrivate; + +struct _MailFolderCache +{ + GObject parent; + + MailFolderCachePrivate *priv; +}; + +struct _MailFolderCacheClass +{ + GObjectClass parent_class; +}; + +GType mail_folder_cache_get_type (void) G_GNUC_CONST; + +MailFolderCache *mail_folder_cache_new (void); + +MailFolderCache *mail_folder_cache_get_default (void); + +typedef gboolean (*NoteDoneFunc)(CamelStore *store, CamelFolderInfo *info, gpointer data); /* Add a store whose folders should appear in the shell The folders are scanned from the store, and/or added at runtime via the folder_created event. The 'done' function returns if we can free folder info. */ -void -mail_note_store (CamelStore *store, CamelOperation *op, - gboolean (*done) (CamelStore *store, CamelFolderInfo *info, gpointer data), - gpointer data); +void mail_folder_cache_note_store (MailFolderCache *self, + CamelStore *store, CamelOperation *op, + NoteDoneFunc func, gpointer data); /* de-note a store */ -void mail_note_store_remove (CamelStore *store); +void mail_folder_cache_note_store_remove (MailFolderCache *self, CamelStore *store); /* When a folder has been opened, notify it for watching. The folder must have already been created on the store (which has already been noted) before the folder can be opened */ -void mail_note_folder (CamelFolder *folder); +void mail_folder_cache_note_folder (MailFolderCache *self, CamelFolder *folder); /* Returns true if a folder is available (yet), and also sets *folderp (if supplied) to a (referenced) copy of the folder if it has already been opened */ -gint mail_note_get_folder_from_uri (const gchar *uri, CamelFolder **folderp); -gboolean mail_folder_cache_get_folder_info_flags (CamelFolder *folder, gint *flags); +gboolean mail_folder_cache_get_folder_from_uri (MailFolderCache *self, const gchar *uri, CamelFolder **folderp); +gboolean mail_folder_cache_get_folder_info_flags (MailFolderCache *self, CamelFolder *folder, gint *flags); +G_END_DECLS #endif diff --git a/mail/mail-send-recv.c b/mail/mail-send-recv.c index b5e135c227..be806ef260 100644 --- a/mail/mail-send-recv.c +++ b/mail/mail-send-recv.c @@ -960,7 +960,7 @@ receive_update_got_store (gchar *uri, CamelStore *store, gpointer data) struct _send_info *info = data; if (store) { - mail_note_store( + mail_folder_cache_note_store(mail_folder_cache_get_default (), store, info->cancel, receive_update_got_folderinfo, info); } else { diff --git a/mail/mail-tools.c b/mail/mail-tools.c index 1403605b33..45f502ecf0 100644 --- a/mail/mail-tools.c +++ b/mail/mail-tools.c @@ -349,7 +349,7 @@ mail_tool_uri_to_folder (const gchar *uri, guint32 flags, CamelException *ex) } if (folder) - mail_note_folder (folder); + mail_folder_cache_note_folder (mail_folder_cache_get_default (), folder); camel_url_free (url); g_free(curi); diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c index d95ee2b876..f58886b214 100644 --- a/mail/mail-vfolder.c +++ b/mail/mail-vfolder.c @@ -255,7 +255,9 @@ vfolder_adduri_exec (struct _adduri_msg *m) /* we dont try lookup the cache if we are removing it, its no longer there */ - if (!m->remove && !mail_note_get_folder_from_uri(m->uri, &folder)) { + if (!m->remove && + !mail_folder_cache_get_folder_from_uri(mail_folder_cache_get_default (), + m->uri, &folder)) { g_warning("Folder '%s' disappeared while I was adding/remove it to/from my vfolder", m->uri); return; } @@ -707,7 +709,8 @@ rule_add_sources(GList *l, GList **sources_folderp, GList **sources_urip) while (l) { gchar *curi = em_uri_to_camel(l->data); - if (mail_note_get_folder_from_uri(curi, &newfolder)) { + if (mail_folder_cache_get_folder_from_uri + (mail_folder_cache_get_default (), curi, &newfolder)) { if (newfolder) sources_folder = g_list_append(sources_folder, newfolder); else diff --git a/plugins/itip-formatter/itip-formatter.c b/plugins/itip-formatter/itip-formatter.c index 57e9bc2ad8..4ce4b430d5 100644 --- a/plugins/itip-formatter/itip-formatter.c +++ b/plugins/itip-formatter/itip-formatter.c @@ -2117,7 +2117,8 @@ in_proper_folder (CamelFolder *folder) uri = mail_tools_folder_to_url (folder); - if (mail_folder_cache_get_folder_info_flags (folder, &flags)) { + if (mail_folder_cache_get_folder_info_flags (mail_folder_cache_get_default (), + folder, &flags)) { /* it should be neither trash nor junk folder, */ res = ((flags & CAMEL_FOLDER_TYPE_TRASH) != CAMEL_FOLDER_TYPE_TRASH && (flags & CAMEL_FOLDER_TYPE_JUNK) != CAMEL_FOLDER_TYPE_JUNK && |