}
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;
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);
}
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) {
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);
}
}
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);
+}
}
}
+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,
}
}
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);
}
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) {
}
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,
#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 */