diff options
Diffstat (limited to 'camel/providers/local/camel-local-folder.c')
-rw-r--r-- | camel/providers/local/camel-local-folder.c | 263 |
1 files changed, 44 insertions, 219 deletions
diff --git a/camel/providers/local/camel-local-folder.c b/camel/providers/local/camel-local-folder.c index 931c95a114..116a10ea7d 100644 --- a/camel/providers/local/camel-local-folder.c +++ b/camel/providers/local/camel-local-folder.c @@ -42,6 +42,8 @@ #include "camel-mime-filter-from.h" #include "camel-exception.h" +#include "camel-local-private.h" + #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ static CamelFolderClass *parent_class = NULL; @@ -55,30 +57,11 @@ static int local_lock(CamelLocalFolder *lf, CamelLockType type, CamelException * static void local_unlock(CamelLocalFolder *lf); static void local_sync(CamelFolder *folder, gboolean expunge, CamelException *ex); -static gint local_get_message_count(CamelFolder *folder); -static gint local_get_unread_message_count(CamelFolder *folder); - -static GPtrArray *local_get_uids(CamelFolder *folder); -static GPtrArray *local_get_summary(CamelFolder *folder); -#if 0 -static void local_append_message(CamelFolder *folder, CamelMimeMessage * message, const CamelMessageInfo * info, CamelException *ex); -static CamelMimeMessage *local_get_message(CamelFolder *folder, const gchar * uid, CamelException *ex); -#endif static void local_expunge(CamelFolder *folder, CamelException *ex); -static const CamelMessageInfo *local_get_message_info(CamelFolder *folder, const char *uid); - static GPtrArray *local_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex); static void local_search_free(CamelFolder *folder, GPtrArray * result); -static guint32 local_get_message_flags(CamelFolder *folder, const char *uid); -static void local_set_message_flags(CamelFolder *folder, const char *uid, guint32 flags, guint32 set); -static gboolean local_get_message_user_flag(CamelFolder *folder, const char *uid, const char *name); -static void local_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value); -static const char *local_get_message_user_tag(CamelFolder *folder, const char *uid, const char *name); -static void local_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value); - - static void local_finalize(CamelObject * object); static void @@ -92,26 +75,11 @@ camel_local_folder_class_init(CamelLocalFolderClass * camel_local_folder_class) /* virtual method overload */ camel_folder_class->sync = local_sync; - camel_folder_class->get_message_count = local_get_message_count; - camel_folder_class->get_unread_message_count = local_get_unread_message_count; - camel_folder_class->get_uids = local_get_uids; - camel_folder_class->free_uids = camel_folder_free_deep; - camel_folder_class->get_summary = local_get_summary; - camel_folder_class->free_summary = camel_folder_free_nop; camel_folder_class->expunge = local_expunge; camel_folder_class->search_by_expression = local_search_by_expression; camel_folder_class->search_free = local_search_free; - camel_folder_class->get_message_info = local_get_message_info; - - camel_folder_class->get_message_flags = local_get_message_flags; - camel_folder_class->set_message_flags = local_set_message_flags; - camel_folder_class->get_message_user_flag = local_get_message_user_flag; - camel_folder_class->set_message_user_flag = local_set_message_user_flag; - camel_folder_class->get_message_user_tag = local_get_message_user_tag; - camel_folder_class->set_message_user_tag = local_set_message_user_tag; - camel_local_folder_class->lock = local_lock; camel_local_folder_class->unlock = local_unlock; } @@ -129,18 +97,25 @@ local_init(gpointer object, gpointer klass) CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_USER; - local_folder->summary = NULL; + folder->summary = NULL; local_folder->search = NULL; + + local_folder->priv = g_malloc0(sizeof(*local_folder->priv)); +#ifdef ENABLE_THREADS + local_folder->priv->search_lock = g_mutex_new(); +#endif } static void local_finalize(CamelObject * object) { CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(object); + CamelFolder *folder = (CamelFolder *)object; - if (local_folder->summary) { - camel_local_summary_sync(local_folder->summary, FALSE, local_folder->changes, NULL); - camel_object_unref((CamelObject *)local_folder->summary); + if (folder->summary) { + camel_local_summary_sync((CamelLocalSummary *)folder->summary, FALSE, local_folder->changes, NULL); + camel_object_unref((CamelObject *)folder->summary); + folder->summary = NULL; } if (local_folder->search) { @@ -160,6 +135,11 @@ local_finalize(CamelObject * object) g_free(local_folder->index_path); camel_folder_change_info_free(local_folder->changes); + +#ifdef ENABLE_THREADS + g_mutex_free(local_folder->priv->search_lock); +#endif + g_free(local_folder->priv); } CamelType camel_local_folder_get_type(void) @@ -228,8 +208,8 @@ camel_local_folder_construct(CamelLocalFolder *lf, CamelStore *parent_store, con lf->flags = flags; - lf->summary = CLOCALF_CLASS(lf)->create_summary(lf->summary_path, lf->folder_path, lf->index); - if (camel_local_summary_load(lf->summary, forceindex, ex) == -1) { + folder->summary = (CamelFolderSummary *)CLOCALF_CLASS(lf)->create_summary(lf->summary_path, lf->folder_path, lf->index); + if (camel_local_summary_load((CamelLocalSummary *)folder->summary, forceindex, ex) == -1) { camel_object_unref (CAMEL_OBJECT (folder)); return NULL; } @@ -289,7 +269,7 @@ local_sync(CamelFolder *folder, gboolean expunge, CamelException *ex) return; /* if sync fails, we'll pass it up on exit through ex */ - camel_local_summary_sync(lf->summary, expunge, lf->changes, ex); + camel_local_summary_sync((CamelLocalSummary *)folder->summary, expunge, lf->changes, ex); camel_local_folder_unlock(lf); if (camel_folder_change_info_changed(lf->changes)) { @@ -300,8 +280,8 @@ local_sync(CamelFolder *folder, gboolean expunge, CamelException *ex) /* force save of metadata */ if (lf->index) ibex_save(lf->index); - if (lf->summary) - camel_folder_summary_save(CAMEL_FOLDER_SUMMARY(lf->summary)); + if (folder->summary) + camel_folder_summary_save(folder->summary); } static void @@ -310,203 +290,48 @@ local_expunge(CamelFolder *folder, CamelException *ex) d(printf("expunge\n")); /* Just do a sync with expunge, serves the same purpose */ - camel_folder_sync(folder, TRUE, ex); -} - -/* - The following functions all work off the summary, so the default operations provided - in camel-local-folder will suffice for all subclasses. They may want to - snoop various operations to ensure the status remains synced, or just wait - for the sync operation -*/ -static gint -local_get_message_count(CamelFolder *folder) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); - - g_return_val_if_fail(local_folder->summary != NULL, -1); - - return camel_folder_summary_count(CAMEL_FOLDER_SUMMARY(local_folder->summary)); -} - -static gint -local_get_unread_message_count(CamelFolder *folder) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); - CamelMessageInfo *info; - GPtrArray *infolist; - gint i, max, count = 0; - - g_return_val_if_fail(local_folder->summary != NULL, -1); - - max = camel_folder_summary_count(CAMEL_FOLDER_SUMMARY(local_folder->summary)); - if (max == -1) - return -1; - - infolist = local_get_summary(folder); - - for (i = 0; i < infolist->len; i++) { - info = (CamelMessageInfo *) g_ptr_array_index(infolist, i); - if (!(info->flags & CAMEL_MESSAGE_SEEN)) - count++; - } - - return count; + /* call the callback directly, to avoid locking problems */ + CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->sync(folder, TRUE, ex); } static GPtrArray * -local_get_uids(CamelFolder *folder) -{ - GPtrArray *array; - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); - int i, count; - - count = camel_folder_summary_count(CAMEL_FOLDER_SUMMARY(local_folder->summary)); - array = g_ptr_array_new(); - g_ptr_array_set_size(array, count); - for (i = 0; i < count; i++) { - CamelMessageInfo *info = camel_folder_summary_index(CAMEL_FOLDER_SUMMARY(local_folder->summary), i); - - array->pdata[i] = g_strdup(camel_message_info_uid(info)); - } - - return array; -} - -GPtrArray * -local_get_summary(CamelFolder *folder) +local_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex) { CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); + GPtrArray *summary, *matches; - return CAMEL_FOLDER_SUMMARY(local_folder->summary)->messages; -} - -/* get a single message info, by uid */ -static const CamelMessageInfo * -local_get_message_info(CamelFolder *folder, const char *uid) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); + /* NOTE: could get away without the search lock by creating a new + search object each time */ - return camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(local_folder->summary), uid); -} - -static GPtrArray * -local_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); + CAMEL_LOCAL_FOLDER_LOCK(folder, search_lock); - if (local_folder->search == NULL) { + if (local_folder->search == NULL) local_folder->search = camel_folder_search_new(); - } camel_folder_search_set_folder(local_folder->search, folder); - if (local_folder->summary) { - /* FIXME: dont access summary array directly? */ - camel_folder_search_set_summary(local_folder->search, - CAMEL_FOLDER_SUMMARY(local_folder->summary)->messages); - } - camel_folder_search_set_body_index(local_folder->search, local_folder->index); + summary = camel_folder_get_summary(folder); + camel_folder_search_set_summary(local_folder->search, summary); - return camel_folder_search_execute_expression(local_folder->search, expression, ex); -} - -static void -local_search_free(CamelFolder *folder, GPtrArray * result) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); - - camel_folder_search_free_result(local_folder->search, result); -} - -static guint32 -local_get_message_flags(CamelFolder *folder, const char *uid) -{ - CamelMessageInfo *info; - CamelLocalFolder *mf = CAMEL_LOCAL_FOLDER(folder); - - info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid); - g_return_val_if_fail(info != NULL, 0); - - return info->flags; -} - -static void -local_set_message_flags(CamelFolder *folder, const char *uid, guint32 flags, guint32 set) -{ - CamelMessageInfo *info; - CamelLocalFolder *mf = CAMEL_LOCAL_FOLDER(folder); - guint32 new; - - info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid); - g_return_if_fail(info != NULL); - - new = (info->flags & ~flags) | (set & flags); - if (new == info->flags) - return; - - info->flags = new | CAMEL_MESSAGE_FOLDER_FLAGGED; - camel_folder_summary_touch(CAMEL_FOLDER_SUMMARY(mf->summary)); - - camel_object_trigger_event(CAMEL_OBJECT(folder), "message_changed", (char *) uid); -} + matches = camel_folder_search_execute_expression(local_folder->search, expression, ex); -static gboolean -local_get_message_user_flag(CamelFolder *folder, const char *uid, const char *name) -{ - CamelMessageInfo *info; - CamelLocalFolder *mf = CAMEL_LOCAL_FOLDER(folder); + CAMEL_LOCAL_FOLDER_UNLOCK(folder, search_lock); - info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid); - g_return_val_if_fail(info != NULL, FALSE); + camel_folder_free_summary(folder, summary); - return camel_flag_get(&info->user_flags, name); + return matches; } static void -local_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value) -{ - CamelMessageInfo *info; - CamelLocalFolder *mf = CAMEL_LOCAL_FOLDER(folder); - - info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid); - g_return_if_fail(info != NULL); - - if (!camel_flag_set(&info->user_flags, name, value)) - return; - - info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED|CAMEL_MESSAGE_FOLDER_XEVCHANGE; - camel_folder_summary_touch(CAMEL_FOLDER_SUMMARY(mf->summary)); - camel_object_trigger_event(CAMEL_OBJECT(folder), "message_changed", (char *) uid); -} - -static const char * -local_get_message_user_tag(CamelFolder *folder, const char *uid, const char *name) -{ - CamelMessageInfo *info; - CamelLocalFolder *mf = CAMEL_LOCAL_FOLDER(folder); - - info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid); - g_return_val_if_fail(info != NULL, FALSE); - - return camel_tag_get(&info->user_tags, name); -} - -static void -local_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value) +local_search_free(CamelFolder *folder, GPtrArray * result) { - CamelMessageInfo *info; - CamelLocalFolder *mf = CAMEL_LOCAL_FOLDER(folder); + CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); - info = camel_folder_summary_uid(CAMEL_FOLDER_SUMMARY(mf->summary), uid); - g_return_if_fail(info != NULL); + /* we need to lock this free because of the way search_free_result works */ + /* FIXME: put the lock inside search_free_result */ + CAMEL_LOCAL_FOLDER_LOCK(folder, search_lock); - if (!camel_tag_set(&info->user_tags, name, value)) - return; + camel_folder_search_free_result(local_folder->search, result); - info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED|CAMEL_MESSAGE_FOLDER_XEVCHANGE; - camel_folder_summary_touch(CAMEL_FOLDER_SUMMARY(mf->summary)); - camel_object_trigger_event(CAMEL_OBJECT(folder), "message_changed", (char *) uid); + CAMEL_LOCAL_FOLDER_UNLOCK(folder, search_lock); } - - |