aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-data-cache.c
diff options
context:
space:
mode:
authorNot Zed <NotZed@Ximian.com>2002-12-09 08:28:06 +0800
committerMichael Zucci <zucchi@src.gnome.org>2002-12-09 08:28:06 +0800
commit24b06cb2a4030282763c8f60ba3b0b8b806d15d3 (patch)
tree44b57fbee23cb93c7b1e0d26aa2aac5eb360ee5f /camel/camel-data-cache.c
parentc43c83145ab56f5422665f8a9c8468033064ce95 (diff)
downloadgsoc2013-evolution-24b06cb2a4030282763c8f60ba3b0b8b806d15d3.tar
gsoc2013-evolution-24b06cb2a4030282763c8f60ba3b0b8b806d15d3.tar.gz
gsoc2013-evolution-24b06cb2a4030282763c8f60ba3b0b8b806d15d3.tar.bz2
gsoc2013-evolution-24b06cb2a4030282763c8f60ba3b0b8b806d15d3.tar.lz
gsoc2013-evolution-24b06cb2a4030282763c8f60ba3b0b8b806d15d3.tar.xz
gsoc2013-evolution-24b06cb2a4030282763c8f60ba3b0b8b806d15d3.tar.zst
gsoc2013-evolution-24b06cb2a4030282763c8f60ba3b0b8b806d15d3.zip
Use a bag instead of a hashtable to track the cache streams.
2002-12-07 Not Zed <NotZed@Ximian.com> * camel-data-cache.c (data_cache_init): Use a bag instead of a hashtable to track the cache streams. (data_cache_finalise): Same. (free_busy): No longer needed. (data_cache_expire): use bag instead of hashtable. (stream_finalised): No longer required. (camel_data_cache_add): objectbagise (camel_data_cache_get): " (camel_data_cache_remove): " (data_cache_path): Set the now expired date before running expiry, so it plays better with multiple threads. Still a couple of harmless races. 2002-12-06 Not Zed <NotZed@Ximian.com> * providers/local/camel-spool-store.c (scan_dir): folders -> object bag. (get_folder_info_mbox): folders -> object bag. * providers/local/camel-mh-store.c (folder_info_new): folders -> object bag. * providers/local/camel-maildir-store.c (scan_dir): folders -> object bag. * providers/local/camel-local-store.c (rename_folder): folders -> object bag. * camel-private.h (CamelStorePrivate): Remove 'cache' lock, handled by the objectbag. * providers/imap/camel-imap-store.c (copy_folder): Removed. (imap_store_refresh_folders): folders -> object bag. (get_folder_counts): folders -> object bag. * camel-vee-store.c (vee_get_folder): changes for folders objectbag. (vee_get_folder_info): Change to use folders objectbag. Also, dont refresh the base folder if we're in FAST mode. (build_info): Removed, no longer needed. (vee_rename_folder): Fixed for folders objectbag. * camel-store.c (camel_store_init): init the folders objectbag. (camel_store_finalize): Destroy the folders object bag. (folder_matches): (folder_finalize): Removed, now handled implicitly by the objectbag. (camel_store_get_folder): object bag changes. (camel_store_delete_folder): " (get_subfolders): Removed, now handled without a callback. (camel_store_rename_folder): Changed to use object bag of folders. (trash_add_folder): Removed. (init_trash): use folders object bag. (copy_folder_cache): (sync_folder): Removed, no longer needed. Weird arsed code anyway. (store_sync): Use folder object bag instead of hashtable. (camel_store_unsubscribe_folder): " (camel_store_init): remove cache_lock init, no longer used. (camel_store_finalize): Same for cleanup. 2002-12-05 Not Zed <NotZed@Ximian.com> * camel-store.h (struct _CamelStore): change folders from a hashtable into a CamelObjectBag. * camel-object.c (camel_object_ref): Use type_lock instead of class lock for ref counting. (camel_object_unref): Use type_lock instead of class lock for unref. (camel_object_unref): If the object is 'bagged', then also look hooks, and remove it from any bags. (camel_object_bag_new): (camel_object_bag_destroy): (camel_object_bag_add): (camel_object_bag_get): (camel_object_bag_remove_unlocked): (camel_object_bag_list): (camel_object_bag_abort): (camel_object_bag_remove): New functions to implement a utility object which can manage a 'bag' of weakly ref'd children in an atomic & threadsafe way. svn path=/trunk/; revision=19056
Diffstat (limited to 'camel/camel-data-cache.c')
-rw-r--r--camel/camel-data-cache.c140
1 files changed, 35 insertions, 105 deletions
diff --git a/camel/camel-data-cache.c b/camel/camel-data-cache.c
index 6147a888f1..c0d399bbff 100644
--- a/camel/camel-data-cache.c
+++ b/camel/camel-data-cache.c
@@ -55,27 +55,17 @@ static void stream_finalised(CamelObject *o, void *event_data, void *data);
#define CAMEL_DATA_CACHE_CYCLE_TIME (60*60)
struct _CamelDataCachePrivate {
- GHashTable *busy_stream;
- GHashTable *busy_path;
+ CamelObjectBag *busy_bag;
int expire_inc;
time_t expire_last[1<<CAMEL_DATA_CACHE_BITS];
-
-#ifdef ENABLE_THREADS
- GMutex *lock;
-#define CDC_LOCK(c, l) g_mutex_lock(((CamelDataCache *)(c))->priv->l)
-#define CDC_UNLOCK(c, l) g_mutex_unlock(((CamelDataCache *)(c))->priv->l)
-#else
-#define CDC_LOCK(c, l)
-#define CDC_UNLOCK(c, l)
-#endif
};
static CamelObject *camel_data_cache_parent;
static void data_cache_class_init(CamelDataCacheClass *klass)
{
- camel_data_cache_parent = (CamelObject *)camel_type_get_global_classfuncs (camel_object_get_type ());
+ camel_data_cache_parent = (CamelObject *)camel_object_get_type ();
#if 0
klass->add = data_cache_add;
@@ -91,39 +81,17 @@ static void data_cache_init(CamelDataCache *cdc, CamelDataCacheClass *klass)
struct _CamelDataCachePrivate *p;
p = cdc->priv = g_malloc0(sizeof(*cdc->priv));
-
- p->busy_stream = g_hash_table_new(NULL, NULL);
- p->busy_path = g_hash_table_new(g_str_hash, g_str_equal);
-
-#ifdef ENABLE_THREADS
- p->lock = g_mutex_new();
-#endif
-}
-
-static void
-free_busy(CamelStream *stream, char *path, CamelDataCache *cdc)
-{
- d(printf(" Freeing busy stream %p path %s\n", stream, path));
- camel_object_unhook_event((CamelObject *)stream, "finalize", stream_finalised, cdc);
- camel_object_unref((CamelObject *)stream);
- g_free(path);
+ p->busy_bag = camel_object_bag_new(g_str_hash, g_str_equal);
}
static void data_cache_finalise(CamelDataCache *cdc)
{
struct _CamelDataCachePrivate *p;
+ GPtrArray *streams;
+ int i;
p = cdc->priv;
-
- d(printf("cache finalised, %d (= %d?) streams reamining\n", g_hash_table_size(p->busy_stream), g_hash_table_size(p->busy_path)));
-
- g_hash_table_foreach(p->busy_stream, (GHFunc)free_busy, cdc);
- g_hash_table_destroy(p->busy_path);
- g_hash_table_destroy(p->busy_stream);
-
-#ifdef ENABLE_THREADS
- g_mutex_free(p->lock);
-#endif
+ camel_object_bag_destroy(p->busy_bag);
g_free(p);
g_free (cdc->path);
@@ -249,10 +217,10 @@ data_cache_expire(CamelDataCache *cdc, const char *path, const char *keep, time_
|| (cdc->expire_access != -1 && st.st_atime + cdc->expire_access < now))) {
dd(printf("Has expired! Removing!\n"));
unlink(s->str);
- if (g_hash_table_lookup_extended(cdc->priv->busy_path, s->str, (void **)&oldpath, (void **)&stream)) {
- g_hash_table_remove(cdc->priv->busy_path, oldpath);
- g_hash_table_remove(cdc->priv->busy_stream, stream);
- g_free(oldpath);
+ stream = camel_object_bag_get(cdc->priv->busy_bag, s->str);
+ if (stream) {
+ camel_object_bag_remove(cdc->priv->busy_bag, stream);
+ camel_object_unref(stream);
}
}
}
@@ -283,10 +251,11 @@ data_cache_path(CamelDataCache *cdc, int create, const char *path, const char *k
dd(printf("Checking expire cycle time on dir '%s'\n", dir));
+ /* This has a race, but at worst we re-run an expire cycle which is safe */
now = time(0);
if (cdc->priv->expire_last[hash] + CAMEL_DATA_CACHE_CYCLE_TIME < now) {
- data_cache_expire(cdc, dir, key, now);
cdc->priv->expire_last[hash] = now;
+ data_cache_expire(cdc, dir, key, now);
}
cdc->priv->expire_inc = (cdc->priv->expire_inc + 1) & CAMEL_DATA_CACHE_MASK;
}
@@ -298,27 +267,6 @@ data_cache_path(CamelDataCache *cdc, int create, const char *path, const char *k
return real;
}
-static void
-stream_finalised(CamelObject *o, void *event_data, void *data)
-{
- CamelDataCache *cdc = data;
- char *key;
-
- d(printf("Stream finalised '%p'\n", data));
-
- CDC_LOCK(cdc, lock);
- key = g_hash_table_lookup(cdc->priv->busy_stream, o);
- if (key) {
- d(printf(" For path '%s'\n", key));
- g_hash_table_remove(cdc->priv->busy_path, key);
- g_hash_table_remove(cdc->priv->busy_stream, o);
- g_free(key);
- } else {
- d(printf(" Unknown stream?!\n"));
- }
- CDC_UNLOCK(cdc, lock);
-}
-
/**
* camel_data_cache_add:
* @cdc:
@@ -340,29 +288,24 @@ stream_finalised(CamelObject *o, void *event_data, void *data)
CamelStream *
camel_data_cache_add(CamelDataCache *cdc, const char *path, const char *key, CamelException *ex)
{
- char *real, *oldpath;
+ char *real;
CamelStream *stream;
- CDC_LOCK(cdc, lock);
-
real = data_cache_path(cdc, TRUE, path, key);
- if (g_hash_table_lookup_extended(cdc->priv->busy_path, real, (void **)&oldpath, (void **)&stream)) {
- g_hash_table_remove(cdc->priv->busy_path, oldpath);
- g_hash_table_remove(cdc->priv->busy_stream, stream);
- unlink(oldpath);
- g_free(oldpath);
+ stream = camel_object_bag_reserve(cdc->priv->busy_bag, real);
+ if (stream) {
+ unlink(real);
+ camel_object_bag_remove(cdc->priv->busy_bag, stream);
+ camel_object_unref(stream);
}
stream = camel_stream_fs_new_with_name(real, O_RDWR|O_CREAT|O_TRUNC, 0600);
- if (stream) {
- camel_object_hook_event((CamelObject *)stream, "finalize", stream_finalised, cdc);
- g_hash_table_insert(cdc->priv->busy_stream, stream, real);
- g_hash_table_insert(cdc->priv->busy_path, real, stream);
- } else {
- g_free(real);
- }
+ if (stream)
+ camel_object_bag_add(cdc->priv->busy_bag, real, stream);
+ else
+ camel_object_bag_abort(cdc->priv->busy_bag, real);
- CDC_UNLOCK(cdc, lock);
+ g_free(real);
return stream;
}
@@ -387,25 +330,16 @@ camel_data_cache_get(CamelDataCache *cdc, const char *path, const char *key, Cam
char *real;
CamelStream *stream;
- CDC_LOCK(cdc, lock);
-
real = data_cache_path(cdc, FALSE, path, key);
- stream = g_hash_table_lookup(cdc->priv->busy_path, real);
- if (stream) {
- camel_object_ref((CamelObject *)stream);
- g_free(real);
- } else {
+ stream = camel_object_bag_reserve(cdc->priv->busy_bag, real);
+ if (!stream) {
stream = camel_stream_fs_new_with_name(real, O_RDWR, 0600);
- if (stream) {
- camel_object_hook_event((CamelObject *)stream, "finalize", stream_finalised, cdc);
- g_hash_table_insert(cdc->priv->busy_stream, stream, real);
- g_hash_table_insert(cdc->priv->busy_path, real, stream);
- } else {
- g_free (real);
- }
+ if (stream)
+ camel_object_bag_add(cdc->priv->busy_bag, real, stream);
+ else
+ camel_object_bag_abort(cdc->priv->busy_bag, real);
}
-
- CDC_UNLOCK(cdc, lock);
+ g_free(real);
return stream;
}
@@ -425,16 +359,14 @@ int
camel_data_cache_remove(CamelDataCache *cdc, const char *path, const char *key, CamelException *ex)
{
CamelStream *stream;
- char *real, *oldpath;
+ char *real;
int ret;
- CDC_LOCK(cdc, lock);
-
real = data_cache_path(cdc, FALSE, path, key);
- if (g_hash_table_lookup_extended(cdc->priv->busy_path, real, (void **)&oldpath, (void **)&stream)) {
- g_hash_table_remove(cdc->priv->busy_path, oldpath);
- g_hash_table_remove(cdc->priv->busy_stream, stream);
- g_free(oldpath);
+ stream = camel_object_bag_get(cdc->priv->busy_bag, real);
+ if (stream) {
+ camel_object_bag_remove(cdc->priv->busy_bag, stream);
+ camel_object_unref(stream);
}
/* maybe we were a mem stream */
@@ -449,8 +381,6 @@ camel_data_cache_remove(CamelDataCache *cdc, const char *path, const char *key,
g_free(real);
- CDC_UNLOCK(cdc, lock);
-
return ret;
}