[evolution-data-server] Bug #646898 - IMAPX should invalidated cache when uidvalidity changes
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug #646898 - IMAPX should invalidated cache when uidvalidity changes
- Date: Tue, 17 May 2011 09:31:12 +0000 (UTC)
commit 621d4e0acf20729ed889e6266458f2bce27ff42f
Author: Milan Crha <mcrha redhat com>
Date: Tue May 17 11:30:38 2011 +0200
Bug #646898 - IMAPX should invalidated cache when uidvalidity changes
camel/camel-data-cache.c | 73 ++++++++++++++++++++++------
camel/camel-data-cache.h | 2 +
camel/providers/imapx/camel-imapx-server.c | 56 ++++++++++++++++++++--
3 files changed, 112 insertions(+), 19 deletions(-)
---
diff --git a/camel/camel-data-cache.c b/camel/camel-data-cache.c
index e3ecd5f..57029e6 100644
--- a/camel/camel-data-cache.c
+++ b/camel/camel-data-cache.c
@@ -265,11 +265,10 @@ camel_data_cache_set_expire_access (CamelDataCache *cdc, time_t when)
}
static void
-data_cache_expire (CamelDataCache *cdc, const gchar *path, const gchar *keep, time_t now)
+data_cache_expire (CamelDataCache *cdc, const gchar *path, const gchar *keep, time_t now, gboolean expire_all)
{
GDir *dir;
const gchar *dname;
- GString *s;
struct stat st;
CamelStream *stream;
@@ -277,25 +276,29 @@ data_cache_expire (CamelDataCache *cdc, const gchar *path, const gchar *keep, ti
if (dir == NULL)
return;
- s = g_string_new("");
while ((dname = g_dir_read_name (dir))) {
- if (strcmp (dname, keep) == 0)
+ gchar *dpath;
+
+ if (keep && strcmp (dname, keep) == 0)
continue;
- g_string_printf (s, "%s/%s", path, dname);
- if (g_stat (s->str, &st) == 0
+ dpath = g_build_filename (path, dname, NULL);
+
+ if (g_stat (dpath, &st) == 0
&& S_ISREG (st.st_mode)
- && ((cdc->priv->expire_age != -1 && st.st_mtime + cdc->priv->expire_age < now)
+ && (expire_all
+ || (cdc->priv->expire_age != -1 && st.st_mtime + cdc->priv->expire_age < now)
|| (cdc->priv->expire_access != -1 && st.st_atime + cdc->priv->expire_access < now))) {
- g_unlink (s->str);
- stream = camel_object_bag_get (cdc->priv->busy_bag, s->str);
+ g_unlink (dpath);
+ stream = camel_object_bag_get (cdc->priv->busy_bag, dpath);
if (stream) {
camel_object_bag_remove (cdc->priv->busy_bag, stream);
g_object_unref (stream);
}
}
+
+ g_free (dpath);
}
- g_string_free (s, TRUE);
g_dir_close (dir);
}
@@ -314,11 +317,7 @@ data_cache_path (CamelDataCache *cdc, gint create, const gchar *path, const gcha
dir = alloca (strlen (cdc->priv->path) + strlen (path) + 8);
sprintf(dir, "%s/%s/%02x", cdc->priv->path, path, hash);
-#ifdef G_OS_WIN32
if (g_access (dir, F_OK) == -1) {
-#else
- if (access (dir, F_OK) == -1) {
-#endif
if (create)
g_mkdir_with_parents (dir, 0700);
} else if (cdc->priv->expire_age != -1 || cdc->priv->expire_access != -1) {
@@ -328,7 +327,7 @@ data_cache_path (CamelDataCache *cdc, gint create, const gchar *path, const gcha
now = time (NULL);
if (cdc->priv->expire_last[hash] + CAMEL_DATA_CACHE_CYCLE_TIME < now) {
cdc->priv->expire_last[hash] = now;
- data_cache_expire (cdc, dir, key, now);
+ data_cache_expire (cdc, dir, key, now, FALSE);
}
}
@@ -505,3 +504,47 @@ camel_data_cache_remove (CamelDataCache *cdc,
return ret;
}
+/**
+ * camel_data_cache_clear:
+ * @cdc: a #CamelDataCache
+ * @path: Path to the (sub) cache the item exists in.
+ *
+ * Clear cache's content in @path.
+ **/
+void
+camel_data_cache_clear (CamelDataCache *cdc, const gchar *path)
+{
+ gchar *base_dir;
+ GDir *dir;
+ const gchar *dname;
+ struct stat st;
+
+ g_return_if_fail (cdc != NULL);
+ g_return_if_fail (path != NULL);
+
+ base_dir = g_build_filename (cdc->priv->path, path, NULL);
+
+ dir = g_dir_open (base_dir, 0, NULL);
+ if (dir == NULL) {
+ g_free (base_dir);
+ return;
+ }
+
+ while ((dname = g_dir_read_name (dir))) {
+ gchar *dpath;
+
+ dpath = g_build_filename (base_dir, dname, NULL);
+
+ if (g_stat (dpath, &st) == 0
+ && S_ISDIR (st.st_mode)
+ && !g_str_equal (dname, ".")
+ && !g_str_equal (dname, "..")) {
+ data_cache_expire (cdc, dpath, NULL, -1, TRUE);
+ }
+
+ g_free (dpath);
+ }
+
+ g_dir_close (dir);
+ g_free (base_dir);
+}
diff --git a/camel/camel-data-cache.h b/camel/camel-data-cache.h
index 559b8b0..8b3e454 100644
--- a/camel/camel-data-cache.h
+++ b/camel/camel-data-cache.h
@@ -90,6 +90,8 @@ gchar * camel_data_cache_get_filename (CamelDataCache *cdc,
const gchar *path,
const gchar *key,
GError **error);
+void camel_data_cache_clear (CamelDataCache *cdc,
+ const gchar *path);
G_END_DECLS
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index 79157e7..c4640f7 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -1236,6 +1236,43 @@ imapx_expunge_uid_from_summary (CamelIMAPXServer *imap, gchar *uid, gboolean uns
}
}
+static void
+invalidate_local_cache (CamelIMAPXFolder *ifolder, guint64 new_uidvalidity)
+{
+ CamelFolder *cfolder;
+ CamelFolderChangeInfo *changes;
+ GPtrArray *uids;
+ gint ii;
+
+ g_return_if_fail (ifolder != NULL);
+
+ cfolder = CAMEL_FOLDER (ifolder);
+ g_return_if_fail (cfolder != NULL);
+
+ changes = camel_folder_change_info_new ();
+
+ uids = camel_folder_summary_array (cfolder->summary);
+ for (ii = 0; uids && ii < uids->len; ii++) {
+ const gchar *uid = uids->pdata[ii];
+
+ if (uid)
+ camel_folder_change_info_change_uid (changes, uid);
+ }
+
+ g_ptr_array_foreach (uids, (GFunc) camel_pstring_free, NULL);
+ g_ptr_array_free (uids, TRUE);
+
+ CAMEL_IMAPX_SUMMARY (cfolder->summary)->validity = new_uidvalidity;
+ camel_folder_summary_touch (cfolder->summary);
+ camel_folder_summary_save_to_db (cfolder->summary, NULL);
+
+ camel_data_cache_clear (ifolder->cache, "cache");
+ camel_data_cache_clear (ifolder->cache, "cur");
+
+ camel_folder_changed (cfolder, changes);
+ camel_folder_change_info_free (changes);
+}
+
/* handle any untagged responses */
static gint
imapx_untagged (CamelIMAPXServer *imap,
@@ -1637,11 +1674,15 @@ imapx_untagged (CamelIMAPXServer *imap,
}
}
if (ifolder) {
+ CamelFolder *cfolder = CAMEL_FOLDER (ifolder);
+
ifolder->unread_on_server = sinfo->unseen;
ifolder->exists_on_server = sinfo->messages;
ifolder->modseq_on_server = sinfo->highestmodseq;
ifolder->uidnext_on_server = sinfo->uidnext;
ifolder->uidvalidity_on_server = sinfo->uidvalidity;
+ if (sinfo->uidvalidity && sinfo->uidvalidity != ((CamelIMAPXSummary *) cfolder->summary)->validity)
+ invalidate_local_cache (ifolder, sinfo->uidvalidity);
} else {
c(imap->tagprefix, "Received STATUS for unknown folder '%s'\n", sinfo->name);
}
@@ -2491,6 +2532,8 @@ imapx_command_select_done (CamelIMAPXServer *is, CamelIMAPXCommand *ic)
is->state = IMAPX_INITIALISED;
} else {
CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) is->select_pending;
+ CamelFolder *cfolder = is->select_pending;
+
c(is->tagprefix, "Select ok!\n");
if (!is->select_folder) {
@@ -2508,11 +2551,11 @@ imapx_command_select_done (CamelIMAPXServer *is, CamelIMAPXCommand *ic)
}
ifolder->uidvalidity_on_server = is->uidvalidity;
selected_folder = camel_folder_get_full_name (is->select_folder);
-#if 0
- /* This must trigger a complete index rebuild! */
- if (is->uidvalidity && is->uidvalidity != ((CamelIMAPXSummary *) is->select_folder->summary)->uidvalidity)
- g_warning("uidvalidity doesn't match!");
+ if (is->uidvalidity && is->uidvalidity != ((CamelIMAPXSummary *) cfolder->summary)->validity)
+ invalidate_local_cache (ifolder, is->uidvalidity);
+
+#if 0
/* This should trigger a new messages scan */
if (is->exists != is->select_folder->summary->root_view->total_count)
g_warning("exists is %d our summary is %d and summary exists is %d\n", is->exists,
@@ -4078,6 +4121,11 @@ imapx_job_refresh_info_start (CamelIMAPXServer *is,
#endif
total = camel_folder_summary_count (folder->summary);
+ if (ifolder->uidvalidity_on_server && isum->validity && isum->validity != ifolder->uidvalidity_on_server) {
+ invalidate_local_cache (ifolder, ifolder->uidvalidity_on_server);
+ need_rescan = TRUE;
+ }
+
/* We don't have valid unread count or modseq for currently-selected server
(unless we want to re-SELECT it). We fake unread count when fetching
message flags, but don't depend on modseq for the selected folder */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]