1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
4 * Copyright (C) 2003 Novell, Inc.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU Lesser General Public
8 * License as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * Authors: Rodrigo Moya <rodrigo@ximian.com>
27 #include <glib/gstdio.h>
29 #include "e-file-cache.h"
30 #include "e-data-server-util.h"
31 #include "e-xml-hash-utils.h"
33 struct _EFileCachePrivate {
46 G_DEFINE_TYPE (EFileCache, e_file_cache, G_TYPE_OBJECT);
49 e_file_cache_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
52 EFileCachePrivate *priv;
56 cache = E_FILE_CACHE (object);
59 /* FIXME: the property is being set twice. Need to investigate
60 * why and fix. Until then, we just return when called the
65 switch (property_id) {
67 /* make sure the directory for the cache exists */
68 priv->filename = g_strdup ( g_value_get_string (value));
69 dirname = g_path_get_dirname (priv->filename);
70 result = g_mkdir_with_parents (dirname, 0700);
76 e_xmlhash_destroy (priv->xml_hash);
77 priv->xml_hash = e_xmlhash_new (g_value_get_string (value));
79 /* if opening the cache file fails, remove it and try again */
80 if (!priv->xml_hash) {
81 g_unlink (g_value_get_string (value));
82 priv->xml_hash = e_xmlhash_new (g_value_get_string (value));
84 g_message (G_STRLOC ": could not open not re-create cache file %s",
85 g_value_get_string (value));
90 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
95 e_file_cache_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
98 EFileCachePrivate *priv;
100 cache = E_FILE_CACHE (object);
103 switch (property_id) {
105 g_value_set_string (value, priv->filename);
108 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
113 e_file_cache_finalize (GObject *object)
116 EFileCachePrivate *priv;
118 cache = E_FILE_CACHE (object);
122 if (priv->filename) {
123 g_free (priv->filename);
124 priv->filename = NULL;
127 if (priv->xml_hash) {
128 e_xmlhash_destroy (priv->xml_hash);
129 priv->xml_hash = NULL;
136 G_OBJECT_CLASS (e_file_cache_parent_class)->finalize (object);
140 e_file_cache_class_init (EFileCacheClass *klass)
142 GObjectClass *object_class;
144 object_class = G_OBJECT_CLASS (klass);
145 object_class->finalize = e_file_cache_finalize;
146 object_class->set_property = e_file_cache_set_property;
147 object_class->get_property = e_file_cache_get_property;
149 g_object_class_install_property (object_class, PROP_FILENAME,
150 g_param_spec_string ("filename", NULL, NULL, "",
151 G_PARAM_READABLE | G_PARAM_WRITABLE
152 | G_PARAM_CONSTRUCT_ONLY));
156 e_file_cache_init (EFileCache *cache)
158 EFileCachePrivate *priv;
160 priv = g_new0 (EFileCachePrivate, 1);
162 priv->frozen = FALSE;
168 * @filename: filename where the cache is kept.
170 * Creates a new #EFileCache object, which implements a cache of
171 * objects, very useful for remote backends.
173 * Return value: The newly created object.
176 e_file_cache_new (const char *filename)
180 cache = g_object_new (E_TYPE_FILE_CACHE, "filename", filename, NULL);
186 * e_file_cache_remove:
187 * @cache: A #EFileCache object.
189 * Remove the cache from disk.
191 * Returns: TRUE if successful, FALSE otherwise.
194 e_file_cache_remove (EFileCache *cache)
196 EFileCachePrivate *priv;
198 g_return_val_if_fail (E_IS_FILE_CACHE (cache), FALSE);
202 if (priv->filename) {
203 char *dirname, *full_path;
208 /* remove all files in the directory */
209 dirname = g_path_get_dirname (priv->filename);
210 dir = g_dir_open (dirname, 0, NULL);
212 while ((fname = g_dir_read_name (dir))) {
213 full_path = g_build_filename (dirname, fname, NULL);
214 if (g_unlink (full_path) != 0) {
228 /* remove the directory itself */
229 success = g_rmdir (dirname) == 0;
231 /* free all memory */
233 g_free (priv->filename);
234 priv->filename = NULL;
236 e_xmlhash_destroy (priv->xml_hash);
237 priv->xml_hash = NULL;
246 add_key_to_list (const char *key, const char *value, gpointer user_data)
248 GList **keys = user_data;
250 *keys = g_list_append (*keys, (char *) key);
254 * e_file_cache_clean:
255 * @cache: A #EFileCache object.
257 * Clean up the cache's contents.
259 * Returns: TRUE if successful, FALSE otherwise.
262 e_file_cache_clean (EFileCache *cache)
264 EFileCachePrivate *priv;
267 g_return_val_if_fail (E_IS_FILE_CACHE (cache), FALSE);
271 e_xmlhash_foreach_key (priv->xml_hash, (EXmlHashFunc) add_key_to_list, &keys);
272 while (keys != NULL) {
273 e_file_cache_remove_object (cache, (const char *) keys->data);
274 keys = g_list_remove (keys, keys->data);
283 const char *found_value;
287 find_object_in_hash (gpointer key, gpointer value, gpointer user_data)
289 CacheFindData *find_data = user_data;
291 if (find_data->found)
294 if (!strcmp (find_data->key, (const char *) key)) {
295 find_data->found = TRUE;
296 find_data->found_value = (const char *) value;
301 * e_file_cache_get_object:
304 e_file_cache_get_object (EFileCache *cache, const char *key)
306 CacheFindData find_data;
307 EFileCachePrivate *priv;
309 g_return_val_if_fail (E_IS_FILE_CACHE (cache), NULL);
310 g_return_val_if_fail (key != NULL, NULL);
315 find_data.found = FALSE;
316 find_data.found_value = NULL;
318 e_xmlhash_foreach_key (priv->xml_hash, (EXmlHashFunc) find_object_in_hash, &find_data);
320 return find_data.found_value;
324 add_object_to_list (const char *key, const char *value, gpointer user_data)
326 GSList **list = user_data;
328 *list = g_slist_prepend (*list, (char *) value);
332 * e_file_cache_get_objects:
335 e_file_cache_get_objects (EFileCache *cache)
337 EFileCachePrivate *priv;
340 g_return_val_if_fail (E_IS_FILE_CACHE (cache), NULL);
344 e_xmlhash_foreach_key (priv->xml_hash, (EXmlHashFunc) add_object_to_list, &list);
350 * e_file_cache_get_keys:
353 e_file_cache_get_keys (EFileCache *cache)
355 EFileCachePrivate *priv;
358 g_return_val_if_fail (E_IS_FILE_CACHE (cache), NULL);
362 e_xmlhash_foreach_key (priv->xml_hash, (EXmlHashFunc) add_key_to_list, &list);
368 * e_file_cache_add_object:
371 e_file_cache_add_object (EFileCache *cache, const char *key, const char *value)
373 EFileCachePrivate *priv;
375 g_return_val_if_fail (E_IS_FILE_CACHE (cache), FALSE);
376 g_return_val_if_fail (key != NULL, FALSE);
380 if (e_file_cache_get_object (cache, key))
383 e_xmlhash_add (priv->xml_hash, key, value);
387 e_xmlhash_write (priv->xml_hash);
395 * e_file_cache_replace_object:
398 e_file_cache_replace_object (EFileCache *cache, const char *key, const char *new_value)
400 EFileCachePrivate *priv;
402 g_return_val_if_fail (E_IS_FILE_CACHE (cache), FALSE);
403 g_return_val_if_fail (key != NULL, FALSE);
407 if (!e_file_cache_get_object (cache, key))
410 if (!e_file_cache_remove_object (cache, key))
413 return e_file_cache_add_object (cache, key, new_value);
417 * e_file_cache_remove_object:
420 e_file_cache_remove_object (EFileCache *cache, const char *key)
422 EFileCachePrivate *priv;
424 g_return_val_if_fail (E_IS_FILE_CACHE (cache), FALSE);
425 g_return_val_if_fail (key != NULL, FALSE);
429 if (!e_file_cache_get_object (cache, key))
432 e_xmlhash_remove (priv->xml_hash, key);
436 e_xmlhash_write (priv->xml_hash);
444 * e_file_cache_freeze_changes:
445 * @cache: An #EFileCache object.
447 * Disables temporarily all writes to disk for the given cache object.
450 e_file_cache_freeze_changes (EFileCache *cache)
452 EFileCachePrivate *priv;
454 g_return_if_fail (E_IS_FILE_CACHE (cache));
462 * e_file_cache_thaw_changes:
463 * @cache: An #EFileCache object.
465 * Enables again writes to disk on every change.
468 e_file_cache_thaw_changes (EFileCache *cache)
470 EFileCachePrivate *priv;
472 g_return_if_fail (E_IS_FILE_CACHE (cache));
476 priv->frozen = FALSE;
478 e_xmlhash_write (priv->xml_hash);
484 * e_file_cache_get_filename:
485 * @cache: A %EFileCache object.
487 * Gets the name of the file where the cache is being stored.
489 * Return value: The name of the cache.
492 e_file_cache_get_filename (EFileCache *cache)
494 g_return_val_if_fail (E_IS_FILE_CACHE (cache), NULL);
495 return (const char *) cache->priv->filename;