[evolution] MailFolderCache can sometimes block folder 'changed' notifications
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] MailFolderCache can sometimes block folder 'changed' notifications
- Date: Wed, 3 May 2017 09:49:53 +0000 (UTC)
commit 3df39f3d08e70f3f028cc08d61ac23ee03828f24
Author: Milan Crha <mcrha redhat com>
Date: Wed May 3 11:45:04 2017 +0200
MailFolderCache can sometimes block folder 'changed' notifications
One way to have lost folder 'changed' notifications from MailFolderCache
is to fail to connect to the account after start, in which case the folder
tree in the Mail view doesn't update unread counts properly. It had been
due to the MailFolderCache still considering the store being initializing
for the first time, while piling the folder notifications to be emitted
when the initialization of the store is over.
src/libemail-engine/mail-folder-cache.c | 36 +++++++++++++++++++++++++------
1 files changed, 29 insertions(+), 7 deletions(-)
---
diff --git a/src/libemail-engine/mail-folder-cache.c b/src/libemail-engine/mail-folder-cache.c
index 5662019..cfe0503 100644
--- a/src/libemail-engine/mail-folder-cache.c
+++ b/src/libemail-engine/mail-folder-cache.c
@@ -91,6 +91,12 @@ enum {
static guint signals[LAST_SIGNAL];
+typedef enum {
+ E_FIRST_UPDATE_RUNNING,
+ E_FIRST_UPDATE_FAILED,
+ E_FIRST_UPDATE_DONE
+} EFirstUpdateState;
+
struct _StoreInfo {
volatile gint ref_count;
@@ -107,7 +113,7 @@ struct _StoreInfo {
gulong reachable_handler_id;
GHashTable *folder_info_ht; /* by full_name */
- gboolean first_update; /* TRUE, then FALSE forever */
+ EFirstUpdateState first_update;
GSList *pending_folder_notes; /* Gather note_folder calls during first_update period */
/* Hold a reference to keep them alive. */
@@ -263,7 +269,7 @@ store_info_new (CamelStore *store)
store_info = g_slice_new0 (StoreInfo);
store_info->ref_count = 1;
store_info->store = g_object_ref (store);
- store_info->first_update = TRUE;
+ store_info->first_update = E_FIRST_UPDATE_RUNNING;
store_info->folder_info_ht = g_hash_table_new_full (
(GHashFunc) g_str_hash,
@@ -2036,7 +2042,7 @@ mail_folder_cache_first_update (MailFolderCache *cache,
g_object_unref (session);
g_mutex_lock (&store_info->lock);
- store_info->first_update = FALSE;
+ store_info->first_update = E_FIRST_UPDATE_DONE;
folders = store_info->pending_folder_notes;
store_info->pending_folder_notes = NULL;
g_mutex_unlock (&store_info->lock);
@@ -2060,6 +2066,7 @@ mail_folder_cache_note_store_thread (GSimpleAsyncResult *simple,
StoreInfo *store_info;
GQueue result_queue = G_QUEUE_INIT;
AsyncContext *async_context;
+ gboolean success = FALSE;
GError *local_error = NULL;
cache = MAIL_FOLDER_CACHE (source_object);
@@ -2132,17 +2139,22 @@ mail_folder_cache_note_store_thread (GSimpleAsyncResult *simple,
/* Do some extra work for the first update. */
g_mutex_lock (&store_info->lock);
- if (store_info->first_update) {
+ if (store_info->first_update != E_FIRST_UPDATE_DONE) {
g_mutex_unlock (&store_info->lock);
mail_folder_cache_first_update (cache, store_info);
} else {
g_mutex_unlock (&store_info->lock);
}
+ success = TRUE;
exit:
/* We don't want finish() functions being invoked while holding a
* locked mutex, so flush the StoreInfo's queue to a local queue. */
g_mutex_lock (&store_info->lock);
+
+ if (store_info->first_update != E_FIRST_UPDATE_DONE)
+ store_info->first_update = success ? E_FIRST_UPDATE_DONE : E_FIRST_UPDATE_FAILED;
+
e_queue_transfer (&store_info->folderinfo_updates, &result_queue);
g_mutex_unlock (&store_info->lock);
@@ -2202,6 +2214,9 @@ mail_folder_cache_note_store (MailFolderCache *cache,
g_mutex_lock (&store_info->lock);
+ if (store_info->first_update != E_FIRST_UPDATE_DONE)
+ store_info->first_update = E_FIRST_UPDATE_RUNNING;
+
g_queue_push_tail (
&store_info->folderinfo_updates,
g_object_ref (simple));
@@ -2283,18 +2298,23 @@ mail_folder_cache_note_folder (MailFolderCache *cache,
* warnings on startup which might be worth tracking down. */
if (folder_info == NULL) {
StoreInfo *store_info;
- gboolean retry = FALSE;
+ gboolean retry = FALSE, renote_store = FALSE;
store_info = mail_folder_cache_ref_store_info (cache, parent_store);
if (!store_info)
return;
g_mutex_lock (&store_info->lock);
- if (store_info->first_update) {
+ if (store_info->first_update != E_FIRST_UPDATE_DONE) {
/* The first update did not finish yet, thus add this as a pending
folder to be noted once the first update finishes */
store_info->pending_folder_notes = g_slist_prepend (
store_info->pending_folder_notes, g_object_ref (folder));
+
+ if (store_info->first_update == E_FIRST_UPDATE_FAILED) {
+ store_info->first_update = E_FIRST_UPDATE_RUNNING;
+ renote_store = TRUE;
+ }
} else {
/* It can be that certain threading interleaving made
the first store update finished before we reached
@@ -2305,7 +2325,9 @@ mail_folder_cache_note_folder (MailFolderCache *cache,
store_info_unref (store_info);
- if (retry)
+ if (renote_store)
+ mail_folder_cache_note_store (cache, parent_store, NULL, NULL, NULL);
+ else if (retry)
folder_info = mail_folder_cache_ref_folder_info (
cache, parent_store, full_name);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]