summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2016-01-13 12:17:45 +0100
committerMilan Crha <mcrha@redhat.com>2016-01-13 12:27:48 +0100
commitc4432ba2bbdd1b8317edc23988333fdeeb643d96 (patch)
treed510aca10914fadb74663e3ec43a0f914ded440e
parentb73ae1e070eeafec54898e11fa84abc2dcc69a64 (diff)
downloadevolution-data-server-c4432ba2bbdd1b8317edc23988333fdeeb643d96.tar.gz
[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.
-rw-r--r--camel/providers/imapx/camel-imapx-conn-manager.c265
-rw-r--r--camel/providers/imapx/camel-imapx-server.c104
-rw-r--r--camel/providers/imapx/camel-imapx-server.h5
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 49fc670c6..b756d5c58 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 d77901cef..582d6a4da 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);
@@ -2008,7 +2005,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);
@@ -2334,40 +2331,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,
@@ -6043,6 +6006,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,
@@ -6055,7 +6073,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 e617ea2fd..a51c39d05 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,