From ef1357e239a696f620720e21a8ddd81d91924690 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Thu, 10 Apr 2014 09:34:36 +0200 Subject: [PATCH] [IMAPx] Do not open each folder on LIST/LSUB responses It has sever performance issues, especially with large folders, which load (part of) the folder summary into memory too. --- camel/providers/imapx/camel-imapx-conn-manager.c | 27 ++++++++++++++++++++ camel/providers/imapx/camel-imapx-conn-manager.h | 4 +++ camel/providers/imapx/camel-imapx-folder.c | 18 +++++++++++-- camel/providers/imapx/camel-imapx-store.c | 32 +++++++++++++----------- camel/providers/imapx/camel-imapx-store.h | 4 +++ 5 files changed, 68 insertions(+), 17 deletions(-) diff --git a/camel/providers/imapx/camel-imapx-conn-manager.c b/camel/providers/imapx/camel-imapx-conn-manager.c index aeb64d3..d7d37d2 100644 --- a/camel/providers/imapx/camel-imapx-conn-manager.c +++ b/camel/providers/imapx/camel-imapx-conn-manager.c @@ -897,6 +897,33 @@ camel_imapx_conn_manager_update_con_info (CamelIMAPXConnManager *con_man, connection_info_unref (cinfo); } +CamelIMAPXMailbox * +camel_imapx_conn_manager_ref_mailbox (CamelIMAPXConnManager *con_man, + const gchar *mailbox_name) +{ + CamelIMAPXMailbox *mailbox = NULL; + GList *iter; + + g_return_val_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (con_man), NULL); + g_return_val_if_fail (mailbox_name != NULL, NULL); + + CON_READ_LOCK (con_man); + + for (iter = con_man->priv->connections; iter != NULL; iter = g_list_next (iter)) { + ConnectionInfo *candidate = iter->data; + + if (candidate->is) { + mailbox = camel_imapx_server_ref_mailbox (candidate->is, mailbox_name); + if (mailbox) + break; + } + } + + CON_READ_UNLOCK (con_man); + + return mailbox; +} + void camel_imapx_conn_manager_close_connections (CamelIMAPXConnManager *con_man) { diff --git a/camel/providers/imapx/camel-imapx-conn-manager.h b/camel/providers/imapx/camel-imapx-conn-manager.h index 5ebfd71..43c7894 100644 --- a/camel/providers/imapx/camel-imapx-conn-manager.h +++ b/camel/providers/imapx/camel-imapx-conn-manager.h @@ -88,6 +88,10 @@ void camel_imapx_conn_manager_update_con_info (CamelIMAPXConnManager *con_man, CamelIMAPXServer *server, const gchar *folder_name); +CamelIMAPXMailbox * + camel_imapx_conn_manager_ref_mailbox + (CamelIMAPXConnManager *con_man, + const gchar *mailbox_name); G_END_DECLS diff --git a/camel/providers/imapx/camel-imapx-folder.c b/camel/providers/imapx/camel-imapx-folder.c index e5962f5..6fe1021 100644 --- a/camel/providers/imapx/camel-imapx-folder.c +++ b/camel/providers/imapx/camel-imapx-folder.c @@ -1447,11 +1447,20 @@ void camel_imapx_folder_set_mailbox (CamelIMAPXFolder *folder, CamelIMAPXMailbox *mailbox) { + CamelIMAPXSummary *imapx_summary; + guint32 uidvalidity; + g_return_if_fail (CAMEL_IS_IMAPX_FOLDER (folder)); g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox)); g_weak_ref_set (&folder->priv->mailbox, mailbox); + imapx_summary = CAMEL_IMAPX_SUMMARY (CAMEL_FOLDER (folder)->summary); + uidvalidity = camel_imapx_mailbox_get_uidvalidity (mailbox); + + if (uidvalidity > 0 && uidvalidity != imapx_summary->validity) + camel_imapx_folder_invalidate_local_cache (folder, uidvalidity); + g_object_notify (G_OBJECT (folder), "mailbox"); } @@ -1519,10 +1528,15 @@ camel_imapx_folder_list_mailbox (CamelIMAPXFolder *folder, camel_store_summary_info_unref (imapx_store->summary, store_info); - /* See if the CamelIMAPXServer already has the mailbox. */ + /* See if the CamelIMAPXStore already has the mailbox. */ - server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, error); + mailbox = camel_imapx_store_ref_mailbox (imapx_store, mailbox_name); + if (mailbox != NULL) { + camel_imapx_folder_set_mailbox (folder, mailbox); + goto exit; + } + server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, error); if (server == NULL) goto exit; diff --git a/camel/providers/imapx/camel-imapx-store.c b/camel/providers/imapx/camel-imapx-store.c index eaf3603..b69ed0f 100644 --- a/camel/providers/imapx/camel-imapx-store.c +++ b/camel/providers/imapx/camel-imapx-store.c @@ -529,23 +529,18 @@ imapx_store_process_mailbox_attributes (CamelIMAPXStore *store, } static void -imapx_store_process_mailbox_status (CamelIMAPXStore *store, +imapx_store_process_mailbox_status (CamelIMAPXStore *imapx_store, CamelIMAPXMailbox *mailbox) { - CamelFolder *folder = NULL; + CamelStore *store; + CamelFolder *folder; gchar *folder_path; - GError *local_error = NULL; folder_path = camel_imapx_mailbox_dup_folder_path (mailbox); + store = CAMEL_STORE (imapx_store); - folder = camel_store_get_folder_sync ( - CAMEL_STORE (store), folder_path, 0, NULL, &local_error); - - /* Sanity check. */ - g_return_if_fail ( - ((folder != NULL) && (local_error == NULL)) || - ((folder == NULL) && (local_error != NULL))); - + /* Update only already opened folders */ + folder = camel_object_bag_reserve (store->folders, folder_path); if (folder != NULL) { CamelIMAPXFolder *imapx_folder; CamelIMAPXSummary *imapx_summary; @@ -562,10 +557,7 @@ imapx_store_process_mailbox_status (CamelIMAPXStore *store, g_object_unref (folder); } else { - g_warning ( - "%s: Failed to get folder '%s': %s", - G_STRFUNC, folder_path, local_error->message); - g_error_free (local_error); + camel_object_bag_abort (store->folders, folder_path); } g_free (folder_path); @@ -2535,6 +2527,16 @@ camel_imapx_store_folder_op_done (CamelIMAPXStore *store, store->priv->con_man, server, folder_name); } +CamelIMAPXMailbox * +camel_imapx_store_ref_mailbox (CamelIMAPXStore *imapx_store, + const gchar *mailbox_name) +{ + g_return_val_if_fail (CAMEL_IS_IMAPX_STORE (imapx_store), NULL); + g_return_val_if_fail (mailbox_name != NULL, NULL); + + return camel_imapx_conn_manager_ref_mailbox (imapx_store->priv->con_man, mailbox_name); +} + CamelFolderQuotaInfo * camel_imapx_store_dup_quota_info (CamelIMAPXStore *store, const gchar *quota_root_name) diff --git a/camel/providers/imapx/camel-imapx-store.h b/camel/providers/imapx/camel-imapx-store.h index 0da0b16..8ef34ba 100644 --- a/camel/providers/imapx/camel-imapx-store.h +++ b/camel/providers/imapx/camel-imapx-store.h @@ -76,6 +76,10 @@ void camel_imapx_store_folder_op_done (CamelIMAPXStore *store, CamelIMAPXServer *server, const gchar *folder_name); +CamelIMAPXMailbox * + camel_imapx_store_ref_mailbox (CamelIMAPXStore *imapx_store, + const gchar *mailbox_name); + CamelFolderQuotaInfo * camel_imapx_store_dup_quota_info (CamelIMAPXStore *store, -- 2.7.4