[evolution-data-server] [IMAPx] Enhance processing of server IDLE notifications
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] [IMAPx] Enhance processing of server IDLE notifications
- Date: Tue, 20 Feb 2018 12:01:36 +0000 (UTC)
commit d05386e3adbedd25163933512fc648a2c7bd4022
Author: Milan Crha <mcrha redhat com>
Date: Tue Feb 20 13:01:41 2018 +0100
[IMAPx] Enhance processing of server IDLE notifications
It could happen that some IDLE notifications had not been reflected
in the UI, showing incorrect folder content to the user.
.../providers/imapx/camel-imapx-conn-manager.c | 18 +++++
src/camel/providers/imapx/camel-imapx-server.c | 66 +++++++++++++++----
2 files changed, 70 insertions(+), 14 deletions(-)
---
diff --git a/src/camel/providers/imapx/camel-imapx-conn-manager.c
b/src/camel/providers/imapx/camel-imapx-conn-manager.c
index da7d32d..02bcd8f 100644
--- a/src/camel/providers/imapx/camel-imapx-conn-manager.c
+++ b/src/camel/providers/imapx/camel-imapx-conn-manager.c
@@ -70,6 +70,9 @@ struct _CamelIMAPXConnManagerPrivate {
GMutex busy_mailboxes_lock; /* used for both busy_mailboxes and idle_mailboxes */
GHashTable *busy_mailboxes; /* CamelIMAPXMailbox ~> gint */
GHashTable *idle_mailboxes; /* CamelIMAPXMailbox ~> gint */
+
+ GMutex idle_refresh_lock;
+ GHashTable *idle_refresh_mailboxes; /* not-referenced CamelIMAPXMailbox, just to use for pointer
comparison ~> NULL */
};
struct _ConnectionInfo {
@@ -138,6 +141,10 @@ imapx_conn_manager_idle_mailbox_refresh_thread (gpointer user_data)
local_error ? local_error->message : "Unknown error");
}
+ g_mutex_lock (&data->conn_man->priv->idle_refresh_lock);
+ g_hash_table_remove (data->conn_man->priv->idle_refresh_mailboxes, data->mailbox);
+ g_mutex_unlock (&data->conn_man->priv->idle_refresh_lock);
+
mailbox_refresh_data_free (data);
g_clear_error (&local_error);
@@ -157,6 +164,13 @@ imapx_conn_manager_refresh_mailbox_cb (CamelIMAPXServer *is,
g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
g_return_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (conn_man));
+ g_mutex_lock (&conn_man->priv->idle_refresh_lock);
+ if (!g_hash_table_insert (conn_man->priv->idle_refresh_mailboxes, mailbox, NULL)) {
+ g_mutex_unlock (&conn_man->priv->idle_refresh_lock);
+ return;
+ }
+ g_mutex_unlock (&conn_man->priv->idle_refresh_lock);
+
data = g_new0 (MailboxRefreshData, 1);
data->conn_man = g_object_ref (conn_man);
data->mailbox = g_object_ref (mailbox);
@@ -627,6 +641,8 @@ imapx_conn_manager_finalize (GObject *object)
g_mutex_clear (&priv->busy_mailboxes_lock);
g_hash_table_destroy (priv->busy_mailboxes);
g_hash_table_destroy (priv->idle_mailboxes);
+ g_mutex_clear (&priv->idle_refresh_lock);
+ g_hash_table_destroy (priv->idle_refresh_mailboxes);
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (camel_imapx_conn_manager_parent_class)->finalize (object);
@@ -679,10 +695,12 @@ camel_imapx_conn_manager_init (CamelIMAPXConnManager *conn_man)
g_cond_init (&conn_man->priv->busy_connections_cond);
g_weak_ref_init (&conn_man->priv->store, NULL);
g_mutex_init (&conn_man->priv->busy_mailboxes_lock);
+ g_mutex_init (&conn_man->priv->idle_refresh_lock);
conn_man->priv->last_tagprefix = 'A' - 1;
conn_man->priv->busy_mailboxes = g_hash_table_new_full (g_direct_hash, g_direct_equal,
g_object_unref, NULL);
conn_man->priv->idle_mailboxes = g_hash_table_new_full (g_direct_hash, g_direct_equal,
g_object_unref, NULL);
+ conn_man->priv->idle_refresh_mailboxes = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
NULL);
}
static gchar
diff --git a/src/camel/providers/imapx/camel-imapx-server.c b/src/camel/providers/imapx/camel-imapx-server.c
index d6969a6..d94a4f7 100644
--- a/src/camel/providers/imapx/camel-imapx-server.c
+++ b/src/camel/providers/imapx/camel-imapx-server.c
@@ -796,9 +796,36 @@ imapx_untagged_expunge (CamelIMAPXServer *is,
/* Ignore EXPUNGE responses when not running a COPY(MOVE)_MESSAGE job */
if (!is->priv->current_command || (is->priv->current_command->job_kind !=
CAMEL_IMAPX_JOB_COPY_MESSAGE &&
is->priv->current_command->job_kind != CAMEL_IMAPX_JOB_MOVE_MESSAGE)) {
+ gboolean ignored = TRUE;
+ gboolean is_idle_command = is->priv->current_command && is->priv->current_command->job_kind
== CAMEL_IMAPX_JOB_IDLE;
+
COMMAND_UNLOCK (is);
- c (is->priv->tagprefix, "ignoring untagged expunge: %lu\n", expunged_idx);
+ /* Process only untagged EXPUNGE responses within ongoing IDLE command */
+ if (is_idle_command) {
+ CamelIMAPXMailbox *mailbox;
+
+ mailbox = camel_imapx_server_ref_selected (is);
+ if (mailbox) {
+ guint32 messages;
+
+ messages = camel_imapx_mailbox_get_messages (mailbox);
+ if (messages > 0) {
+ camel_imapx_mailbox_set_messages (mailbox, messages - 1);
+
+ ignored = FALSE;
+ c (is->priv->tagprefix, "going to refresh mailbox '%s' due to
untagged expunge: %lu\n", camel_imapx_mailbox_get_name (mailbox), expunged_idx);
+
+ g_signal_emit (is, signals[REFRESH_MAILBOX], 0, mailbox);
+ }
+
+ g_object_unref (mailbox);
+ }
+ }
+
+ if (ignored)
+ c (is->priv->tagprefix, "ignoring untagged expunge: %lu\n", expunged_idx);
+
return TRUE;
}
@@ -973,10 +1000,9 @@ imapx_untagged_exists (CamelIMAPXServer *is,
GCancellable *cancellable,
GError **error)
{
- CamelFolder *folder;
CamelIMAPXMailbox *mailbox;
guint32 exists;
- gboolean success = TRUE;
+ gboolean success = TRUE, changed;
g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE);
@@ -994,20 +1020,12 @@ imapx_untagged_exists (CamelIMAPXServer *is,
camel_imapx_mailbox_get_messages (mailbox),
exists);
+ changed = camel_imapx_mailbox_get_messages (mailbox) != exists;
camel_imapx_mailbox_set_messages (mailbox, exists);
- folder = imapx_server_ref_folder (is, mailbox);
- g_return_val_if_fail (folder != NULL, FALSE);
-
- if (camel_imapx_server_is_in_idle (is)) {
- guint count;
+ if (changed && camel_imapx_server_is_in_idle (is))
+ g_signal_emit (is, signals[REFRESH_MAILBOX], 0, mailbox);
- count = camel_folder_summary_count (camel_folder_get_folder_summary (folder));
- if (count < exists)
- g_signal_emit (is, signals[REFRESH_MAILBOX], 0, mailbox);
- }
-
- g_object_unref (folder);
g_object_unref (mailbox);
return success;
@@ -1340,6 +1358,26 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
if (free_user_flags)
camel_named_flags_free (server_user_flags);
+
+ if (camel_imapx_server_is_in_idle (is) && !camel_folder_is_frozen (folder)) {
+ CamelFolderChangeInfo *changes = NULL;
+
+ g_mutex_lock (&is->priv->changes_lock);
+
+ if (camel_folder_change_info_changed (is->priv->changes)) {
+ changes = is->priv->changes;
+ is->priv->changes = camel_folder_change_info_new ();
+ }
+
+ g_mutex_unlock (&is->priv->changes_lock);
+
+ if (changes) {
+ imapx_update_store_summary (folder);
+ camel_folder_changed (folder, changes);
+
+ camel_folder_change_info_free (changes);
+ }
+ }
}
g_clear_object (&mailbox);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]