[evolution-data-server] [IMAPx] Enhance IDLE run management on folders
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] [IMAPx] Enhance IDLE run management on folders
- Date: Wed, 13 Jan 2016 11:26:50 +0000 (UTC)
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]