aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-store.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-store.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-store.c')
-rw-r--r--camel/camel-store.c254
1 files changed, 75 insertions, 179 deletions
diff --git a/camel/camel-store.c b/camel/camel-store.c
index d76af40e60..c6454fc8f5 100644
--- a/camel/camel-store.c
+++ b/camel/camel-store.c
@@ -126,8 +126,8 @@ camel_store_init (void *o)
CamelStoreClass *store_class = (CamelStoreClass *)CAMEL_OBJECT_GET_CLASS (o);
if (store_class->hash_folder_name) {
- store->folders = g_hash_table_new (store_class->hash_folder_name,
- store_class->compare_folder_name);
+ store->folders = camel_object_bag_new(store_class->hash_folder_name,
+ store_class->compare_folder_name);
} else
store->folders = NULL;
@@ -139,7 +139,6 @@ camel_store_init (void *o)
store->priv = g_malloc0 (sizeof (*store->priv));
#ifdef ENABLE_THREADS
store->priv->folder_lock = e_mutex_new (E_MUTEX_REC);
- store->priv->cache_lock = e_mutex_new (E_MUTEX_SIMPLE);
#endif
}
@@ -148,18 +147,11 @@ camel_store_finalize (CamelObject *object)
{
CamelStore *store = CAMEL_STORE (object);
- if (store->folders) {
- if (g_hash_table_size (store->folders) != 0) {
- d(g_warning ("Folder cache for store %p contains "
- "%d folders at destruction.", store,
- g_hash_table_size (store->folders)));
- }
- g_hash_table_destroy (store->folders);
- }
+ if (store->folders)
+ camel_object_bag_destroy(store->folders);
#ifdef ENABLE_THREADS
e_mutex_destroy (store->priv->folder_lock);
- e_mutex_destroy (store->priv->cache_lock);
#endif
g_free (store->priv);
}
@@ -197,28 +189,6 @@ store_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args)
return CAMEL_OBJECT_CLASS (parent_class)->getv (object, ex, args);
}
-static gboolean
-folder_matches (gpointer key, gpointer value, gpointer user_data)
-{
- if (value == user_data) {
- g_free (key);
- return TRUE;
- } else
- return FALSE;
-}
-
-static void
-folder_finalize (CamelObject *folder, gpointer event_data, gpointer user_data)
-{
- CamelStore *store = CAMEL_STORE (user_data);
-
- if (store->folders) {
- CAMEL_STORE_LOCK(store, cache_lock);
- g_hash_table_foreach_remove (store->folders, folder_matches, folder);
- CAMEL_STORE_UNLOCK(store, cache_lock);
- }
-}
-
static void
construct (CamelService *service, CamelSession *session,
CamelProvider *provider, CamelURL *url,
@@ -264,14 +234,9 @@ camel_store_get_folder (CamelStore *store, const char *folder_name, guint32 flag
CAMEL_STORE_LOCK(store, folder_lock);
- if (store->folders) {
+ if (store->folders)
/* Try cache first. */
- CAMEL_STORE_LOCK(store, cache_lock);
- folder = g_hash_table_lookup (store->folders, folder_name);
- if (folder)
- camel_object_ref (CAMEL_OBJECT (folder));
- CAMEL_STORE_UNLOCK(store, cache_lock);
- }
+ folder = camel_object_bag_reserve(store->folders, folder_name);
if (!folder) {
folder = CS_CLASS (store)->get_folder (store, folder_name, flags, ex);
@@ -280,17 +245,14 @@ camel_store_get_folder (CamelStore *store, const char *folder_name, guint32 flag
if (store->vtrash)
camel_vee_folder_add_folder (CAMEL_VEE_FOLDER (store->vtrash), folder);
- if (store->folders) {
- CAMEL_STORE_LOCK(store, cache_lock);
-
- g_hash_table_insert (store->folders, g_strdup (folder_name), folder);
-
- camel_object_hook_event (CAMEL_OBJECT (folder), "finalize", folder_finalize, store);
- CAMEL_STORE_UNLOCK(store, cache_lock);
- }
+ if (store->folders)
+ camel_object_bag_add(store->folders, folder_name, folder);
+ } else {
+ if (store->folders)
+ camel_object_bag_abort(store->folders, folder_name);
}
}
-
+
CAMEL_STORE_UNLOCK(store, folder_lock);
return folder;
}
@@ -362,12 +324,7 @@ camel_store_delete_folder (CamelStore *store, const char *folder_name, CamelExce
/* if we deleted a folder, force it out of the cache, and also out of the vtrash if setup */
if (store->folders) {
- CAMEL_STORE_LOCK(store, cache_lock);
- folder = g_hash_table_lookup(store->folders, folder_name);
- if (folder)
- camel_object_ref((CamelObject *)folder);
- CAMEL_STORE_UNLOCK(store, cache_lock);
-
+ folder = camel_object_bag_get(store->folders, folder_name);
if (folder) {
if (store->vtrash)
camel_vee_folder_remove_folder((CamelVeeFolder *)store->vtrash, folder);
@@ -377,17 +334,11 @@ camel_store_delete_folder (CamelStore *store, const char *folder_name, CamelExce
CS_CLASS (store)->delete_folder (store, folder_name, ex);
- if (folder)
- camel_object_unref((CamelObject *)folder);
+ if (store->folders)
+ camel_object_bag_remove(store->folders, folder);
- if (store->folders) {
- CAMEL_STORE_LOCK(store, cache_lock);
- if (g_hash_table_lookup_extended(store->folders, folder_name, (void **)&key, (void **)&folder)) {
- g_hash_table_remove (store->folders, key);
- g_free (key);
- }
- CAMEL_STORE_UNLOCK(store, cache_lock);
- }
+ if (folder)
+ camel_object_unref(folder);
CAMEL_STORE_UNLOCK(store, folder_lock);
}
@@ -399,34 +350,6 @@ rename_folder (CamelStore *store, const char *old_name, const char *new_name, Ca
camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store))));
}
-struct _get_info {
- CamelStore *store;
- GPtrArray *folders;
- const char *old;
- const char *new;
-};
-
-static void
-get_subfolders(char *key, CamelFolder *folder, struct _get_info *info)
-{
- int oldlen, namelen;
-
- namelen = strlen(folder->full_name);
- oldlen = strlen(info->old);
-
- if ((namelen == oldlen &&
- strcmp(folder->full_name, info->old) == 0)
- || ((namelen > oldlen)
- && strncmp(folder->full_name, info->old, oldlen) == 0
- && folder->full_name[oldlen] == info->store->dir_sep)) {
-
- d(printf("Found subfolder of '%s' == '%s'\n", info->old, folder->full_name));
- camel_object_ref((CamelObject *)folder);
- g_ptr_array_add(info->folders, folder);
- CAMEL_FOLDER_LOCK(folder, lock);
- }
-}
-
/**
* camel_store_rename_folder:
* @store: a CamelStore
@@ -440,26 +363,39 @@ void
camel_store_rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex)
{
char *key;
- CamelFolder *folder, *oldfolder;
- struct _get_info info = { store, NULL, old_name, new_name };
- int i;
+ CamelFolder *folder;
+ int i, oldlen, namelen;
+ GPtrArray *folders;
d(printf("store rename folder %s '%s' '%s'\n", ((CamelService *)store)->url->protocol, old_name, new_name));
if (strcmp(old_name, new_name) == 0)
return;
- info.folders = g_ptr_array_new();
+ oldlen = strlen(old_name);
CAMEL_STORE_LOCK(store, folder_lock);
/* If the folder is open (or any subfolders of the open folder)
We need to rename them atomically with renaming the actual folder path */
if (store->folders) {
- CAMEL_STORE_LOCK(store, cache_lock);
- /* Get all subfolders that are about to have their name changed */
- g_hash_table_foreach(store->folders, (GHFunc)get_subfolders, &info);
- CAMEL_STORE_UNLOCK(store, cache_lock);
+ folders = camel_object_bag_list(store->folders);
+ for (i=0;i<folders->len;i++) {
+ folder = folders->pdata[i];
+ namelen = strlen(folder->full_name);
+ if ((namelen == oldlen &&
+ strcmp(folder->full_name, old_name) == 0)
+ || ((namelen > oldlen)
+ && strncmp(folder->full_name, old_name, oldlen) == 0
+ && folder->full_name[oldlen] == store->dir_sep)) {
+ d(printf("Found subfolder of '%s' == '%s'\n", old_name, folder->full_name));
+ CAMEL_FOLDER_LOCK(folder, lock);
+ } else {
+ g_ptr_array_remove_index_fast(folders, i);
+ i--;
+ camel_object_unref(folder);
+ }
+ }
}
/* Now try the real rename (will emit renamed event) */
@@ -470,26 +406,19 @@ camel_store_rename_folder (CamelStore *store, const char *old_name, const char *
guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE;
CamelRenameInfo reninfo;
- CAMEL_STORE_LOCK(store, cache_lock);
- for (i=0;i<info.folders->len;i++) {
+ for (i=0;i<folders->len;i++) {
char *new;
- folder = info.folders->pdata[i];
+ folder = folders->pdata[i];
new = g_strdup_printf("%s%s", new_name, folder->full_name+strlen(old_name));
-
- if (g_hash_table_lookup_extended(store->folders, folder->full_name, (void **)&key, (void **)&oldfolder)) {
- g_hash_table_remove(store->folders, key);
- g_free(key);
- g_hash_table_insert(store->folders, new, oldfolder);
- }
-
+ camel_object_bag_remove(store->folders, folder);
+ camel_object_bag_add(store->folders, new, folder);
camel_folder_rename(folder, new);
CAMEL_FOLDER_UNLOCK(folder, lock);
- camel_object_unref((CamelObject *)folder);
+ camel_object_unref(folder);
}
- CAMEL_STORE_UNLOCK(store, cache_lock);
/* Emit changed signal */
if (store->flags & CAMEL_STORE_SUBSCRIPTIONS)
@@ -503,16 +432,16 @@ camel_store_rename_folder (CamelStore *store, const char *old_name, const char *
}
} else {
/* Failed, just unlock our folders for re-use */
- for (i=0;i<info.folders->len;i++) {
- folder = info.folders->pdata[i];
+ for (i=0;i<folders->len;i++) {
+ folder = folders->pdata[i];
CAMEL_FOLDER_UNLOCK(folder, lock);
- camel_object_unref((CamelObject *)folder);
+ camel_object_unref(folder);
}
}
CAMEL_STORE_UNLOCK(store, folder_lock);
- g_ptr_array_free(info.folders, TRUE);
+ g_ptr_array_free(folders, TRUE);
}
@@ -545,16 +474,6 @@ camel_store_get_inbox (CamelStore *store, CamelException *ex)
return folder;
}
-
-static void
-trash_add_folder (gpointer key, gpointer value, gpointer data)
-{
- CamelFolder *folder = CAMEL_FOLDER (value);
- CamelStore *store = CAMEL_STORE (data);
-
- camel_vee_folder_add_folder (CAMEL_VEE_FOLDER (store->vtrash), folder);
-}
-
static void
trash_finalize (CamelObject *trash, gpointer event_data, gpointer user_data)
{
@@ -572,15 +491,21 @@ init_trash (CamelStore *store)
store->vtrash = camel_vtrash_folder_new (store, CAMEL_VTRASH_NAME);
if (store->vtrash) {
+ /* FIXME: this should probably use the object bag or another one ? ... */
/* attach to the finalise event of the vtrash */
camel_object_hook_event (CAMEL_OBJECT (store->vtrash), "finalize",
trash_finalize, store);
/* add all the pre-opened folders to the vtrash */
if (store->folders) {
- CAMEL_STORE_LOCK(store, cache_lock);
- g_hash_table_foreach (store->folders, trash_add_folder, store);
- CAMEL_STORE_UNLOCK(store, cache_lock);
+ GPtrArray *folders = camel_object_bag_list(store->folders);
+ int i;
+
+ for (i=0;i<folders->len;i++) {
+ camel_vee_folder_add_folder (CAMEL_VEE_FOLDER (store->vtrash), (CamelFolder *)folders->pdata[i]);
+ camel_object_unref(folders->pdata[i]);
+ }
+ g_ptr_array_free(folders, TRUE);
}
}
}
@@ -629,42 +554,24 @@ camel_store_get_trash (CamelStore *store, CamelException *ex)
return folder;
}
-
-static void
-sync_folder (gpointer key, gpointer folder, gpointer ex)
-{
- if (!camel_exception_is_set (ex))
- camel_folder_sync (folder, FALSE, ex);
-
- camel_object_unref (CAMEL_OBJECT (folder));
- g_free (key);
-}
-
-static void
-copy_folder_cache (gpointer key, gpointer folder, gpointer hash)
-{
- g_hash_table_insert ((GHashTable *) hash, g_strdup (key), folder);
- camel_object_ref (CAMEL_OBJECT (folder));
-}
-
static void
store_sync (CamelStore *store, CamelException *ex)
{
if (store->folders) {
- CamelException internal_ex;
- GHashTable *hash;
-
- hash = g_hash_table_new (CS_CLASS (store)->hash_folder_name,
- CS_CLASS (store)->compare_folder_name);
-
- camel_exception_init (&internal_ex);
- CAMEL_STORE_LOCK(store, cache_lock);
- g_hash_table_foreach (store->folders, copy_folder_cache, hash);
- CAMEL_STORE_UNLOCK(store, cache_lock);
- camel_exception_xfer (ex, &internal_ex);
-
- g_hash_table_foreach (hash, sync_folder, &internal_ex);
- g_hash_table_destroy (hash);
+ GPtrArray *folders;
+ CamelFolder *folder;
+ CamelException x;
+ int i;
+
+ folders = camel_object_bag_list(store->folders);
+ for (i=0;i<folders->len;i++) {
+ folder = folders->pdata[i];
+ if (!camel_exception_is_set(&x))
+ camel_folder_sync(folder, FALSE, &x);
+ camel_object_unref(folder);
+ }
+ camel_exception_xfer(ex, &x);
+ g_ptr_array_free(folders, TRUE);
}
}
@@ -1102,12 +1009,7 @@ camel_store_unsubscribe_folder (CamelStore *store,
/* if we deleted a folder, force it out of the cache, and also out of the vtrash if setup */
if (store->folders) {
- CAMEL_STORE_LOCK(store, cache_lock);
- folder = g_hash_table_lookup(store->folders, folder_name);
- if (folder)
- camel_object_ref((CamelObject *)folder);
- CAMEL_STORE_UNLOCK(store, cache_lock);
-
+ folder = camel_object_bag_get(store->folders, folder_name);
if (folder) {
if (store->vtrash)
camel_vee_folder_remove_folder((CamelVeeFolder *)store->vtrash, folder);
@@ -1117,17 +1019,11 @@ camel_store_unsubscribe_folder (CamelStore *store,
CS_CLASS (store)->unsubscribe_folder (store, folder_name, ex);
- if (folder)
- camel_object_unref((CamelObject *)folder);
+ if (store->folders)
+ camel_object_bag_remove(store->folders, folder);
- if (store->folders) {
- CAMEL_STORE_LOCK(store, cache_lock);
- if (g_hash_table_lookup_extended(store->folders, folder_name, (void **)&key, (void **)&folder)) {
- g_hash_table_remove (store->folders, key);
- g_free (key);
- }
- CAMEL_STORE_UNLOCK(store, cache_lock);
- }
+ if (folder)
+ camel_object_unref(folder);
CAMEL_STORE_UNLOCK(store, folder_lock);
}