[evolution-data-server/gnome-3-0] Bug 640054 - sqlite summary hang. Fix vfolder transactions.
- From: Chenthill Palanisamy <pchen src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/gnome-3-0] Bug 640054 - sqlite summary hang. Fix vfolder transactions.
- Date: Tue, 7 Jun 2011 10:07:05 +0000 (UTC)
commit fd286b57ecaf5d68cf15c4852c1b2922cb5e0370
Author: Chenthill Palanisamy <pchenthill novell com>
Date: Tue Jun 7 15:22:45 2011 +0530
Bug 640054 - sqlite summary hang. Fix vfolder transactions.
camel/camel-vee-folder.c | 199 +++++++++++++++++++++++++++-------------------
1 files changed, 118 insertions(+), 81 deletions(-)
---
diff --git a/camel/camel-vee-folder.c b/camel/camel-vee-folder.c
index 8fef906..41cfeee 100644
--- a/camel/camel-vee-folder.c
+++ b/camel/camel-vee-folder.c
@@ -61,6 +61,10 @@ struct _update_data {
CamelVeeFolder *folder_unmatched;
GHashTable *unmatched_uids;
gboolean rebuilt, correlating;
+
+ /* used for storing uids that needs to be updated in db later by unmatched_check_uid and
+ folder_added_uid */
+ GSList *uids_to_update;
};
struct _folder_changed_msg {
@@ -120,12 +124,15 @@ expression_is_correlating (const gchar *expr)
/* Hold all these with summary lock and unmatched summary lock held */
static void
-folder_changed_add_uid (CamelFolder *sub, const gchar *uid, const gchar hash[8], CamelVeeFolder *vf, gboolean use_db)
+folder_changed_add_uid (CamelFolder *sub,
+ const gchar *uid,
+ const gchar hash[8],
+ CamelVeeFolder *vf,
+ gboolean use_db,
+ GSList **m_added_l,
+ GSList **unm_added_l)
{
- CamelFolder *folder = CAMEL_FOLDER (vf);
- CamelStore *parent_store;
CamelVeeMessageInfo *vinfo;
- const gchar *full_name;
const gchar *vuid;
gchar *oldkey;
gpointer oldval;
@@ -133,19 +140,16 @@ folder_changed_add_uid (CamelFolder *sub, const gchar *uid, const gchar hash[8],
CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL;
GHashTable *unmatched_uids = vf->parent_vee_store ? vf->parent_vee_store->unmatched_uids : NULL;
- parent_store = camel_folder_get_parent_store (folder);
-
vinfo = vee_folder_add_uid (vf, sub, uid, hash);
if (vinfo == NULL)
return;
vuid = camel_pstring_strdup (camel_message_info_uid (vinfo));
camel_message_info_free ((CamelMessageInfo *) vinfo);
- if (use_db) {
- full_name = camel_folder_get_full_name (folder);
- camel_db_add_to_vfolder_transaction (
- parent_store->cdb_w, full_name, vuid, NULL);
- }
+
+ if (use_db)
+ *m_added_l = g_slist_prepend (*m_added_l, (gpointer) camel_pstring_strdup (vuid));
+
camel_folder_change_info_add_uid (vf->changes, vuid);
if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !CAMEL_IS_VEE_FOLDER (sub) && folder_unmatched != NULL) {
if (g_hash_table_lookup_extended (unmatched_uids, vuid, (gpointer *)&oldkey, &oldval)) {
@@ -157,12 +161,11 @@ folder_changed_add_uid (CamelFolder *sub, const gchar *uid, const gchar hash[8],
vinfo = (CamelVeeMessageInfo *)camel_folder_get_message_info ((CamelFolder *)folder_unmatched, vuid);
if (vinfo) {
camel_folder_summary_update_counts_by_flags (CAMEL_FOLDER (folder_unmatched)->summary, vinfo->old_flags, TRUE);
- full_name = camel_folder_get_full_name (
- CAMEL_FOLDER (folder_unmatched));
camel_folder_change_info_remove_uid (
folder_unmatched->changes, vuid);
- camel_db_delete_uid_from_vfolder_transaction (
- parent_store->cdb_w, full_name, vuid, NULL);
+
+ *unm_added_l = g_slist_prepend (*unm_added_l, (gpointer) camel_pstring_strdup (vuid));
+
camel_folder_summary_remove_uid_fast (
CAMEL_FOLDER (folder_unmatched)->summary, vuid);
camel_folder_free_message_info (
@@ -175,11 +178,16 @@ folder_changed_add_uid (CamelFolder *sub, const gchar *uid, const gchar hash[8],
}
static void
-folder_changed_remove_uid (CamelFolder *sub, const gchar *uid, const gchar hash[8], gint keep, CamelVeeFolder *vf, gboolean use_db)
+folder_changed_remove_uid (CamelFolder *sub,
+ const gchar *uid,
+ const gchar hash[8],
+ gint keep,
+ CamelVeeFolder *vf,
+ gboolean use_db,
+ GSList **m_removed_l,
+ GSList **unm_removed_l)
{
CamelFolder *folder = (CamelFolder *)vf;
- CamelStore *parent_store;
- const gchar *full_name;
gchar *vuid, *oldkey;
gpointer oldval;
gint n;
@@ -191,8 +199,6 @@ folder_changed_remove_uid (CamelFolder *sub, const gchar *uid, const gchar hash[
memcpy (vuid, hash, 8);
strcpy (vuid+8, uid);
- parent_store = camel_folder_get_parent_store (folder);
-
vinfo = (CamelVeeMessageInfo *) camel_folder_summary_uid (folder->summary, vuid);
if (vinfo) {
camel_folder_summary_update_counts_by_flags (folder->summary, vinfo->old_flags, TRUE);
@@ -200,11 +206,9 @@ folder_changed_remove_uid (CamelFolder *sub, const gchar *uid, const gchar hash[
}
camel_folder_change_info_remove_uid (vf->changes, vuid);
- if (use_db) {
- full_name = camel_folder_get_full_name (folder);
- camel_db_delete_uid_from_vfolder_transaction (
- parent_store->cdb_w, full_name, vuid, NULL);
- }
+ if (use_db)
+ *m_removed_l = g_slist_prepend (*m_removed_l, (gpointer) camel_pstring_strdup (vuid));
+
camel_folder_summary_remove_uid_fast (folder->summary, vuid);
if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !CAMEL_IS_VEE_FOLDER (sub) && folder_unmatched != NULL) {
@@ -232,12 +236,11 @@ folder_changed_remove_uid (CamelFolder *sub, const gchar *uid, const gchar hash[
vinfo = (CamelVeeMessageInfo *)camel_folder_get_message_info ((CamelFolder *)folder_unmatched, vuid);
if (vinfo) {
camel_folder_summary_update_counts_by_flags (CAMEL_FOLDER (folder_unmatched)->summary, vinfo->old_flags, TRUE);
- full_name = camel_folder_get_full_name (
- CAMEL_FOLDER (folder_unmatched));
camel_folder_change_info_remove_uid (
folder_unmatched->changes, vuid);
- camel_db_delete_uid_from_vfolder_transaction (
- parent_store->cdb_w, full_name, vuid, NULL);
+
+ *unm_removed_l = g_slist_prepend (*unm_removed_l, (gpointer) camel_pstring_strdup (vuid));
+
camel_folder_summary_remove_uid_fast (
CAMEL_FOLDER (folder_unmatched)->summary, vuid);
camel_folder_free_message_info (
@@ -260,7 +263,13 @@ update_old_flags (CamelFolderSummary *summary, CamelVeeMessageInfo *vinfo)
}
static void
-folder_changed_change_uid (CamelFolder *sub, const gchar *uid, const gchar hash[8], CamelVeeFolder *vf, gboolean use_db)
+folder_changed_change_uid (CamelFolder *sub,
+ const gchar *uid,
+ const gchar hash[8],
+ CamelVeeFolder *vf,
+ gboolean use_db,
+ GSList **m_removed_l,
+ GSList **unm_removed_l)
{
gchar *vuid;
CamelVeeMessageInfo *vinfo, *uinfo = NULL;
@@ -293,7 +302,7 @@ folder_changed_change_uid (CamelFolder *sub, const gchar *uid, const gchar hash[
camel_folder_free_message_info (sub, info);
} else {
if (vinfo) {
- folder_changed_remove_uid (sub, uid, hash, FALSE, vf, use_db);
+ folder_changed_remove_uid (sub, uid, hash, FALSE, vf, use_db, m_removed_l, unm_removed_l);
camel_message_info_free ((CamelMessageInfo *)vinfo);
}
if (uinfo)
@@ -302,6 +311,27 @@ folder_changed_change_uid (CamelFolder *sub, const gchar *uid, const gchar hash[
}
}
+
+static void
+vfolder_add_remove_transaction (CamelStore *parent_store, const gchar *full_name, GSList **uids, gboolean add, GError **error)
+{
+ GSList *l;
+
+ for (l = *uids; l != NULL; l = g_slist_next (l)) {
+ if (add)
+ camel_db_add_to_vfolder_transaction (parent_store->cdb_w, full_name,
+ (const gchar *) l->data, error);
+ else
+ camel_db_delete_uid_from_vfolder_transaction
+ (parent_store->cdb_w, full_name,
+ (const gchar *) l->data, error);
+ }
+
+ g_slist_foreach (*uids, (GFunc) camel_pstring_free, NULL);
+ g_slist_free (*uids);
+ *uids = NULL;
+}
+
static void
folder_changed_change (CamelSession *session, CamelSessionThreadMsg *msg)
{
@@ -310,7 +340,6 @@ folder_changed_change (CamelSession *session, CamelSessionThreadMsg *msg)
CamelFolder *folder = (CamelFolder *)m->vee_folder;
CamelVeeFolder *vf = m->vee_folder;
CamelFolderChangeInfo *changes = m->changes;
- CamelStore *parent_store;
gchar *vuid = NULL, hash[8];
const gchar *uid;
CamelVeeMessageInfo *vinfo;
@@ -325,6 +354,7 @@ folder_changed_change (CamelSession *session, CamelSessionThreadMsg *msg)
CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL;
GHashTable *unmatched_uids = vf->parent_vee_store ? vf->parent_vee_store->unmatched_uids : NULL;
GPtrArray *present = NULL;
+ GSList *m_added_l = NULL, *m_removed_l = NULL, *unm_added_l = NULL, *unm_removed_l = NULL;
/* See vee_folder_rebuild_folder. */
gboolean correlating = expression_is_correlating (vf->expression);
@@ -388,15 +418,10 @@ folder_changed_change (CamelSession *session, CamelSessionThreadMsg *msg)
if (folder_unmatched != NULL)
camel_vee_folder_lock (folder_unmatched, CAMEL_VEE_FOLDER_SUMMARY_LOCK);
- if (matches_changed || matches_added || changes->uid_removed->len||present) {
- parent_store = camel_folder_get_parent_store (folder);
- camel_db_begin_transaction (parent_store->cdb_w, NULL);
- }
-
/* Always remove removed uid's, in any case */
for (i=0;i<changes->uid_removed->len;i++) {
dd (printf (" removing uid '%s'\n", (gchar *)changes->uid_removed->pdata[i]));
- folder_changed_remove_uid (sub, changes->uid_removed->pdata[i], hash, FALSE, vf, !correlating);
+ folder_changed_remove_uid (sub, changes->uid_removed->pdata[i], hash, FALSE, vf, !correlating, &m_removed_l, &unm_removed_l);
}
/* Add any newly matched or to unmatched folder if they dont */
@@ -410,7 +435,7 @@ folder_changed_change (CamelSession *session, CamelSessionThreadMsg *msg)
uid = changes->uid_added->pdata[i];
if (g_hash_table_lookup (matches_hash, uid)) {
dd (printf (" adding uid '%s' [newly matched]\n", (gchar *)uid));
- folder_changed_add_uid (sub, uid, hash, vf, !correlating);
+ folder_changed_add_uid (sub, uid, hash, vf, !correlating, &m_added_l, &unm_added_l);
} else if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0) {
if (strlen (uid)+9 > vuidlen) {
vuidlen = strlen (uid)+64;
@@ -443,12 +468,12 @@ folder_changed_change (CamelSession *session, CamelSessionThreadMsg *msg)
* vee_folder_rebuild_folder will make any necessary removals
* when it re-queries the entire source folder. */
for (i=0;i<always_changed->len;i++)
- folder_changed_change_uid (sub, always_changed->pdata[i], hash, vf, !correlating);
+ folder_changed_change_uid (sub, always_changed->pdata[i], hash, vf, !correlating, &m_removed_l, &unm_removed_l);
} else {
GHashTable *ht_present = g_hash_table_new (g_str_hash, g_str_equal);
for (i=0;present && i<present->len;i++) {
- folder_changed_change_uid (sub, present->pdata[i], hash, vf, !correlating);
+ folder_changed_change_uid (sub, present->pdata[i], hash, vf, !correlating, &m_removed_l, &unm_removed_l);
g_hash_table_insert (ht_present, present->pdata[i], present->pdata[i]);
}
@@ -456,7 +481,7 @@ folder_changed_change (CamelSession *session, CamelSessionThreadMsg *msg)
if (!present || !g_hash_table_lookup (ht_present, always_changed->pdata[i]))
/* XXX: IIUC, these messages haven't been deleted from the
* source folder, so shouldn't "keep" be set to TRUE? */
- folder_changed_remove_uid (sub, always_changed->pdata[i], hash, TRUE, vf, !correlating);
+ folder_changed_remove_uid (sub, always_changed->pdata[i], hash, TRUE, vf, !correlating, &m_removed_l, &unm_removed_l);
}
g_hash_table_destroy (ht_present);
@@ -488,21 +513,21 @@ folder_changed_change (CamelSession *session, CamelSessionThreadMsg *msg)
if (g_hash_table_lookup (matches_hash, uid)) {
/* A uid we dont have, but now it matches, add it */
dd (printf (" adding uid '%s' [newly matched]\n", uid));
- folder_changed_add_uid (sub, uid, hash, vf, !correlating);
+ folder_changed_add_uid (sub, uid, hash, vf, !correlating, &m_added_l, &unm_added_l);
} else {
/* A uid we still don't have, just change it (for unmatched) */
- folder_changed_change_uid (sub, uid, hash, vf, !correlating);
+ folder_changed_change_uid (sub, uid, hash, vf, !correlating, &m_removed_l, &unm_removed_l);
}
} else {
if ((vf->flags & CAMEL_STORE_VEE_FOLDER_AUTO) == 0
|| g_hash_table_lookup (matches_hash, uid)) {
/* still match, or we're not auto-updating, change event, (if it changed) */
dd (printf (" changing uid '%s' [still matches]\n", uid));
- folder_changed_change_uid (sub, uid, hash, vf, !correlating);
+ folder_changed_change_uid (sub, uid, hash, vf, !correlating, &m_removed_l, &unm_removed_l);
} else {
/* No longer matches, remove it, but keep it in unmatched (potentially) */
dd (printf (" removing uid '%s' [did match]\n", uid));
- folder_changed_remove_uid (sub, uid, hash, TRUE, vf, !correlating);
+ folder_changed_remove_uid (sub, uid, hash, TRUE, vf, !correlating, &m_removed_l, &unm_removed_l);
}
camel_message_info_free ((CamelMessageInfo *)vinfo);
}
@@ -511,7 +536,7 @@ folder_changed_change (CamelSession *session, CamelSessionThreadMsg *msg)
} else {
/* stuff didn't match but it changed - check unmatched folder for changes */
for (i=0;i<changed->len;i++)
- folder_changed_change_uid (sub, changed->pdata[i], hash, vf, !correlating);
+ folder_changed_change_uid (sub, changed->pdata[i], hash, vf, !correlating, &m_removed_l, &unm_removed_l);
}
if (folder_unmatched != NULL) {
@@ -529,9 +554,27 @@ folder_changed_change (CamelSession *session, CamelSessionThreadMsg *msg)
}
if (matches_changed || matches_added || changes->uid_removed->len || present) {
+ const gchar *full_name, *unm_full_name;
+ CamelStore *parent_store;
+
parent_store = camel_folder_get_parent_store (folder);
+ full_name = camel_folder_get_full_name (folder);
+ unm_full_name = camel_folder_get_full_name (CAMEL_FOLDER (folder_unmatched));
+
+ camel_db_begin_transaction (parent_store->cdb_w, NULL);
+
+ if (m_added_l)
+ vfolder_add_remove_transaction (parent_store, full_name, &m_added_l, TRUE, NULL);
+ if (m_removed_l)
+ vfolder_add_remove_transaction (parent_store, full_name, &m_removed_l, FALSE, NULL);
+ if (unm_added_l)
+ vfolder_add_remove_transaction (parent_store, unm_full_name, &unm_added_l, TRUE, NULL);
+ if (unm_removed_l)
+ vfolder_add_remove_transaction (parent_store, unm_full_name, &unm_removed_l, FALSE, NULL);
+
camel_db_end_transaction (parent_store->cdb_w, NULL);
}
+
camel_vee_folder_unlock (vf, CAMEL_VEE_FOLDER_SUMMARY_LOCK);
/* Cleanup stuff on our folder */
@@ -683,17 +726,8 @@ unmatched_check_uid (gchar *uidin, gpointer value, struct _update_data *u)
} else {
CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_uid (((CamelFolder *)u->folder_unmatched)->summary, uid);
if (mi) {
- CamelStore *parent_store;
- const gchar *full_name;
-
- full_name = camel_folder_get_full_name (
- CAMEL_FOLDER (u->folder_unmatched));
- parent_store = camel_folder_get_parent_store (
- CAMEL_FOLDER (u->folder_unmatched));
-
camel_folder_summary_update_counts_by_flags (CAMEL_FOLDER (u->folder_unmatched)->summary, mi->old_flags, TRUE);
- camel_db_delete_uid_from_vfolder_transaction (
- parent_store->cdb_w, full_name, uid, NULL);
+ u->uids_to_update = g_slist_prepend (u->uids_to_update, (gpointer) camel_pstring_strdup (uid));
camel_folder_summary_remove_uid_fast (
((CamelFolder *)u->folder_unmatched)->summary, uid);
camel_folder_change_info_remove_uid (
@@ -713,21 +747,9 @@ folder_added_uid (gchar *uidin, gpointer value, struct _update_data *u)
if ((mi = vee_folder_add_uid (u->vee_folder, u->source, uidin, u->hash)) != NULL) {
camel_folder_change_info_add_uid (u->vee_folder->changes, camel_message_info_uid (mi));
- /* FIXME[disk-summary] Handle exceptions */
- /* FIXME[disk-summary] Make all these as transactions, just
- * testing atm */
- if (u->rebuilt && !u->correlating) {
- CamelStore *parent_store;
- const gchar *full_name;
-
- full_name = camel_folder_get_full_name (
- CAMEL_FOLDER (u->vee_folder));
- parent_store = camel_folder_get_parent_store (
- CAMEL_FOLDER (u->vee_folder));
- camel_db_add_to_vfolder_transaction (
- parent_store->cdb_w, full_name,
- camel_message_info_uid (mi), NULL);
- }
+ if (u->rebuilt && !u->correlating)
+ u->uids_to_update = g_slist_prepend (u->uids_to_update, (gpointer) camel_pstring_strdup (camel_message_info_uid (mi)));
+
if (!CAMEL_IS_VEE_FOLDER (u->source) && u->unmatched_uids != NULL) {
if (g_hash_table_lookup_extended (u->unmatched_uids, camel_message_info_uid (mi), (gpointer *)&oldkey, &oldval)) {
n = GPOINTER_TO_INT (oldval);
@@ -1694,6 +1716,7 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder,
u.unmatched_uids = unmatched_uids;
u.rebuilt = rebuilded;
u.correlating = correlating;
+ u.uids_to_update = NULL;
camel_vee_folder_lock (vee_folder, CAMEL_VEE_FOLDER_SUMMARY_LOCK);
@@ -1778,19 +1801,18 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder,
camel_folder_summary_remove_range (folder->summary, start, last);
/* now matchhash contains any new uid's, add them, etc */
- if (rebuilded && !correlating) {
- CamelStore *parent_store;
-
- parent_store = camel_folder_get_parent_store (folder);
- camel_db_begin_transaction (parent_store->cdb_w, NULL);
- }
-
g_hash_table_foreach (matchhash, (GHFunc)folder_added_uid, &u);
- if (rebuilded && !correlating) {
+ if (rebuilded && !correlating && u.uids_to_update) {
CamelStore *parent_store;
+ const gchar *full_name;
parent_store = camel_folder_get_parent_store (folder);
+ full_name = camel_folder_get_full_name (folder);
+
+ /* FIXME[disk-summary] Handle exceptions */
+ camel_db_begin_transaction (parent_store->cdb_w, NULL);
+ vfolder_add_remove_transaction (parent_store, full_name, &(u.uids_to_update), TRUE, NULL);
camel_db_end_transaction (parent_store->cdb_w, NULL);
}
@@ -1822,8 +1844,23 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder,
}
/* now allhash contains all potentially new uid's for the unmatched folder, process */
- if (!CAMEL_IS_VEE_FOLDER (source))
+ if (!CAMEL_IS_VEE_FOLDER (source)) {
g_hash_table_foreach (allhash, (GHFunc)unmatched_check_uid, &u);
+
+ if (u.uids_to_update) {
+ CamelStore *parent_store;
+ const gchar *full_name;
+
+ full_name = camel_folder_get_full_name (
+ CAMEL_FOLDER (u.folder_unmatched));
+ parent_store = camel_folder_get_parent_store (
+ CAMEL_FOLDER (u.folder_unmatched));
+
+ camel_db_begin_transaction (parent_store->cdb_w, NULL);
+ vfolder_add_remove_transaction (parent_store, full_name, &(u.uids_to_update), FALSE, NULL);
+ camel_db_end_transaction (parent_store->cdb_w, NULL);
+ }
+ }
/* copy any changes so we can raise them outside the lock */
if (camel_folder_change_info_changed (folder_unmatched->changes)) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]