[evolution-data-server] [IMAPx] Enhance IDLE run management on folders



commit c50135844c8010c96059a9c9fa6edeff8b64dda4
Author: Milan Crha <mcrha redhat com>
Date:   Wed Jan 13 12:17:45 2016 +0100

    [IMAPx] Enhance IDLE run management on folders
    
    This is to avoid processing of IDLE responses for changes made by itself
    and have running IDLE commands multiple times on one folder. Both can
    cause misbehaviour in the UI.

 camel/providers/imapx/camel-imapx-conn-manager.c |  265 +++++++++++++++++++++-
 camel/providers/imapx/camel-imapx-server.c       |  104 +++++----
 camel/providers/imapx/camel-imapx-server.h       |    5 +
 3 files changed, 323 insertions(+), 51 deletions(-)
---
diff --git a/camel/providers/imapx/camel-imapx-conn-manager.c 
b/camel/providers/imapx/camel-imapx-conn-manager.c
index a383143..36639c9 100644
--- a/camel/providers/imapx/camel-imapx-conn-manager.c
+++ b/camel/providers/imapx/camel-imapx-conn-manager.c
@@ -68,6 +68,10 @@ struct _CamelIMAPXConnManagerPrivate {
 
        GMutex busy_connections_lock;
        GCond busy_connections_cond;
+
+       GMutex busy_mailboxes_lock; /* used for both busy_mailboxes and idle_mailboxes */
+       GHashTable *busy_mailboxes; /* CamelIMAPXMailbox ~> gint */
+       GHashTable *idle_mailboxes; /* CamelIMAPXMailbox ~> gint */
 };
 
 struct _ConnectionInfo {
@@ -354,6 +358,159 @@ imapx_conn_manager_ref_folder_sync (CamelIMAPXConnManager *conn_man,
 }
 
 static void
+imapx_conn_manager_inc_mailbox_hash (CamelIMAPXConnManager *conn_man,
+                                    CamelIMAPXMailbox *mailbox,
+                                    GHashTable *mailboxes_hash)
+{
+       gint count;
+
+       g_return_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (conn_man));
+       g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
+       g_return_if_fail (mailboxes_hash != NULL);
+
+       g_mutex_lock (&conn_man->priv->busy_mailboxes_lock);
+
+       count = GPOINTER_TO_INT (g_hash_table_lookup (mailboxes_hash, mailbox));
+       count++;
+
+       g_hash_table_insert (mailboxes_hash, g_object_ref (mailbox), GINT_TO_POINTER (count));
+
+       g_mutex_unlock (&conn_man->priv->busy_mailboxes_lock);
+}
+
+static void
+imapx_conn_manager_dec_mailbox_hash (CamelIMAPXConnManager *conn_man,
+                                    CamelIMAPXMailbox *mailbox,
+                                    GHashTable *mailboxes_hash)
+{
+       gint count;
+
+       g_return_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (conn_man));
+       g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
+       g_return_if_fail (mailboxes_hash != NULL);
+
+       g_mutex_lock (&conn_man->priv->busy_mailboxes_lock);
+
+       count = GPOINTER_TO_INT (g_hash_table_lookup (mailboxes_hash, mailbox));
+       if (!count) {
+               g_mutex_unlock (&conn_man->priv->busy_mailboxes_lock);
+               g_warn_if_fail (count > 0);
+
+               return;
+       }
+
+       count--;
+
+       if (count)
+               g_hash_table_insert (mailboxes_hash, g_object_ref (mailbox), GINT_TO_POINTER (count));
+       else
+               g_hash_table_remove (mailboxes_hash, mailbox);
+
+       g_mutex_unlock (&conn_man->priv->busy_mailboxes_lock);
+}
+
+static gboolean
+imapx_conn_manager_is_mailbox_hash (CamelIMAPXConnManager *conn_man,
+                                   CamelIMAPXMailbox *mailbox,
+                                   GHashTable *mailboxes_hash)
+{
+       gint count;
+
+       g_return_val_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (conn_man), FALSE);
+       g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), FALSE);
+       g_return_val_if_fail (mailboxes_hash != NULL, FALSE);
+
+       g_mutex_lock (&conn_man->priv->busy_mailboxes_lock);
+
+       count = GPOINTER_TO_INT (g_hash_table_lookup (mailboxes_hash, mailbox));
+
+       g_mutex_unlock (&conn_man->priv->busy_mailboxes_lock);
+
+       return count > 0;
+}
+
+static void
+imapx_conn_manager_inc_mailbox_busy (CamelIMAPXConnManager *conn_man,
+                                    CamelIMAPXMailbox *mailbox)
+{
+       g_return_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (conn_man));
+       g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
+
+       imapx_conn_manager_inc_mailbox_hash (conn_man, mailbox, conn_man->priv->busy_mailboxes);
+}
+
+static void
+imapx_conn_manager_dec_mailbox_busy (CamelIMAPXConnManager *conn_man,
+                                    CamelIMAPXMailbox *mailbox)
+{
+       g_return_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (conn_man));
+       g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
+
+       imapx_conn_manager_dec_mailbox_hash (conn_man, mailbox, conn_man->priv->busy_mailboxes);
+}
+
+static gboolean
+imapx_conn_manager_is_mailbox_busy (CamelIMAPXConnManager *conn_man,
+                                   CamelIMAPXMailbox *mailbox)
+{
+       g_return_val_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (conn_man), FALSE);
+       g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), FALSE);
+
+       return imapx_conn_manager_is_mailbox_hash (conn_man, mailbox, conn_man->priv->busy_mailboxes);
+}
+
+static void
+imapx_conn_manager_inc_mailbox_idle (CamelIMAPXConnManager *conn_man,
+                                    CamelIMAPXMailbox *mailbox)
+{
+       g_return_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (conn_man));
+       g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
+
+       imapx_conn_manager_inc_mailbox_hash (conn_man, mailbox, conn_man->priv->idle_mailboxes);
+}
+
+static void
+imapx_conn_manager_dec_mailbox_idle (CamelIMAPXConnManager *conn_man,
+                                    CamelIMAPXMailbox *mailbox)
+{
+       g_return_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (conn_man));
+       g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
+
+       imapx_conn_manager_dec_mailbox_hash (conn_man, mailbox, conn_man->priv->idle_mailboxes);
+}
+
+static gboolean
+imapx_conn_manager_is_mailbox_idle (CamelIMAPXConnManager *conn_man,
+                                   CamelIMAPXMailbox *mailbox)
+{
+       g_return_val_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (conn_man), FALSE);
+       g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), FALSE);
+
+       return imapx_conn_manager_is_mailbox_hash (conn_man, mailbox, conn_man->priv->idle_mailboxes);
+}
+
+static gboolean
+imapx_conn_manager_has_inbox_idle (CamelIMAPXConnManager *conn_man)
+{
+       CamelIMAPXStore *imapx_store;
+       CamelIMAPXMailbox *inbox_mailbox;
+       gboolean is_idle;
+
+       g_return_val_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (conn_man), FALSE);
+
+       imapx_store = camel_imapx_conn_manager_ref_store (conn_man);
+       inbox_mailbox = imapx_store ? camel_imapx_store_ref_mailbox (imapx_store, "INBOX") : NULL;
+
+       g_clear_object (&imapx_store);
+
+       is_idle = inbox_mailbox && imapx_conn_manager_is_mailbox_idle (conn_man, inbox_mailbox);
+
+       g_clear_object (&inbox_mailbox);
+
+       return is_idle;
+}
+
+static void
 imapx_conn_manager_set_store (CamelIMAPXConnManager *conn_man,
                               CamelStore *store)
 {
@@ -414,6 +571,11 @@ imapx_conn_manager_dispose (GObject *object)
 
        g_weak_ref_set (&conn_man->priv->store, NULL);
 
+       g_mutex_lock (&conn_man->priv->busy_mailboxes_lock);
+       g_hash_table_remove_all (conn_man->priv->busy_mailboxes);
+       g_hash_table_remove_all (conn_man->priv->idle_mailboxes);
+       g_mutex_unlock (&conn_man->priv->busy_mailboxes_lock);
+
        /* Chain up to parent's dispose() method. */
        G_OBJECT_CLASS (camel_imapx_conn_manager_parent_class)->dispose (object);
 }
@@ -434,6 +596,9 @@ imapx_conn_manager_finalize (GObject *object)
        g_mutex_clear (&priv->busy_connections_lock);
        g_cond_clear (&priv->busy_connections_cond);
        g_weak_ref_clear (&priv->store);
+       g_mutex_clear (&priv->busy_mailboxes_lock);
+       g_hash_table_destroy (priv->busy_mailboxes);
+       g_hash_table_destroy (priv->idle_mailboxes);
 
        /* Chain up to parent's finalize() method. */
        G_OBJECT_CLASS (camel_imapx_conn_manager_parent_class)->finalize (object);
@@ -485,8 +650,11 @@ camel_imapx_conn_manager_init (CamelIMAPXConnManager *conn_man)
        g_mutex_init (&conn_man->priv->busy_connections_lock);
        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);
 
        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);
 }
 
 static gchar
@@ -980,20 +1148,82 @@ camel_imapx_conn_manager_run_job_sync (CamelIMAPXConnManager *conn_man,
 
                cinfo = camel_imapx_conn_manager_ref_connection (conn_man, camel_imapx_job_get_mailbox (job), 
cancellable, error);
                if (cinfo) {
+                       CamelIMAPXMailbox *job_mailbox;
+
+                       job_mailbox = camel_imapx_job_get_mailbox (job);
+
+                       if (job_mailbox)
+                               imapx_conn_manager_inc_mailbox_busy (conn_man, job_mailbox);
+
+                       if (camel_imapx_server_is_in_idle (cinfo->is)) {
+                               CamelIMAPXMailbox *idle_mailbox;
+
+                               idle_mailbox = camel_imapx_server_ref_idle_mailbox (cinfo->is);
+                               if (idle_mailbox)
+                                       imapx_conn_manager_dec_mailbox_idle (conn_man, idle_mailbox);
+                               g_clear_object (&idle_mailbox);
+                       }
+
                        success = camel_imapx_server_stop_idle_sync (cinfo->is, cancellable, &local_error);
 
+                       if (success && camel_imapx_server_can_use_idle (cinfo->is)) {
+                               GList *link, *connection_infos, *disconnected_infos = NULL;
+
+                               CON_READ_LOCK (conn_man);
+                               connection_infos = g_list_copy (conn_man->priv->connections);
+                               g_list_foreach (connection_infos, (GFunc) connection_info_ref, NULL);
+                               CON_READ_UNLOCK (conn_man);
+
+                               /* Stop IDLE on all connections serving the same mailbox,
+                                  to avoid notifications for changes done by itself */
+                               for (link = connection_infos; link && !g_cancellable_is_cancelled 
(cancellable); link = g_list_next (link)) {
+                                       ConnectionInfo *other_cinfo = link->data;
+                                       CamelIMAPXMailbox *other_mailbox;
+
+                                       if (!other_cinfo || other_cinfo == cinfo || connection_info_get_busy 
(other_cinfo) ||
+                                           !camel_imapx_server_is_in_idle (other_cinfo->is))
+                                               continue;
+
+                                       other_mailbox = camel_imapx_server_ref_idle_mailbox (other_cinfo->is);
+                                       if (job_mailbox == other_mailbox) {
+                                               if (!camel_imapx_server_stop_idle_sync (other_cinfo->is, 
cancellable, &local_error)) {
+                                                       c (camel_imapx_server_get_tagprefix (other_cinfo->is),
+                                                               "Failed to stop IDLE call (will be removed) 
on connection %p (server:%p) due to error: %s\n",
+                                                               other_cinfo, other_cinfo->is, local_error ? 
local_error->message : "Unknown error");
+
+                                                       camel_imapx_server_disconnect_sync (other_cinfo->is, 
cancellable, NULL);
+
+                                                       disconnected_infos = g_list_prepend 
(disconnected_infos, connection_info_ref (other_cinfo));
+                                               } else {
+                                                       imapx_conn_manager_dec_mailbox_idle (conn_man, 
other_mailbox);
+                                               }
+
+                                               g_clear_error (&local_error);
+                                       }
+
+                                       g_clear_object (&other_mailbox);
+                               }
+
+                               for (link = disconnected_infos; link; link = g_list_next (link)) {
+                                       ConnectionInfo *other_cinfo = link->data;
+
+                                       imapx_conn_manager_remove_info (conn_man, other_cinfo);
+                               }
+
+                               g_list_free_full (disconnected_infos, (GDestroyNotify) connection_info_unref);
+                               g_list_free_full (connection_infos, (GDestroyNotify) connection_info_unref);
+                       }
+
                        if (success)
                                success = camel_imapx_job_run_sync (job, cinfo->is, cancellable, 
&local_error);
 
+                       if (job_mailbox)
+                               imapx_conn_manager_dec_mailbox_busy (conn_man, job_mailbox);
+
                        if (success) {
                                CamelIMAPXMailbox *idle_mailbox = NULL;
-                               gboolean is_first_connection;
 
-                               CON_READ_LOCK (conn_man);
-                               is_first_connection = conn_man->priv->connections && 
conn_man->priv->connections->data == cinfo;
-                               CON_READ_UNLOCK (conn_man);
-
-                               if (is_first_connection) {
+                               if (!imapx_conn_manager_has_inbox_idle (conn_man)) {
                                        CamelIMAPXStore *imapx_store;
 
                                        imapx_store = camel_imapx_conn_manager_ref_store (conn_man);
@@ -1002,7 +1232,24 @@ camel_imapx_conn_manager_run_job_sync (CamelIMAPXConnManager *conn_man,
                                        g_clear_object (&imapx_store);
                                }
 
-                               camel_imapx_server_schedule_idle_sync (cinfo->is, idle_mailbox, cancellable, 
NULL);
+                               if (!idle_mailbox)
+                                       idle_mailbox = camel_imapx_server_ref_selected (cinfo->is);
+
+                               /* Can start IDLE on the connection only if the IDLE folder is not busy
+                                  and not in IDLE already, to avoid multiple IDLE notifications on the same 
mailbox */
+                               if (idle_mailbox && camel_imapx_server_can_use_idle (cinfo->is) &&
+                                   !imapx_conn_manager_is_mailbox_busy (conn_man, idle_mailbox) &&
+                                   !imapx_conn_manager_is_mailbox_idle (conn_man, idle_mailbox)) {
+                                       camel_imapx_server_schedule_idle_sync (cinfo->is, idle_mailbox, 
cancellable, NULL);
+
+                                       if (camel_imapx_server_is_in_idle (cinfo->is)) {
+                                               g_clear_object (&idle_mailbox);
+
+                                               idle_mailbox = camel_imapx_server_ref_idle_mailbox 
(cinfo->is);
+                                               if (idle_mailbox)
+                                                       imapx_conn_manager_inc_mailbox_idle (conn_man, 
idle_mailbox);
+                                       }
+                               }
 
                                g_clear_object (&idle_mailbox);
 
@@ -2482,7 +2729,9 @@ camel_imapx_conn_manager_dump_queue_status (CamelIMAPXConnManager *conn_man)
                if (cinfo)
                        cmd = cinfo->is ? camel_imapx_server_ref_current_command (cinfo->is) : NULL;
 
-               printf ("   connection:%p server:%p busy:%d command:%s\n", cinfo, cinfo ? cinfo->is : NULL, 
cinfo ? cinfo->busy : FALSE,
+               printf ("   connection:%p server:[%c] %p busy:%d command:%s\n", cinfo,
+                       cinfo && cinfo->is ? camel_imapx_server_get_tagprefix (cinfo->is) : '?',
+                       cinfo ? cinfo->is : NULL, cinfo ? cinfo->busy : FALSE,
                        cmd ? camel_imapx_job_get_kind_name (cmd->job_kind) : "[null]");
 
                if (cmd)
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index 2514226..4844813 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -351,9 +351,6 @@ static gint imapx_uids_array_cmp            (gconstpointer ap,
                                                 gconstpointer bp);
 static void    imapx_sync_free_user            (GArray *user_set);
 
-static gboolean        imapx_in_idle                   (CamelIMAPXServer *is);
-static gboolean        imapx_use_idle                  (CamelIMAPXServer *is);
-
 G_DEFINE_TYPE (CamelIMAPXServer, camel_imapx_server, G_TYPE_OBJECT)
 
 typedef struct _FetchChangesInfo {
@@ -632,7 +629,7 @@ imapx_server_inactivity_thread (gpointer user_data)
 
        g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), NULL);
 
-       if (imapx_in_idle (is)) {
+       if (camel_imapx_server_is_in_idle (is)) {
                /* Stop and restart the IDLE command. */
                if (!camel_imapx_server_schedule_idle_sync (is, NULL, is->priv->cancellable, &local_error) &&
                    !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
@@ -759,7 +756,7 @@ imapx_expunge_uid_from_summary (CamelIMAPXServer *is,
        camel_folder_summary_remove_uid (folder->summary, uid);
        camel_folder_change_info_remove_uid (is->priv->changes, uid);
 
-       if (imapx_in_idle (is)) {
+       if (camel_imapx_server_is_in_idle (is)) {
                camel_folder_summary_save_to_db (folder->summary, NULL);
                imapx_update_store_summary (folder);
                camel_folder_changed (folder, is->priv->changes);
@@ -1017,7 +1014,7 @@ imapx_untagged_exists (CamelIMAPXServer *is,
        folder = imapx_server_ref_folder (is, mailbox);
        g_return_val_if_fail (folder != NULL, FALSE);
 
-       if (imapx_in_idle (is)) {
+       if (camel_imapx_server_is_in_idle (is)) {
                guint count;
 
                count = camel_folder_summary_count (folder->summary);
@@ -1218,7 +1215,7 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
                        }
                        g_free (uid);
 
-                       if (changed && imapx_in_idle (is)) {
+                       if (changed && camel_imapx_server_is_in_idle (is)) {
                                camel_folder_summary_save_to_db (select_folder->summary, NULL);
                                imapx_update_store_summary (select_folder);
                                camel_folder_changed (select_folder, is->priv->changes);
@@ -2011,7 +2008,7 @@ imapx_continuation (CamelIMAPXServer *is,
         * can write while we have it ... so we dont need any
         * ohter lock here.  All other writes go through
         * queue-lock */
-       if (imapx_in_idle (is)) {
+       if (camel_imapx_server_is_in_idle (is)) {
                success = camel_imapx_input_stream_skip (
                        CAMEL_IMAPX_INPUT_STREAM (input_stream),
                        cancellable, error);
@@ -2337,40 +2334,6 @@ imapx_step (CamelIMAPXServer *is,
        return success;
 }
 
-static gboolean
-imapx_use_idle (CamelIMAPXServer *is)
-{
-       gboolean use_idle = FALSE;
-
-       /* No need for IDLE if the server supports NOTIFY. */
-       if (CAMEL_IMAPX_HAVE_CAPABILITY (is->priv->cinfo, NOTIFY))
-               return FALSE;
-
-       if (CAMEL_IMAPX_HAVE_CAPABILITY (is->priv->cinfo, IDLE)) {
-               CamelIMAPXSettings *settings;
-
-               settings = camel_imapx_server_ref_settings (is);
-               use_idle = camel_imapx_settings_get_use_idle (settings);
-               g_object_unref (settings);
-       }
-
-       return use_idle;
-}
-
-static gboolean
-imapx_in_idle (CamelIMAPXServer *is)
-{
-       gboolean in_idle;
-
-       g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE);
-
-       g_rec_mutex_lock (&is->priv->idle_lock);
-       in_idle = is->priv->idle_running || is->priv->idle_pending || is->priv->idle_thread;
-       g_rec_mutex_unlock (&is->priv->idle_lock);
-
-       return in_idle;
-}
-
 static void
 imapx_server_set_streams (CamelIMAPXServer *is,
                           GInputStream *input_stream,
@@ -6055,6 +6018,61 @@ imapx_server_run_idle_thread_cb (gpointer user_data)
 }
 
 gboolean
+camel_imapx_server_can_use_idle (CamelIMAPXServer *is)
+{
+       gboolean use_idle = FALSE;
+
+       /* No need for IDLE if the server supports NOTIFY. */
+       if (CAMEL_IMAPX_HAVE_CAPABILITY (is->priv->cinfo, NOTIFY))
+               return FALSE;
+
+       if (CAMEL_IMAPX_HAVE_CAPABILITY (is->priv->cinfo, IDLE)) {
+               CamelIMAPXSettings *settings;
+
+               settings = camel_imapx_server_ref_settings (is);
+               use_idle = camel_imapx_settings_get_use_idle (settings);
+               g_object_unref (settings);
+       }
+
+       return use_idle;
+}
+
+gboolean
+camel_imapx_server_is_in_idle (CamelIMAPXServer *is)
+{
+       gboolean in_idle;
+
+       g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE);
+
+       g_rec_mutex_lock (&is->priv->idle_lock);
+       in_idle = is->priv->idle_running || is->priv->idle_pending || is->priv->idle_thread;
+       g_rec_mutex_unlock (&is->priv->idle_lock);
+
+       return in_idle;
+}
+
+CamelIMAPXMailbox *
+camel_imapx_server_ref_idle_mailbox (CamelIMAPXServer *is)
+{
+       CamelIMAPXMailbox *mailbox = NULL;
+
+       g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), NULL);
+
+       g_rec_mutex_lock (&is->priv->idle_lock);
+
+       if (is->priv->idle_running || is->priv->idle_pending || is->priv->idle_thread) {
+               if (is->priv->idle_mailbox)
+                       mailbox = g_object_ref (is->priv->idle_mailbox);
+               else
+                       mailbox = camel_imapx_server_ref_selected (is);
+       }
+
+       g_rec_mutex_unlock (&is->priv->idle_lock);
+
+       return mailbox;
+}
+
+gboolean
 camel_imapx_server_schedule_idle_sync (CamelIMAPXServer *is,
                                       CamelIMAPXMailbox *mailbox,
                                       GCancellable *cancellable,
@@ -6067,7 +6085,7 @@ camel_imapx_server_schedule_idle_sync (CamelIMAPXServer *is,
        if (!camel_imapx_server_stop_idle_sync (is, cancellable, error))
                return FALSE;
 
-       if (!imapx_use_idle (is))
+       if (!camel_imapx_server_can_use_idle (is))
                return TRUE;
 
        g_rec_mutex_lock (&is->priv->idle_lock);
diff --git a/camel/providers/imapx/camel-imapx-server.h b/camel/providers/imapx/camel-imapx-server.h
index e617ea2..a51c39d 100644
--- a/camel/providers/imapx/camel-imapx-server.h
+++ b/camel/providers/imapx/camel-imapx-server.h
@@ -273,6 +273,11 @@ GPtrArray *        camel_imapx_server_uid_search_sync
                                                 const gchar * const *words,
                                                 GCancellable *cancellable,
                                                 GError **error);
+gboolean       camel_imapx_server_can_use_idle (CamelIMAPXServer *is);
+gboolean       camel_imapx_server_is_in_idle   (CamelIMAPXServer *is);
+CamelIMAPXMailbox *
+               camel_imapx_server_ref_idle_mailbox
+                                               (CamelIMAPXServer *is);
 gboolean       camel_imapx_server_schedule_idle_sync
                                                (CamelIMAPXServer *is,
                                                 CamelIMAPXMailbox *mailbox,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]