From: Milan Crha Date: Tue, 17 May 2011 09:30:38 +0000 (+0200) Subject: Bug #646898 - IMAPX should invalidated cache when uidvalidity changes X-Git-Tag: upstream/3.7.4~2055 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=621d4e0acf20729ed889e6266458f2bce27ff42f;p=platform%2Fupstream%2Fevolution-data-server.git Bug #646898 - IMAPX should invalidated cache when uidvalidity changes --- 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 */