diff options
author | Not Zed <NotZed@HelixCode.com> | 2000-12-24 08:46:20 +0800 |
---|---|---|
committer | Michael Zucci <zucchi@src.gnome.org> | 2000-12-24 08:46:20 +0800 |
commit | 6de256c2a2b23f30d35e4a2213ad5839bf141d06 (patch) | |
tree | a34d8be64c0718070c4e1ea9548282912f37b387 /camel/providers | |
parent | 6183d89039ba67a7f3869f460c13aff09a548471 (diff) | |
download | gsoc2013-evolution-6de256c2a2b23f30d35e4a2213ad5839bf141d06.tar gsoc2013-evolution-6de256c2a2b23f30d35e4a2213ad5839bf141d06.tar.gz gsoc2013-evolution-6de256c2a2b23f30d35e4a2213ad5839bf141d06.tar.bz2 gsoc2013-evolution-6de256c2a2b23f30d35e4a2213ad5839bf141d06.tar.lz gsoc2013-evolution-6de256c2a2b23f30d35e4a2213ad5839bf141d06.tar.xz gsoc2013-evolution-6de256c2a2b23f30d35e4a2213ad5839bf141d06.tar.zst gsoc2013-evolution-6de256c2a2b23f30d35e4a2213ad5839bf141d06.zip |
Lock the command channel while searching. (imap_body_contains): If
2000-12-24 Not Zed <NotZed@HelixCode.com>
* providers/imap/camel-imap-search.c (imap_body_contains): Lock
the command channel while searching.
(imap_body_contains): If performing a whole uid search, then add
references to our own summary items, dont look it up in the
folder. This way they can't vanish unexpectedly.
* providers/imap/camel-imap-folder.h (CamelImapFolder): Added a
private field.
* providers/imap/camel-imap-private.h: Added lock for imap
searches.
* Merge from camel-mt-branch.
* providers/imap/camel-imap-folder.c (imap_update_summary): Merge
fix, use the folder->summary.
(imap_get_message_flags, imap_set_message_flags,
imap_get_message_user_flag, imap_set_message_user_flag): Removed
again.
(camel_imap_folder_init): Setup private data/lock.
(imap_finalize): Free private data/search lock.
(imap_search_free): Lock the search_lock.
(imap_search_by_expression): Lock the search lock when using the
search object. Also copy/ref hte summary, rather than getting it
directly.
(imap_refresh_info): Free any info lookups. Use folder->summary
not imap_folder->summary. And lock around commands.
svn path=/trunk/; revision=7150
Diffstat (limited to 'camel/providers')
25 files changed, 746 insertions, 923 deletions
diff --git a/camel/providers/imap/Makefile.am b/camel/providers/imap/Makefile.am index 03dec12608..35a4a97e77 100644 --- a/camel/providers/imap/Makefile.am +++ b/camel/providers/imap/Makefile.am @@ -42,6 +42,9 @@ libcamelimapinclude_HEADERS = \ libcamelimap_la_LDFLAGS = $(KRB4_LDFLAGS) -version-info 0:0:0 +noinst_HEADERS = \ + camel-imap-private.h + EXTRA_DIST = libcamelimap.urls diff --git a/camel/providers/imap/camel-imap-auth.c b/camel/providers/imap/camel-imap-auth.c index c510eaf01c..42abd1fa55 100644 --- a/camel/providers/imap/camel-imap-auth.c +++ b/camel/providers/imap/camel-imap-auth.c @@ -42,6 +42,10 @@ #include "camel-imap-command.h" #include "camel-imap-utils.h" +#include "camel-imap-private.h" + +#ifdef HAVE_KRB4 + static char * base64_encode_simple (const char *data, int len) { @@ -66,7 +70,6 @@ base64_decode_simple (char *data, int len) (unsigned char *)data, &state, &save); } -#ifdef HAVE_KRB4 #define IMAP_KERBEROS_V4_PROTECTION_NONE 1 #define IMAP_KERBEROS_V4_PROTECTION_INTEGRITY 2 #define IMAP_KERBEROS_V4_PROTECTION_PRIVACY 4 @@ -85,14 +88,17 @@ imap_try_kerberos_v4_auth (CamelImapStore *store, CamelException *ex) des_cblock session; des_key_schedule schedule; + CAMEL_IMAP_STORE_LOCK(store, command_lock); + /* The kickoff. */ response = camel_imap_command (store, NULL, ex, "AUTHENTICATE KERBEROS_V4"); if (!response) - return FALSE; + goto fail; resp = camel_imap_response_extract_continuation (response, ex); if (!resp) - return FALSE; + goto fail; + data = imap_next_word (resp); /* First server response is a base64-encoded 32-bit random number @@ -182,6 +188,7 @@ imap_try_kerberos_v4_auth (CamelImapStore *store, CamelException *ex) if (!response) goto lose; camel_imap_response_free (response); + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); return TRUE; break_and_lose: @@ -197,6 +204,8 @@ imap_try_kerberos_v4_auth (CamelImapStore *store, CamelException *ex) camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, _("Bad authentication response from server.")); } +fail: + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); return FALSE; } #endif /* HAVE_KRB4 */ diff --git a/camel/providers/imap/camel-imap-command.c b/camel/providers/imap/camel-imap-command.c index b61c9f8cd3..df27fba0fb 100644 --- a/camel/providers/imap/camel-imap-command.c +++ b/camel/providers/imap/camel-imap-command.c @@ -67,6 +67,9 @@ static char *imap_command_strdup_vprintf (CamelImapStore *store, * and quoted strings otherwise. (%S does not support strings that * contain newlines.) * + * This function assumes you have an exclusive lock on the command + * channel/stream. + * * Return value: %NULL if an error occurred (in which case @ex will * be set). Otherwise, a CamelImapResponse describing the server's * response, which the caller must free with camel_imap_response_free(). @@ -120,6 +123,8 @@ camel_imap_command (CamelImapStore *store, CamelFolder *folder, * This method is for sending continuing responses to the IMAP server * after camel_imap_command returns a CAMEL_IMAP_PLUS response. * + * This function assumes you have an exclusive lock on the remote stream. + * * Return value: as for camel_imap_command() **/ CamelImapResponse * diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c index 9da5103b68..952e28faa7 100644 --- a/camel/providers/imap/camel-imap-folder.c +++ b/camel/providers/imap/camel-imap-folder.c @@ -56,6 +56,7 @@ #include "camel-mime-filter-crlf.h" #include "camel-exception.h" #include "camel-mime-utils.h" +#include "camel-imap-private.h" #define d(x) x @@ -69,10 +70,6 @@ static void imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex static const char *imap_get_full_name (CamelFolder *folder); static void imap_expunge (CamelFolder *folder, CamelException *ex); -/* message counts */ -static gint imap_get_message_count (CamelFolder *folder); -static gint imap_get_unread_message_count (CamelFolder *folder); - /* message manipulation */ static CamelMimeMessage *imap_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex); @@ -84,10 +81,6 @@ static void imap_move_message_to (CamelFolder *source, const char *uid, CamelFolder *destination, CamelException *ex); /* summary info */ -static GPtrArray *imap_get_uids (CamelFolder *folder); -static GPtrArray *imap_get_summary (CamelFolder *folder); -static const CamelMessageInfo *imap_get_message_info (CamelFolder *folder, const char *uid); - static void imap_update_summary (CamelFolder *folder, int first, int last, CamelFolderChangeInfo *changes, CamelException *ex); @@ -119,27 +112,13 @@ camel_imap_folder_class_init (CamelImapFolderClass *camel_imap_folder_class) camel_folder_class->expunge = imap_expunge; camel_folder_class->get_full_name = imap_get_full_name; - camel_folder_class->get_uids = imap_get_uids; - camel_folder_class->free_uids = camel_folder_free_nop; - - camel_folder_class->get_message_count = imap_get_message_count; - camel_folder_class->get_unread_message_count = imap_get_unread_message_count; camel_folder_class->get_message = imap_get_message; camel_folder_class->append_message = imap_append_message; camel_folder_class->copy_message_to = imap_copy_message_to; camel_folder_class->move_message_to = imap_move_message_to; - camel_folder_class->get_summary = imap_get_summary; - camel_folder_class->get_message_info = imap_get_message_info; - camel_folder_class->free_summary = camel_folder_free_nop; - camel_folder_class->search_by_expression = imap_search_by_expression; camel_folder_class->search_free = imap_search_free; - - camel_folder_class->get_message_flags = imap_get_message_flags; - camel_folder_class->set_message_flags = imap_set_message_flags; - camel_folder_class->get_message_user_flag = imap_get_message_user_flag; - camel_folder_class->set_message_user_flag = imap_set_message_user_flag; } static void @@ -151,7 +130,11 @@ camel_imap_folder_init (gpointer object, gpointer klass) folder->has_summary_capability = TRUE; folder->has_search_capability = TRUE; - imap_folder->summary = NULL; + folder->summary = NULL; + imap_folder->priv = g_malloc0(sizeof(*imap_folder->priv)); +#ifdef ENABLE_THREADS + imap_folder->priv->search_lock = g_mutex_new(); +#endif } CamelType @@ -188,7 +171,10 @@ camel_imap_folder_new (CamelStore *parent, const char *folder_name, camel_folder_construct (folder, parent, folder_name, short_name); + CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); response = camel_imap_command (imap_store, folder, ex, NULL); + CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); + if (!response) { camel_object_unref ((CamelObject *)folder); return NULL; @@ -213,8 +199,8 @@ camel_imap_folder_new (CamelStore *parent, const char *folder_name, } camel_imap_response_free (response); - imap_folder->summary = camel_imap_summary_new (summary_file, validity); - if (!imap_folder->summary) { + folder->summary = camel_imap_summary_new (summary_file, validity); + if (!folder->summary) { camel_object_unref (CAMEL_OBJECT (folder)); camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Could not load summary for %s"), @@ -236,9 +222,13 @@ imap_finalize (CamelObject *object) { CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object); - camel_object_unref ((CamelObject *)imap_folder->summary); if (imap_folder->search) camel_object_unref ((CamelObject *)imap_folder->search); + +#ifdef ENABLE_THREADS + g_mutex_free(imap_folder->priv->search_lock); +#endif + g_free(imap_folder->priv); } static void @@ -262,9 +252,11 @@ imap_refresh_info (CamelFolder *folder, CamelException *ex) /* Get UIDs and flags of all messages. */ if (imap_folder->exists) { + CAMEL_IMAP_STORE_LOCK(store, command_lock); response = camel_imap_command (store, folder, ex, "FETCH 1:%d (UID FLAGS)", imap_folder->exists); + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); if (!response) { camel_folder_change_info_free (changes); return; @@ -298,18 +290,21 @@ imap_refresh_info (CamelFolder *folder, CamelException *ex) * the UID in the folder, that it means the message was * deleted on the server, so we remove it from the summary. */ - summary_len = camel_folder_summary_count (imap_folder->summary); + summary_len = camel_folder_summary_count (folder->summary); for (i = 0; i < summary_len && i < imap_folder->exists; i++) { - info = camel_folder_summary_index (imap_folder->summary, i); - iinfo = (CamelImapMessageInfo *)info; - /* Shouldn't happen, but... */ if (!new[i].uid) continue; + info = camel_folder_summary_index (imap_folder->summary, i); + iinfo = (CamelImapMessageInfo *)info; + if (strcmp (camel_message_info_uid (info), new[i].uid) != 0) { camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info)); camel_folder_summary_remove (imap_folder->summary, info); + camel_folder_summary_info_free(folder->summary, info); + folder_changed = TRUE; + g_free (new[i].uid); i--; summary_len--; continue; @@ -328,14 +323,17 @@ imap_refresh_info (CamelFolder *folder, CamelException *ex) camel_folder_change_info_change_uid (changes, new[i].uid); } + camel_folder_summary_info_free(folder->summary, info); + g_free (new[i].uid); } /* Remove any leftover cached summary messages. */ while (summary_len > i + 1) { - info = camel_folder_summary_index (imap_folder->summary, --summary_len); + info = camel_folder_summary_index (folder->summary, --summary_len); camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info)); - camel_folder_summary_remove (imap_folder->summary, info); + camel_folder_summary_remove (folder->summary, info); + camel_folder_summary_info_free(folder->summary, info); } /* Add any new folder messages. */ @@ -360,40 +358,48 @@ static void imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) { CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); + /*CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);*/ CamelImapResponse *response; int i, max; /* Set the flags on any messages that have changed this session */ - max = camel_folder_summary_count (imap_folder->summary); + max = camel_folder_summary_count (folder->summary); for (i = 0; i < max; i++) { CamelMessageInfo *info; - info = camel_folder_summary_index (imap_folder->summary, i); - if (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) { + info = camel_folder_summary_index (folder->summary, i); + if (info && (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) { char *flags; flags = imap_create_flag_list (info->flags); if (flags) { + CAMEL_IMAP_STORE_LOCK(store, command_lock); response = camel_imap_command ( store, folder, ex, "UID STORE %s FLAGS.SILENT %s", camel_message_info_uid(info), flags); + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); + g_free (flags); - if (!response) + if (!response) { + camel_folder_summary_info_free(folder->summary, info); return; + } camel_imap_response_free (response); } info->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED; } + camel_folder_summary_info_free(folder->summary, info); } if (expunge) { + CAMEL_IMAP_STORE_LOCK(store, command_lock); response = camel_imap_command (store, folder, ex, "EXPUNGE"); + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); camel_imap_response_free (response); } - camel_folder_summary_save (imap_folder->summary); + camel_folder_summary_save (folder->summary); } static void @@ -417,31 +423,6 @@ imap_get_full_name (CamelFolder *folder) return folder->full_name; } -static gint -imap_get_message_count (CamelFolder *folder) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - - return camel_folder_summary_count (imap_folder->summary); -} - -static gint -imap_get_unread_message_count (CamelFolder *folder) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - CamelMessageInfo *info; - int i, max, count = 0; - - max = camel_folder_summary_count (imap_folder->summary); - for (i = 0; i < max; i++) { - info = camel_folder_summary_index (imap_folder->summary, i); - if (!(info->flags & CAMEL_MESSAGE_SEEN)) - count++; - } - - return count; -} - static void imap_append_message (CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, CamelException *ex) @@ -476,6 +457,7 @@ imap_append_message (CamelFolder *folder, CamelMimeMessage *message, camel_object_unref (CAMEL_OBJECT (crlf_filter)); camel_object_unref (CAMEL_OBJECT (memstream)); + CAMEL_IMAP_STORE_LOCK(store, command_lock); response = camel_imap_command (store, NULL, ex, "APPEND %S%s%s {%d}", folder->full_name, flagstr ? " " : "", flagstr ? flagstr : "", ba->len); @@ -483,11 +465,13 @@ imap_append_message (CamelFolder *folder, CamelMimeMessage *message, if (!response) { g_byte_array_free (ba, TRUE); + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); return; } result = camel_imap_response_extract_continuation (response, ex); if (!result) { g_byte_array_free (ba, TRUE); + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); return; } g_free (result); @@ -496,6 +480,7 @@ imap_append_message (CamelFolder *folder, CamelMimeMessage *message, g_byte_array_append (ba, "\0", 3); response = camel_imap_command_continuation (store, ex, ba->data); g_byte_array_free (ba, TRUE); + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); if (!response) return; camel_imap_response_free (response); @@ -508,8 +493,11 @@ imap_copy_message_to (CamelFolder *source, const char *uid, CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store); CamelImapResponse *response; + CAMEL_IMAP_STORE_LOCK(store, command_lock); response = camel_imap_command (store, source, ex, "UID COPY %s %S", uid, destination->full_name); + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); + camel_imap_response_free (response); } @@ -520,8 +508,10 @@ imap_move_message_to (CamelFolder *source, const char *uid, CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store); CamelImapResponse *response; + CAMEL_IMAP_STORE_LOCK(store, command_lock); response = camel_imap_command (store, source, ex, "UID COPY %s %S", uid, destination->full_name); + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); camel_imap_response_free (response); if (camel_exception_is_set (ex)) @@ -530,27 +520,6 @@ imap_move_message_to (CamelFolder *source, const char *uid, camel_folder_delete_message (source, uid); } -static GPtrArray * -imap_get_uids (CamelFolder *folder) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - const CamelMessageInfo *info; - GPtrArray *array; - int i, count; - - count = camel_folder_summary_count (imap_folder->summary); - - array = g_ptr_array_new (); - g_ptr_array_set_size (array, count); - - for (i = 0; i < count; i++) { - info = camel_folder_summary_index (imap_folder->summary, i); - array->pdata[i] = g_strdup (camel_message_info_uid(info)); - } - - return array; -} - static CamelMimeMessage * imap_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex) { @@ -561,8 +530,11 @@ imap_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex) char *result, *mesg, *p; int len; + CAMEL_IMAP_STORE_LOCK(store, command_lock); response = camel_imap_command (store, folder, ex, "UID FETCH %s BODY.PEEK[]", uid); + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); + if (!response) return NULL; result = camel_imap_response_extract (response, "FETCH", ex); @@ -622,7 +594,7 @@ imap_update_summary (CamelFolder *folder, int first, int last, CamelFolderChangeInfo *changes, CamelException *ex) { CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); + /*CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);*/ CamelImapResponse *response; GPtrArray *headers = NULL; char *q, *summary_specifier; @@ -630,6 +602,7 @@ imap_update_summary (CamelFolder *folder, int first, int last, int i; summary_specifier = imap_protocol_get_summary_specifier (store); + CAMEL_IMAP_STORE_LOCK(store, command_lock); if (first == last) { response = camel_imap_command (store, folder, ex, "FETCH %d (%s)", first, @@ -639,6 +612,7 @@ imap_update_summary (CamelFolder *folder, int first, int last, "FETCH %d:%d (%s)", first, last, summary_specifier); } + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); g_free (summary_specifier); if (!response) @@ -683,9 +657,10 @@ imap_update_summary (CamelFolder *folder, int first, int last, /* We can't just call camel_folder_summary_add_from_parser * because it will assign the wrong UID, and thus get the * uid hash table wrong and all that. FIXME some day. + * Well you can actually now, because you can override next_uid_string(), but + * it hasn't been done yet. */ - info = camel_folder_summary_info_new_from_header ( - imap_folder->summary, h); + info = camel_folder_summary_info_new_from_header(folder->summary, h); iinfo = (CamelImapMessageInfo *)info; header_raw_clear (&h); uid = g_strndup (uid, q - uid); @@ -708,42 +683,33 @@ imap_update_summary (CamelFolder *folder, int first, int last, } else info->size = strtoul (size + 12, NULL, 10); - camel_folder_summary_add (imap_folder->summary, info); + camel_folder_summary_add (folder->summary, info); } camel_imap_response_free (response); } static GPtrArray * -imap_get_summary (CamelFolder *folder) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - - return imap_folder->summary->messages; -} - -/* get a single message info, by uid */ -static const CamelMessageInfo * -imap_get_message_info (CamelFolder *folder, const char *uid) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - - return camel_folder_summary_uid (imap_folder->summary, uid); -} - -static GPtrArray * imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex) { CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); + GPtrArray *matches, *summary; + + /* we could get around this by creating a new search object each time, + but i doubt its worth it since any long operation would lock the + command channel too */ + CAMEL_IMAP_FOLDER_LOCK(folder, search_lock); if (!imap_folder->search) imap_folder->search = camel_imap_search_new (); camel_folder_search_set_folder (imap_folder->search, folder); - camel_folder_search_set_summary ( - imap_folder->search, imap_folder->summary->messages); + summary = camel_folder_get_summary(folder); + camel_folder_search_set_summary(imap_folder->search, summary); + uids = camel_folder_search_execute_expression (imap_folder->search, expression, ex); + + CAMEL_IMAP_FOLDER_UNLOCK(folder, search_lock); - return camel_folder_search_execute_expression (imap_folder->search, - expression, ex); + camel_folder_free_summary(folder, summary); } static void @@ -753,54 +719,11 @@ imap_search_free (CamelFolder *folder, GPtrArray *uids) g_return_if_fail (imap_folder->search); - camel_folder_search_free_result (imap_folder->search, uids); -} + CAMEL_IMAP_FOLDER_LOCK(folder, search_lock); -static guint32 -imap_get_message_flags (CamelFolder *folder, const char *uid) -{ - const CamelMessageInfo *info; - - info = imap_get_message_info (folder, uid); - g_return_val_if_fail (info != NULL, 0); - - return info->flags; -} - -static void -imap_set_message_flags (CamelFolder *folder, const char *uid, guint32 flags, guint32 set) -{ - CamelImapFolder *imap_folder = (CamelImapFolder *)folder; - CamelMessageInfo *info; - guint32 new; - - info = camel_folder_summary_uid (imap_folder->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 (imap_folder->summary); - - camel_object_trigger_event (CAMEL_OBJECT (folder), "message_changed", - (gpointer)uid); -} - -static gboolean -imap_get_message_user_flag (CamelFolder *folder, const char *uid, const char *name) -{ - /* FIXME */ - return FALSE; -} + camel_folder_search_free_result (imap_folder->search, uids); -static void -imap_set_message_user_flag (CamelFolder *folder, const char *uid, const char *name, gboolean value) -{ - /* FIXME */ - camel_object_trigger_event (CAMEL_OBJECT (folder), "message_changed", - (gpointer)uid); + CAMEL_IMAP_FOLDER_UNLOCK(folder, search_lock); } void diff --git a/camel/providers/imap/camel-imap-folder.h b/camel/providers/imap/camel-imap-folder.h index 3183a8816d..cff11255c2 100644 --- a/camel/providers/imap/camel-imap-folder.h +++ b/camel/providers/imap/camel-imap-folder.h @@ -44,6 +44,8 @@ extern "C" { typedef struct { CamelFolder parent_object; + struct _CamelImapFolderPrivate *priv; + CamelFolderSearch *search; CamelFolderSummary *summary; int exists; diff --git a/camel/providers/imap/camel-imap-private.h b/camel/providers/imap/camel-imap-private.h new file mode 100644 index 0000000000..95ec3a5a0b --- /dev/null +++ b/camel/providers/imap/camel-imap-private.h @@ -0,0 +1,74 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * camel-imap-private.h: Private info for imap. + * + * Authors: Michael Zucchi <notzed@helixcode.com> + * + * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#ifndef CAMEL_PRIVATE_H +#define CAMEL_PRIVATE_H 1 + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus }*/ + +/* need a way to configure and save this data, if this header is to + be installed. For now, dont install it */ + +#include "config.h" + +#ifdef ENABLE_THREADS +#include "e-util/e-msgport.h" +#endif + +struct _CamelImapStorePrivate { +#ifdef ENABLE_THREADS + EMutex *command_lock; /* for locking the command stream for a complete operation */ +#endif +}; + +#ifdef ENABLE_THREADS +#define CAMEL_IMAP_STORE_LOCK(f, l) (e_mutex_lock(((CamelImapStore *)f)->priv->l)) +#define CAMEL_IMAP_STORE_UNLOCK(f, l) (e_mutex_unlock(((CamelImapStore *)f)->priv->l)) +#else +#define CAMEL_IMAP_STORE_LOCK(f, l) +#define CAMEL_IMAP_STORE_UNLOCK(f, l) +#endif + +struct _CamelImapFolderPrivate { +#ifdef ENABLE_THREADS + GMutex *search_lock; /* for locking the search object */ +#endif +}; + +#ifdef ENABLE_THREADS +#define CAMEL_IMAP_FOLDER_LOCK(f, l) (g_mutex_lock(((CamelImapFolder *)f)->priv->l)) +#define CAMEL_IMAP_FOLDER_UNLOCK(f, l) (g_mutex_unlock(((CamelImapFolder *)f)->priv->l)) +#else +#define CAMEL_IMAP_FOLDER_LOCK(f, l) +#define CAMEL_IMAP_FOLDER_UNLOCK(f, l) +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CAMEL_H */ + diff --git a/camel/providers/imap/camel-imap-search.c b/camel/providers/imap/camel-imap-search.c index 1aa6b55bc5..cec0ee1f89 100644 --- a/camel/providers/imap/camel-imap-search.c +++ b/camel/providers/imap/camel-imap-search.c @@ -31,6 +31,7 @@ #include "camel-imap-command.h" #include "camel-imap-folder.h" #include "camel-imap-search.h" +#include "camel-imap-private.h" static ESExpResult * imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, @@ -72,10 +73,13 @@ imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (s->folder); char *value = argv[0]->value.string; CamelImapResponse *response; - char *result, *p, *lasts = NULL; + char *result, *p, *lasts = NULL, *real_uid; const char *uid; ESExpResult *r; CamelMessageInfo *info; + GHashTable *uid_hash = NULL; + + CAMEL_IMAP_STORE_LOCK(store, command_lock); if (s->current) { uid = camel_message_info_uid (s->current); @@ -91,6 +95,9 @@ imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, "UID SEARCH BODY \"%s\"", value); } + + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); + if (!response) return r; result = camel_imap_response_extract (response, "SEARCH", NULL); @@ -105,14 +112,27 @@ imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, break; } } else { - /* FIXME: The strings added to the array must be - * static... - */ - info = camel_folder_summary_uid (imap_folder->summary, p); - g_ptr_array_add (r->value.ptrarray, (char *)camel_message_info_uid (info)); + /* if we need to setup a hash of summary items, this way we get + access to the summary memory which is locked for the duration of + the search, and wont vanish on us */ + if (uid_hash == NULL) { + int i; + + uid_hash = g_hash_table_new(g_str_hash, g_str_equal); + for (i=0;i<s->summary->len;i++) { + info = s->summary->pdata[i]; + g_hash_table_insert(uid_hash, camel_message_info_uid(info), info); + } + } + if (g_hash_table_lookup_extended(uid_hash, p, &real_uid, &info)) + g_ptr_array_add (r->value.ptrarray, real_uid); } } + /* we could probably cache this globally, but its probably not worth it */ + if (uid_hash) + g_hash_table_destroy(uid_hash); + return r; } diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c index e3bd61af27..8774d783bd 100644 --- a/camel/providers/imap/camel-imap-store.c +++ b/camel/providers/imap/camel-imap-store.c @@ -47,6 +47,8 @@ #include "camel-url.h" #include "string-utils.h" +#include "camel-imap-private.h" + #define d(x) x /* Specified in RFC 2060 */ @@ -121,6 +123,10 @@ camel_imap_store_finalize (CamelObject *object) g_hash_table_foreach_remove (imap_store->subscribed_folders, free_sub, NULL); g_hash_table_destroy (imap_store->subscribed_folders); +#ifdef ENABLE_THREADS + e_mutex_destroy(imap_store->priv->command_lock); +#endif + g_free(imap_store->priv); } static void @@ -139,6 +145,11 @@ camel_imap_store_init (gpointer object, gpointer klass) imap_store->connected = FALSE; imap_store->subscribed_folders = g_hash_table_new (g_str_hash, g_str_equal); + + imap_store->priv = g_malloc0(sizeof(*imap_store->priv)); +#ifdef ENABLE_THREADS + imap_store->priv->command_lock = e_mutex_new(E_MUTEX_REC); +#endif } CamelType @@ -175,6 +186,7 @@ static struct { { NULL, 0 } }; +/* we have remote-store:connect_lock by now */ static gboolean connect_to_server (CamelService *service, CamelException *ex) { @@ -351,10 +363,12 @@ imap_connect (CamelService *service, CamelException *ex) } } + CAMEL_IMAP_STORE_LOCK(store, command_lock); response = camel_imap_command (store, NULL, ex, "LOGIN %S %S", service->url->user, service->url->passwd); + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); if (!response) { errbuf = g_strdup_printf (_("Unable to authenticate " "to IMAP server.\n%s\n\n"), @@ -380,6 +394,8 @@ imap_connect (CamelService *service, CamelException *ex) namespace++; else namespace = ""; + + CAMEL_IMAP_STORE_LOCK(store, command_lock); if (store->server_level >= IMAP_LEVEL_IMAP4REV1) { /* This idiom means "tell me the hierarchy separator * for the given path, even if that path doesn't exist. @@ -396,6 +412,8 @@ imap_connect (CamelService *service, CamelException *ex) "LIST \"\" %S", namespace); } + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); + if (!response) return FALSE; @@ -431,7 +449,11 @@ imap_disconnect (CamelService *service, gboolean clean, CamelException *ex) if (store->connected && clean) { /* send the logout command */ + + /* NB: this lock probably isn't required */ + CAMEL_IMAP_STORE_LOCK(store, command_lock); response = camel_imap_command (store, NULL, ex, "LOGOUT"); + CAMEL_IMAP_STORE_UNLOCK(store, command_lock); camel_imap_response_free (response); } @@ -440,6 +462,7 @@ imap_disconnect (CamelService *service, gboolean clean, CamelException *ex) return CAMEL_SERVICE_CLASS (remote_store_class)->disconnect (service, clean, ex); } +/* NOTE: Must have imap_store::command_lock before calling this */ static gboolean imap_folder_exists (CamelImapStore *store, const char *folder_name, gboolean *selectable, char **short_name, @@ -481,6 +504,7 @@ imap_folder_exists (CamelImapStore *store, const char *folder_name, return TRUE; } +/* NOTE: Must have imap_store::command_lock before calling this */ static gboolean imap_create (CamelImapStore *store, const char *folder_name, CamelException *ex) @@ -503,18 +527,19 @@ get_folder (CamelStore *store, const char *folder_name, guint32 flags, char *short_name, *summary_file, *p; gboolean selectable; + /* lock around the whole lot to check/create atomically */ + CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); if (!imap_folder_exists (imap_store, folder_name, &selectable, &short_name, ex)) { - if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0) - return NULL; - - if (!imap_create (imap_store, folder_name, ex)) - return NULL; - - if (!imap_folder_exists (imap_store, folder_name, - &selectable, &short_name, ex)) + if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0 + || (!imap_create (imap_store, folder_name, ex)) + || (!imap_folder_exists (imap_store, folder_name, + &selectable, &short_name, ex))) { + CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); return NULL; + } } + CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); if (!selectable) { camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, @@ -621,8 +646,10 @@ get_folder_info (CamelStore *store, const char *top, gboolean fast, else name = ""; } + CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); response = camel_imap_command (imap_store, NULL, ex, "LIST \"\" %S", name); + CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); if (!response) return FALSE; list = camel_imap_response_extract (response, "LIST", ex); @@ -642,10 +669,13 @@ get_folder_info (CamelStore *store, const char *top, gboolean fast, else pattern = g_strdup_printf ("%s%c", name, recursive ? '*' : '%'); + CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); response = camel_imap_command (imap_store, NULL, ex, "%s \"\" %S", subscribed_only ? "LSUB" : "LIST", pattern); + CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); + g_free (pattern); if (!response) return NULL; @@ -694,10 +724,12 @@ get_folder_info (CamelStore *store, const char *top, gboolean fast, if (!fi->url) continue; + CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); response = camel_imap_command ( imap_store, NULL, NULL, "STATUS %S (MESSAGES UNSEEN)", fi->full_name); + CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); if (!response) continue; status = camel_imap_response_extract ( @@ -757,6 +789,7 @@ subscribe_folder (CamelStore *store, const char *folder_name, CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); CamelImapResponse *response; + CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); response = camel_imap_command (imap_store, NULL, ex, "SUBSCRIBE %S", folder_name); if (response) { @@ -774,9 +807,11 @@ unsubscribe_folder (CamelStore *store, const char *folder_name, CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); CamelImapResponse *response; gpointer key, value; - + + CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); response = camel_imap_command (imap_store, NULL, ex, "UNSUBSCRIBE %S", folder_name); + CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); if (response) { g_hash_table_lookup_extended (imap_store->subscribed_folders, folder_name, &key, &value); @@ -793,6 +828,8 @@ imap_keepalive (CamelRemoteStore *store) CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); CamelImapResponse *response; + CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); response = camel_imap_command (imap_store, NULL, NULL, "NOOP"); + CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); camel_imap_response_free (response); } diff --git a/camel/providers/imap/camel-imap-store.h b/camel/providers/imap/camel-imap-store.h index 025e28256a..cd93d8eddf 100644 --- a/camel/providers/imap/camel-imap-store.h +++ b/camel/providers/imap/camel-imap-store.h @@ -56,7 +56,8 @@ typedef enum { typedef struct { CamelRemoteStore parent_object; - + struct _CamelImapStorePrivate *priv; + CamelFolder *current_folder; guint32 command; diff --git a/camel/providers/local/Makefile.am b/camel/providers/local/Makefile.am index 1f250b04cd..2e95021334 100644 --- a/camel/providers/local/Makefile.am +++ b/camel/providers/local/Makefile.am @@ -47,6 +47,9 @@ libcamellocalinclude_HEADERS = \ camel-maildir-store.h \ camel-maildir-summary.h +noinst_HEADERS = \ + camel-local-private.h + libcamellocal_la_LDFLAGS = -version-info 0:0:0 libcamellocal_la_LIBADD = $(top_builddir)/e-util/libeutil.la $(top_builddir)/libibex/libibex.la $(UNICODE_LIBS) 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); } - - diff --git a/camel/providers/local/camel-local-folder.h b/camel/providers/local/camel-local-folder.h index 4fa65420d4..7c975c8f7a 100644 --- a/camel/providers/local/camel-local-folder.h +++ b/camel/providers/local/camel-local-folder.h @@ -43,6 +43,7 @@ extern "C" { typedef struct { CamelFolder parent_object; + struct _CamelLocalFolderPrivate *priv; guint32 flags; /* open mode flags */ @@ -55,7 +56,6 @@ typedef struct { char *index_path; /* where the index file lives */ ibex *index; /* index for this folder */ - CamelLocalSummary *summary; CamelFolderSearch *search; /* used to run searches, we just use the real thing (tm) */ CamelFolderChangeInfo *changes; /* used to store changes to the folder during processing */ } CamelLocalFolder; diff --git a/camel/providers/local/camel-local-private.h b/camel/providers/local/camel-local-private.h new file mode 100644 index 0000000000..1d1a89ea27 --- /dev/null +++ b/camel/providers/local/camel-local-private.h @@ -0,0 +1,60 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * camel-local-private.h: Private info for local provider. + * + * Authors: Michael Zucchi <notzed@helixcode.com> + * + * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#ifndef CAMEL_PRIVATE_H +#define CAMEL_PRIVATE_H 1 + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus }*/ + +/* need a way to configure and save this data, if this header is to + be installed. For now, dont install it */ + +#include "config.h" + +#ifdef ENABLE_THREADS +#include <pthread.h> +#endif + +struct _CamelLocalFolderPrivate { +#ifdef ENABLE_THREADS + GMutex *search_lock; /* for locking the search object */ +#endif +}; + +#ifdef ENABLE_THREADS +#define CAMEL_LOCAL_FOLDER_LOCK(f, l) (g_mutex_lock(((CamelLocalFolder *)f)->priv->l)) +#define CAMEL_LOCAL_FOLDER_UNLOCK(f, l) (g_mutex_unlock(((CamelLocalFolder *)f)->priv->l)) +#else +#define CAMEL_LOCAL_FOLDER_LOCK(f, l) +#define CAMEL_LOCAL_FOLDER_UNLOCK(f, l) +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CAMEL_H */ + diff --git a/camel/providers/local/camel-local-summary.c b/camel/providers/local/camel-local-summary.c index 1377ff43a8..869b7c712a 100644 --- a/camel/providers/local/camel-local-summary.c +++ b/camel/providers/local/camel-local-summary.c @@ -42,19 +42,7 @@ struct _CamelLocalSummaryPrivate { #define _PRIVATE(o) (((CamelLocalSummary *)(o))->priv) -#if 0 -static int summary_header_load (CamelFolderSummary *, FILE *); -static int summary_header_save (CamelFolderSummary *, FILE *); -#endif - static CamelMessageInfo * message_info_new (CamelFolderSummary *, struct _header_raw *); -static CamelMessageInfo * message_info_new_from_parser (CamelFolderSummary *, CamelMimeParser *); -static CamelMessageInfo * message_info_new_from_message(CamelFolderSummary *s, CamelMimeMessage *msg); -#if 0 -static CamelMessageInfo * message_info_load (CamelFolderSummary *, FILE *); -static int message_info_save (CamelFolderSummary *, FILE *, CamelMessageInfo *); -#endif -/*static void message_info_free (CamelFolderSummary *, CamelMessageInfo *);*/ static int local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *mi); static char *local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelMessageInfo *mi); @@ -67,7 +55,6 @@ static CamelMessageInfo *local_summary_add(CamelLocalSummary *cls, CamelMimeMess static void camel_local_summary_class_init (CamelLocalSummaryClass *klass); static void camel_local_summary_init (CamelLocalSummary *obj); static void camel_local_summary_finalise (CamelObject *obj); - static CamelFolderSummaryClass *camel_local_summary_parent; CamelType @@ -95,16 +82,7 @@ camel_local_summary_class_init(CamelLocalSummaryClass *klass) camel_local_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_type_get_global_classfuncs(camel_folder_summary_get_type())); - /*sklass->summary_header_load = summary_header_load; - sklass->summary_header_save = summary_header_save;*/ - sklass->message_info_new = message_info_new; - sklass->message_info_new_from_parser = message_info_new_from_parser; - sklass->message_info_new_from_message = message_info_new_from_message; - - /*sklass->message_info_load = message_info_load; - sklass->message_info_save = message_info_save;*/ - /*sklass->message_info_free = message_info_free;*/ klass->load = local_summary_load; klass->check = local_summary_check; @@ -288,6 +266,7 @@ camel_local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changei for (i=0;i<camel_folder_summary_count(s);i++) { CamelMessageInfo *info = camel_folder_summary_index(s, i); do_stat_mi(cls, &stats, info); + camel_folder_summary_info_free(s, info); } printf("\nMemory used by summary:\n\n"); @@ -372,57 +351,10 @@ camel_local_summary_write_headers(int fd, struct _header_raw *header, char *xevl return outlen; } -#if 0 -static int -summary_header_load(CamelFolderSummary *s, FILE *in) -{ - CamelLocalSummary *mbs = CAMEL_LOCAL_SUMMARY(s); - - if (((CamelFolderSummaryClass *)camel_local_summary_parent)->summary_header_load(s, in) == -1) - return -1; - - return camel_folder_summary_decode_uint32(in, &mbs->folder_size); -} - -static int -summary_header_save(CamelFolderSummary *s, FILE *out) -{ - CamelLocalSummary *mbs = CAMEL_LOCAL_SUMMARY(s); - - if (((CamelFolderSummaryClass *)camel_local_summary_parent)->summary_header_save(s, out) == -1) - return -1; - - return camel_folder_summary_encode_uint32(out, mbs->folder_size); -} - -static int -header_evolution_decode(const char *in, guint32 *uid, guint32 *flags) -{ - char *header; - - if (in && (header = header_token_decode(in))) { - if (strlen (header) == strlen ("00000000-0000") - && sscanf (header, "%08x-%04x", uid, flags) == 2) { - g_free(header); - return *uid; - } - g_free(header); - } - - return -1; -} - -static char * -header_evolution_encode(guint32 uid, guint32 flags) -{ - return g_strdup_printf("%08x-%04x", uid, flags & 0xffff); -} -#endif - static int local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex) { - /* FIXME: sync index here */ + /* FIXME: sync index here ? */ return 0; } @@ -623,90 +555,3 @@ message_info_new(CamelFolderSummary *s, struct _header_raw *h) return mi; } - -static CamelMessageInfo * message_info_new_from_message(CamelFolderSummary *s, CamelMimeMessage *msg) -{ - CamelMessageInfo *mi; - /*CamelLocalSummary *cls = (CamelLocalSummary *)s;*/ - - mi = ((CamelFolderSummaryClass *)camel_local_summary_parent)->message_info_new_from_message(s, msg); -#if 0 - if (mi) { - - if (mi->uid == NULL) { - d(printf("no uid assigned yet, assigning one\n")); - mi->uid = camel_folder_summary_next_uid_string(s); - mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV; - } - - if (cls->index - && (cls->index_force - || !ibex_contains_name(cls->index, mi->uid))) { - d(printf("Am indexing message %s\n", mi->uid)); - camel_folder_summary_set_index(s, cls->index); - } else { - d(printf("Not indexing message %s\n", mi->uid)); - camel_folder_summary_set_index(s, NULL); - } - } -#endif - return mi; -} - -static CamelMessageInfo * -message_info_new_from_parser(CamelFolderSummary *s, CamelMimeParser *mp) -{ - CamelMessageInfo *mi; - /*CamelLocalSummary *mbs = CAMEL_LOCAL_SUMMARY(s);*/ - - mi = ((CamelFolderSummaryClass *)camel_local_summary_parent)->message_info_new_from_parser(s, mp); - if (mi) { -#if 0 - /* do we want to index this message as we add it, as well? */ - if (mbs->index - && (mbs->index_force - || !ibex_contains_name(mbs->index, mi->uid))) { - d(printf("Am indexing message %s\n", mi->uid)); - camel_folder_summary_set_index(s, mbs->index); - } else { - d(printf("Not indexing message %s\n", mi->uid)); - camel_folder_summary_set_index(s, NULL); - } -#endif - } - - return mi; -} - -#if 0 -static CamelMessageInfo * -message_info_load(CamelFolderSummary *s, FILE *in) -{ - CamelMessageInfo *mi; - - io(printf("loading local message info\n")); - - mi = ((CamelFolderSummaryClass *)camel_local_summary_parent)->message_info_load(s, in); - if (mi) { - guint32 position; - CamelLocalMessageInfo *mbi = (CamelLocalMessageInfo *)mi; - - camel_folder_summary_decode_uint32(in, &position); - mbi->frompos = position; - } - - return mi; -} - -static int -message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *mi) -{ - CamelLocalMessageInfo *mbi = (CamelLocalMessageInfo *)mi; - - io(printf("saving local message info\n")); - - ((CamelFolderSummaryClass *)camel_local_summary_parent)->message_info_save(s, out, mi); - - return camel_folder_summary_encode_uint32(out, mbi->frompos); -} -#endif diff --git a/camel/providers/local/camel-maildir-folder.c b/camel/providers/local/camel-maildir-folder.c index d4771db5b8..c4d347d083 100644 --- a/camel/providers/local/camel-maildir-folder.c +++ b/camel/providers/local/camel-maildir-folder.c @@ -131,7 +131,7 @@ static void maildir_append_message(CamelFolder * folder, CamelMimeMessage * mess d(printf("Appending message\n")); /* add it to the summary/assign the uid, etc */ - mi = camel_local_summary_add(lf->summary, message, info, lf->changes, ex); + mi = camel_local_summary_add((CamelLocalSummary *)folder->summary, message, info, lf->changes, ex); if (camel_exception_is_set(ex)) { return; } @@ -191,7 +191,7 @@ static CamelMimeMessage *maildir_get_message(CamelFolder * folder, const gchar * d(printf("getting message: %s\n", uid)); /* get the message summary info */ - if ((info = camel_folder_summary_uid((CamelFolderSummary *)lf->summary, uid)) == NULL) { + if ((info = camel_folder_summary_uid(folder->summary, uid)) == NULL) { camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message: %s\n %s"), uid, _("No such message")); return NULL; } @@ -200,6 +200,9 @@ static CamelMimeMessage *maildir_get_message(CamelFolder * folder, const gchar * /* what do we do if the message flags (and :info data) changes? filename mismatch - need to recheck I guess */ name = g_strdup_printf("%s/cur/%s", lf->folder_path, camel_maildir_info_filename(mdi)); + + camel_folder_summary_info_free(folder->summary, info); + if ((message_stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0)) == NULL) { camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message: %s\n %s"), name, g_strerror(errno)); diff --git a/camel/providers/local/camel-maildir-summary.c b/camel/providers/local/camel-maildir-summary.c index 8d421d5fdd..a65adafc0f 100644 --- a/camel/providers/local/camel-maildir-summary.c +++ b/camel/providers/local/camel-maildir-summary.c @@ -33,6 +33,7 @@ #include <ctype.h> +#include "camel-private.h" #include "e-util/e-memory.h" #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ @@ -474,6 +475,7 @@ remove_summary(char *key, CamelMessageInfo *info, CamelLocalSummary *cls) if (cls->index) ibex_unindex(cls->index, (char *)camel_message_info_uid(info)); camel_folder_summary_remove((CamelFolderSummary *)cls, info); + camel_folder_summary_info_free((CamelFolderSummary *)cls, info); } static int @@ -551,33 +553,47 @@ maildir_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changes, Ca if (info == NULL || (cls->index && (!ibex_contains_name(cls->index, uid)))) { /* need to add this file to the summary */ if (info != NULL) { - g_hash_table_remove(left, uid); + CamelMessageInfo *old = g_hash_table_lookup(left, camel_message_info_uid(info)); + if (old) { + g_hash_table_remove(left, uid); + camel_folder_summary_info_free((CamelFolderSummary *)cls, old); + } camel_folder_summary_remove((CamelFolderSummary *)cls, info); + camel_folder_summary_info_free((CamelFolderSummary *)cls, info); } camel_maildir_summary_add(cls, d->d_name, forceindex); } else { const char *filename; + CamelMessageInfo *old; - g_hash_table_remove(left, camel_message_info_uid(info)); + old = g_hash_table_lookup(left, camel_message_info_uid(info)); + if (old) { + camel_folder_summary_info_free((CamelFolderSummary *)cls, old); + g_hash_table_remove(left, camel_message_info_uid(info)); + } mdi = (CamelMaildirMessageInfo *)info; filename = camel_maildir_info_filename(mdi); /* TODO: only store the extension in the mdi->filename struct, not the whole lot */ if (filename == NULL || strcmp(filename, d->d_name) != 0) { #ifdef DOESTRV +#warning "cannot modify the estrv after its been setup, for mt-safe code" d(printf("filename changed: %s to %s\n", filename, d->d_name)); /* need to update the summary hash string reference since it might (will) change */ + CAMEL_SUMMARY_LOCK(s, summary_lock); g_hash_table_remove(s->messages_uid, uid); info->strings = e_strv_set_ref(info->strings, CAMEL_MAILDIR_INFO_FILENAME, d->d_name); /* we need to re-pack as well */ info->strings = e_strv_pack(info->strings); g_hash_table_insert(s->messages_uid, (char *)camel_message_info_uid(info), info); + CAMEL_SUMMARY_UNLOCK(s, summary_lock); #else g_free(mdi->filename); mdi->filename = g_strdup(d->d_name); #endif } + camel_folder_summary_info_free((CamelFolderSummary *)cls, info); } g_free(uid); } @@ -597,9 +613,10 @@ maildir_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changes, Ca continue; /* already in summary? shouldn't happen, but just incase ... */ - if (camel_folder_summary_uid((CamelFolderSummary *)cls, name)) + if ((info = camel_folder_summary_uid((CamelFolderSummary *)cls, name))) { + camel_folder_summary_info_free((CamelFolderSummary *)cls, info); newname = destname = camel_folder_summary_next_uid_string(s); - else { + } else { newname = NULL; destname = name; } @@ -633,7 +650,9 @@ maildir_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changes, Ca g_free(cur); /* sort the summary based on receive time, since the directory order is not useful */ + CAMEL_SUMMARY_LOCK(s, summary_lock); qsort(s->messages->pdata, s->messages->len, sizeof(CamelMessageInfo *), sort_receive_cmp); + CAMEL_SUMMARY_UNLOCK(s, summary_lock); /* FIXME: move this up a class? */ @@ -699,12 +718,18 @@ maildir_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChange /* we'll assume it didn't work, but dont change anything else */ g_free(newname); } else { + /* TODO: If this is made mt-safe, then this code could be a problem, since + the estrv is being modified. + Sigh, this may mean the maildir name has to be cached another way */ #ifdef DOESTRV +#warning "cannot modify the estrv after its been setup, for mt-safe code" + CAMEL_SUMMARY_LOCK(s, summary_lock); /* need to update the summary hash ref */ g_hash_table_remove(s->messages_uid, camel_message_info_uid(info)); info->strings = e_strv_set_ref_free(info->strings, CAMEL_MAILDIR_INFO_FILENAME, newname); info->strings = e_strv_pack(info->strings); g_hash_table_insert(s->messages_uid, (char *)camel_message_info_uid(info), info); + CAMEL_SUMMARY_UNLOCK(s, summary_lock); #else g_free(mdi->filename); mdi->filename = newname; @@ -719,6 +744,7 @@ maildir_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChange /* strip FOLDER_MESSAGE_FLAGED, etc */ info->flags &= 0xffff; } + camel_folder_summary_info_free((CamelFolderSummary *)cls, info); } return 0; } diff --git a/camel/providers/local/camel-mbox-folder.c b/camel/providers/local/camel-mbox-folder.c index 41fb5865b5..14dca0049e 100644 --- a/camel/providers/local/camel-mbox-folder.c +++ b/camel/providers/local/camel-mbox-folder.c @@ -54,6 +54,9 @@ static CamelLocalFolderClass *parent_class = NULL; static int mbox_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex); static void mbox_unlock(CamelLocalFolder *lf); +static void mbox_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value); +static void mbox_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value); + static void mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const CamelMessageInfo * info, CamelException *ex); static CamelMimeMessage *mbox_get_message(CamelFolder *folder, const gchar * uid, CamelException *ex); static CamelLocalSummary *mbox_create_summary(const char *path, const char *folder, ibex *index); @@ -74,6 +77,9 @@ camel_mbox_folder_class_init(CamelMboxFolderClass * camel_mbox_folder_class) camel_folder_class->append_message = mbox_append_message; camel_folder_class->get_message = mbox_get_message; + camel_folder_class->set_message_user_flag = mbox_set_message_user_flag; + camel_folder_class->set_message_user_tag = mbox_set_message_user_tag; + lclass->create_summary = mbox_create_summary; lclass->lock = mbox_lock; lclass->unlock = mbox_unlock; @@ -164,7 +170,7 @@ mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const Camel CamelLocalFolder *lf = (CamelLocalFolder *)folder; CamelStream *output_stream = NULL, *filter_stream = NULL; CamelMimeFilter *filter_from = NULL; - CamelMboxSummary *mbs = (CamelMboxSummary *)lf->summary; + CamelMboxSummary *mbs = (CamelMboxSummary *)folder->summary; CamelMessageInfo *mi; char *fromline = NULL; int fd; @@ -179,12 +185,12 @@ mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const Camel d(printf("Appending message\n")); /* first, check the summary is correct (updates folder_size too) */ - camel_local_summary_check(lf->summary, lf->changes, ex); + camel_local_summary_check((CamelLocalSummary *)folder->summary, lf->changes, ex); if (camel_exception_is_set(ex)) goto fail; /* add it to the summary/assign the uid, etc */ - mi = camel_local_summary_add(lf->summary, message, info, lf->changes, ex); + mi = camel_local_summary_add((CamelLocalSummary *)folder->summary, message, info, lf->changes, ex); if (camel_exception_is_set(ex)) goto fail; @@ -199,7 +205,7 @@ mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const Camel /* and we need to set the frompos/XEV explicitly */ ((CamelMboxMessageInfo *)mi)->frompos = mbs->folder_size?mbs->folder_size+1:0; #if 0 - xev = camel_local_summary_encode_x_evolution(lf->summary, mi); + xev = camel_local_summary_encode_x_evolution((CamelLocalSummary *)folder->summary, mi); if (xev) { /* the x-ev header should match the 'current' flags, no problem, so store as much */ camel_medium_set_header((CamelMedium *)message, "X-Evolution", xev); @@ -304,7 +310,7 @@ mbox_get_message(CamelFolder *folder, const gchar * uid, CamelException *ex) retry: /* get the message summary info */ - info = (CamelMboxMessageInfo *) camel_folder_summary_uid((CamelFolderSummary *)lf->summary, uid); + info = (CamelMboxMessageInfo *) camel_folder_summary_uid(folder->summary, uid); if (info == NULL) { camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, @@ -327,6 +333,7 @@ retry: _("Cannot get message: %s from folder %s\n %s"), uid, lf->folder_path, strerror(errno)); camel_local_folder_unlock(lf); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)info); return NULL; } @@ -345,10 +352,11 @@ retry: camel_mime_parser_state(parser)); camel_object_unref((CamelObject *)parser); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)info); if (!retried) { retried = TRUE; - camel_local_summary_check(lf->summary, lf->changes, ex); + camel_local_summary_check((CamelLocalSummary *)folder->summary, lf->changes, ex); if (!camel_exception_is_set(ex)) goto retry; } @@ -360,6 +368,8 @@ retry: camel_local_folder_unlock(lf); return NULL; } + + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)info); message = camel_mime_message_new(); if (camel_mime_part_construct_from_parser((CamelMimePart *)message, parser) == -1) { @@ -386,3 +396,39 @@ retry: return message; } + +static void +mbox_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value) +{ + CamelMessageInfo *info; + + g_return_if_fail(folder->summary != NULL); + + info = camel_folder_summary_uid(folder->summary, uid); + g_return_if_fail(info != NULL); + + if (camel_flag_set(&info->user_flags, name, value)) { + info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED|CAMEL_MESSAGE_FOLDER_XEVCHANGE; + camel_folder_summary_touch(folder->summary); + camel_object_trigger_event(CAMEL_OBJECT(folder), "message_changed", (char *) uid); + } + camel_folder_summary_info_free(folder->summary, info); +} + +static void +mbox_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value) +{ + CamelMessageInfo *info; + + g_return_if_fail(folder->summary != NULL); + + info = camel_folder_summary_uid(folder->summary, uid); + g_return_if_fail(info != NULL); + + if (camel_tag_set(&info->user_tags, name, value)) { + info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED|CAMEL_MESSAGE_FOLDER_XEVCHANGE; + camel_folder_summary_touch(folder->summary); + camel_object_trigger_event(CAMEL_OBJECT(folder), "message_changed", (char *) uid); + } + camel_folder_summary_info_free(folder->summary, info); +} diff --git a/camel/providers/local/camel-mbox-summary.c b/camel/providers/local/camel-mbox-summary.c index 2dde67b70c..5b62743857 100644 --- a/camel/providers/local/camel-mbox-summary.c +++ b/camel/providers/local/camel-mbox-summary.c @@ -306,6 +306,7 @@ summary_update(CamelLocalSummary *cls, off_t offset, CamelFolderChangeInfo *chan CamelMessageInfo *mi = camel_folder_summary_index(s, i); camel_folder_change_info_add_source(changeinfo, camel_message_info_uid(mi)); + camel_folder_summary_info_free(s, mi); } } @@ -318,6 +319,7 @@ summary_update(CamelLocalSummary *cls, off_t offset, CamelFolderChangeInfo *chan for (i = 0; i < count; i++) { CamelMessageInfo *mi = camel_folder_summary_index(s, i); camel_folder_change_info_add_update(changeinfo, camel_message_info_uid(mi)); + camel_folder_summary_info_free(s, mi); } camel_folder_change_info_build_diff(changeinfo); } @@ -459,7 +461,7 @@ mbox_summary_sync_full(CamelLocalSummary *cls, gboolean expunge, CamelFolderChan CamelFolderSummary *s = (CamelFolderSummary *)mbs; CamelMimeParser *mp = NULL; int i, count; - CamelMboxMessageInfo *info; + CamelMboxMessageInfo *info = NULL; int fd = -1, fdout = -1; char *tmpname = NULL; char *buffer, *xevnew = NULL; @@ -533,6 +535,7 @@ mbox_summary_sync_full(CamelLocalSummary *cls, gboolean expunge, CamelFolderChan /* remove it from the change list */ camel_folder_change_info_remove_uid(changeinfo, uid); camel_folder_summary_remove(s, (CamelMessageInfo *)info); + camel_folder_summary_info_free(s, (CamelMessageInfo *)info); count--; i--; info = NULL; @@ -584,6 +587,8 @@ mbox_summary_sync_full(CamelLocalSummary *cls, gboolean expunge, CamelFolderChan d(printf("we are now at %d, from = %d\n", (int)camel_mime_parser_tell(mp), (int)camel_mime_parser_tell_start_from(mp))); camel_mime_parser_unstep(mp); + camel_folder_summary_info_free(s, (CamelMessageInfo *)info); + info = NULL; } } @@ -634,6 +639,8 @@ mbox_summary_sync_full(CamelLocalSummary *cls, gboolean expunge, CamelFolderChan unlink(tmpname); if (mp) camel_object_unref((CamelObject *)mp); + if (info) + camel_folder_summary_info_free(s, (CamelMessageInfo *)info); return -1; } @@ -646,7 +653,7 @@ mbox_summary_sync_quick(CamelLocalSummary *cls, gboolean expunge, CamelFolderCha CamelFolderSummary *s = (CamelFolderSummary *)mbs; CamelMimeParser *mp = NULL; int i, count; - CamelMboxMessageInfo *info; + CamelMboxMessageInfo *info = NULL; int fd = -1; char *xevnew, *xevtmp; const char *xev; @@ -678,8 +685,11 @@ mbox_summary_sync_quick(CamelLocalSummary *cls, gboolean expunge, CamelFolderCha d(printf("Checking message %s %08x\n", info->info.uid, info->info.flags)); - if ((info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) == 0) + if ((info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) == 0) { + camel_folder_summary_info_free(s, (CamelMessageInfo *)info); + info = NULL; continue; + } d(printf("Updating message %s\n", info->info.uid)); @@ -738,6 +748,7 @@ mbox_summary_sync_quick(CamelLocalSummary *cls, gboolean expunge, CamelFolderCha camel_mime_parser_drop_step(mp); info->info.flags &= 0xffff; + camel_folder_summary_info_free(s, (CamelMessageInfo *)info); } d(printf("Closing folders\n")); @@ -757,9 +768,10 @@ mbox_summary_sync_quick(CamelLocalSummary *cls, gboolean expunge, CamelFolderCha error: if (fd != -1) close(fd); - if (mp) camel_object_unref((CamelObject *)mp); + if (info) + camel_folder_summary_info_free(s, (CamelMessageInfo *)info); return -1; } @@ -792,6 +804,7 @@ mbox_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInf quick = FALSE; else work |= (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0; + camel_folder_summary_info_free(s, info); } /* yuck i hate this logic, but its to simplify the 'all ok, update summary' and failover cases */ diff --git a/camel/providers/local/camel-mh-folder.c b/camel/providers/local/camel-mh-folder.c index 063e7e939e..fec620edea 100644 --- a/camel/providers/local/camel-mh-folder.c +++ b/camel/providers/local/camel-mh-folder.c @@ -132,7 +132,7 @@ static void mh_append_message(CamelFolder * folder, CamelMimeMessage * message, d(printf("Appending message\n")); /* add it to the summary/assign the uid, etc */ - mi = camel_local_summary_add(lf->summary, message, info, lf->changes, ex); + mi = camel_local_summary_add((CamelLocalSummary *)folder->summary, message, info, lf->changes, ex); if (camel_exception_is_set(ex)) { return; } @@ -179,11 +179,14 @@ static CamelMimeMessage *mh_get_message(CamelFolder * folder, const gchar * uid, d(printf("getting message: %s\n", uid)); /* get the message summary info */ - if ((info = camel_folder_summary_uid((CamelFolderSummary *)lf->summary, uid)) == NULL) { + if ((info = camel_folder_summary_uid(folder->summary, uid)) == NULL) { camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message: %s\n %s"), uid, _("No such message")); return NULL; } + /* we only need it to check the message exists */ + camel_folder_summary_info_free(folder->summary, info); + name = g_strdup_printf("%s/%s", lf->folder_path, uid); if ((message_stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0)) == NULL) { camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message: %s\n %s"), diff --git a/camel/providers/local/camel-mh-summary.c b/camel/providers/local/camel-mh-summary.c index e5f37d879a..c933626653 100644 --- a/camel/providers/local/camel-mh-summary.c +++ b/camel/providers/local/camel-mh-summary.c @@ -37,8 +37,6 @@ #define CAMEL_MH_SUMMARY_VERSION (0x2000) -static CamelMessageInfo *message_info_new(CamelFolderSummary *, struct _header_raw *); - static int mh_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); static int mh_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); /*static int mh_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex);*/ @@ -84,7 +82,6 @@ camel_mh_summary_class_init (CamelMhSummaryClass *class) parent_class = (CamelLocalSummaryClass *)camel_type_get_global_classfuncs(camel_local_summary_get_type ()); /* override methods */ - sklass->message_info_new = message_info_new; sklass->next_uid_string = mh_summary_next_uid_string; lklass->check = mh_summary_check; @@ -125,20 +122,6 @@ CamelMhSummary *camel_mh_summary_new (const char *filename, const char *mhdir, i return o; } -static CamelMessageInfo *message_info_new(CamelFolderSummary * s, struct _header_raw *h) -{ - CamelMessageInfo *mi; - /*CamelMhSummary *mhs = (CamelMhSummary *)s;*/ - - mi = ((CamelFolderSummaryClass *) parent_class)->message_info_new(s, h); - /* hmm, this isn't quite right */ - if (mi) { - /*mi->uid = mh_summary_next_uid_string(s);*/ - } - - return mi; -} - static char *mh_summary_next_uid_string(CamelFolderSummary *s) { CamelMhSummary *mhs = (CamelMhSummary *)s; @@ -206,6 +189,7 @@ remove_summary(char *key, CamelMessageInfo *info, CamelLocalSummary *cls) if (cls->index) ibex_unindex(cls->index, (char *)camel_message_info_uid(info)); camel_folder_summary_remove((CamelFolderSummary *)cls, info); + camel_folder_summary_info_free((CamelFolderSummary *)cls, info); } static int @@ -256,11 +240,19 @@ mh_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, Came if (info != NULL) { g_hash_table_remove(left, camel_message_info_uid(info)); camel_folder_summary_remove((CamelFolderSummary *)cls, info); + camel_folder_summary_info_free((CamelFolderSummary *)cls, info); } camel_mh_summary_add(cls, d->d_name, forceindex); } else { - g_hash_table_remove(left, camel_message_info_uid(info)); - } + const char *uid = camel_message_info_uid(info); + CamelMessageInfo *old = g_hash_table_lookup(left, uid); + + if (old) { + camel_folder_summary_info_free((CamelFolderSummary *)cls, old); + g_hash_table_remove(left, uid); + } + camel_folder_summary_info_free((CamelFolderSummary *)cls, info); + } } } closedir(dir); @@ -394,6 +386,7 @@ mh_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo g_warning("Problem occured when trying to expunge, ignored"); } } + camel_folder_summary_info_free((CamelFolderSummary *)cls, info); } return 0; diff --git a/camel/providers/nntp/camel-nntp-folder.c b/camel/providers/nntp/camel-nntp-folder.c index f918317502..7edc4a98fd 100644 --- a/camel/providers/nntp/camel-nntp-folder.c +++ b/camel/providers/nntp/camel-nntp-folder.c @@ -63,7 +63,7 @@ nntp_folder_sync (CamelFolder *folder, gboolean expunge, { CamelNNTPStore *store; - camel_folder_summary_save (CAMEL_NNTP_FOLDER(folder)->summary); + camel_folder_summary_save (folder->summary); store = CAMEL_NNTP_STORE (camel_folder_get_parent_store (folder)); @@ -71,39 +71,12 @@ nntp_folder_sync (CamelFolder *folder, gboolean expunge, camel_nntp_newsrc_write (store->newsrc); } -static gint -nntp_folder_get_message_count (CamelFolder *folder) -{ - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER(folder); - - g_assert (folder); - g_assert (nntp_folder->summary); - - return camel_folder_summary_count(nntp_folder->summary); -} - -static guint32 -nntp_folder_get_message_flags (CamelFolder *folder, const char *uid) -{ - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - CamelMessageInfo *info = camel_folder_summary_uid (nntp_folder->summary, uid); - - return info->flags; -} - static void nntp_folder_set_message_flags (CamelFolder *folder, const char *uid, guint32 flags, guint32 set) { - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - CamelMessageInfo *info = camel_folder_summary_uid (nntp_folder->summary, uid); - guint32 new; - - new = (info->flags & ~flags) | (set & flags); - if (new == info->flags) - return; + ((CamelFolderClass *)parent_class)->set_message_flags(folder, uid, flags, set); - info->flags = new; if (flags & set & CAMEL_MESSAGE_SEEN) { int article_num; CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (camel_folder_get_parent_store (folder)); @@ -114,8 +87,6 @@ nntp_folder_set_message_flags (CamelFolder *folder, const char *uid, folder->name, article_num); } - - camel_folder_summary_touch (nntp_folder->summary); } static CamelMimeMessage * @@ -151,6 +122,9 @@ nntp_folder_get_message (CamelFolder *folder, const gchar *uid, CamelException * return NULL; } + /* this could probably done fairly easily with an nntp stream that + returns eof after '.' */ + /* XXX ick ick ick. read the entire message into a buffer and then create a stream_mem for it. */ buf_alloc = 2048; @@ -206,34 +180,6 @@ nntp_folder_get_message (CamelFolder *folder, const gchar *uid, CamelException * return message; } -static GPtrArray * -nntp_folder_get_uids (CamelFolder *folder) -{ - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - GPtrArray *out; - CamelMessageInfo *message_info; - int i; - int count = camel_folder_summary_count (nntp_folder->summary); - - out = g_ptr_array_new (); - g_ptr_array_set_size (out, count); - - for (i = 0; i < count; i++) { - message_info = camel_folder_summary_index (nntp_folder->summary, i); - out->pdata[i] = g_strdup (camel_message_info_uid(message_info)); - } - - return out; -} - -static GPtrArray * -nntp_folder_get_summary (CamelFolder *folder) -{ - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - - return nntp_folder->summary->messages; -} - static GPtrArray* nntp_folder_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex) { @@ -241,14 +187,6 @@ nntp_folder_search_by_expression (CamelFolder *folder, const char *expression, C return NULL; } -static const CamelMessageInfo* -nntp_folder_get_message_info (CamelFolder *folder, const char *uid) -{ - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - - return camel_folder_summary_uid (nntp_folder->summary, uid); -} - static void nntp_folder_finalize (CamelObject *object) { @@ -268,16 +206,9 @@ camel_nntp_folder_class_init (CamelNNTPFolderClass *camel_nntp_folder_class) /* virtual method overload */ camel_folder_class->sync = nntp_folder_sync; - camel_folder_class->get_message_count = nntp_folder_get_message_count; camel_folder_class->set_message_flags = nntp_folder_set_message_flags; - camel_folder_class->get_message_flags = nntp_folder_get_message_flags; camel_folder_class->get_message = nntp_folder_get_message; - camel_folder_class->get_uids = nntp_folder_get_uids; - camel_folder_class->free_uids = camel_folder_free_deep; - camel_folder_class->get_summary = nntp_folder_get_summary; - camel_folder_class->free_summary = camel_folder_free_nop; camel_folder_class->search_by_expression = nntp_folder_search_by_expression; - camel_folder_class->get_message_info = nntp_folder_get_message_info; } CamelType @@ -313,11 +244,11 @@ camel_nntp_folder_new (CamelStore *parent, const char *folder_name, CamelExcepti root_dir_path, folder->name); - nntp_folder->summary = camel_folder_summary_new (); - camel_folder_summary_set_filename (nntp_folder->summary, + folder->summary = camel_folder_summary_new (); + camel_folder_summary_set_filename (folder->summary, nntp_folder->summary_file_path); - if (-1 == camel_folder_summary_load (nntp_folder->summary)) { + if (-1 == camel_folder_summary_load (folder->summary)) { /* Bad or nonexistant summary file */ camel_nntp_get_headers (CAMEL_FOLDER( folder )->parent_store, nntp_folder, ex); @@ -327,7 +258,7 @@ camel_nntp_folder_new (CamelStore *parent, const char *folder_name, CamelExcepti } /* XXX check return value */ - camel_folder_summary_save (nntp_folder->summary); + camel_folder_summary_save (folder->summary); } return folder; diff --git a/camel/providers/nntp/camel-nntp-newsrc.c b/camel/providers/nntp/camel-nntp-newsrc.c index b474dd3a40..d0b56222cf 100644 --- a/camel/providers/nntp/camel-nntp-newsrc.c +++ b/camel/providers/nntp/camel-nntp-newsrc.c @@ -32,6 +32,16 @@ #include "camel-nntp-newsrc.h" #include <camel/camel-folder-summary.h> +#ifdef ENABLE_THREADS +#include <pthread.h> + +#define NEWSRC_LOCK(f, l) (g_mutex_lock(((CamelNNTPNewsrc *)f)->l)) +#define NEWSRC_UNLOCK(f, l) (g_mutex_unlock(((CamelNNTPNewsrc *)f)->l)) +#else +#define NEWSRC_LOCK(f, l) +#define NEWSRC_UNLOCK(f, l) +#endif + typedef struct { guint low; guint high; @@ -47,8 +57,12 @@ struct CamelNNTPNewsrc { gchar *filename; GHashTable *groups; gboolean dirty; +#ifdef ENABLE_THREADS + GMutex *lock; +#endif } ; + static NewsrcGroup * camel_nntp_newsrc_group_add (CamelNNTPNewsrc *newsrc, const char *group_name, gboolean subscribed) { @@ -180,26 +194,40 @@ int camel_nntp_newsrc_get_highest_article_read (CamelNNTPNewsrc *newsrc, const char *group_name) { NewsrcGroup *group; + int ret; + + NEWSRC_LOCK(newsrc, lock); group = g_hash_table_lookup (newsrc->groups, group_name); + ret = camel_nntp_newsrc_group_get_highest_article_read (newsrc, group); + + NEWSRC_UNLOCK(newsrc, lock); - return camel_nntp_newsrc_group_get_highest_article_read (newsrc, group); + return ret; } int camel_nntp_newsrc_get_num_articles_read (CamelNNTPNewsrc *newsrc, const char *group_name) { NewsrcGroup *group; + int ret; + + NEWSRC_LOCK(newsrc, lock); group = g_hash_table_lookup (newsrc->groups, group_name); + ret = camel_nntp_newsrc_group_get_num_articles_read (newsrc, group); + + NEWSRC_UNLOCK(newsrc, lock); - return camel_nntp_newsrc_group_get_num_articles_read (newsrc, group); + return ret; } void camel_nntp_newsrc_mark_article_read (CamelNNTPNewsrc *newsrc, const char *group_name, int num) { + NEWSRC_LOCK(newsrc, lock); camel_nntp_newsrc_mark_range_read (newsrc, group_name, num, num); + NEWSRC_UNLOCK(newsrc, lock); } void @@ -216,9 +244,11 @@ camel_nntp_newsrc_mark_range_read(CamelNNTPNewsrc *newsrc, const char *group_nam low = tmp; } + NEWSRC_LOCK(newsrc, lock); group = g_hash_table_lookup (newsrc->groups, group_name); camel_nntp_newsrc_group_mark_range_read (newsrc, group, low, high); + NEWSRC_UNLOCK(newsrc, lock); } gboolean @@ -226,36 +256,51 @@ camel_nntp_newsrc_article_is_read (CamelNNTPNewsrc *newsrc, const char *group_na { int i; NewsrcGroup *group; + int ret = FALSE; + NEWSRC_LOCK(newsrc, lock); group = g_hash_table_lookup (newsrc->groups, group_name); for (i = 0; i < group->ranges->len; i++) { if (num >= g_array_index (group->ranges, ArticleRange, i).low && num <= g_array_index (group->ranges, ArticleRange, i).high) { - return TRUE; + ret = TRUE; + break; } } + NEWSRC_UNLOCK(newsrc, lock); + return FALSE; } gboolean camel_nntp_newsrc_group_is_subscribed (CamelNNTPNewsrc *newsrc, const char *group_name) { - NewsrcGroup *group = g_hash_table_lookup (newsrc->groups, group_name); + NewsrcGroup *group; + int ret = FALSE; + + NEWSRC_LOCK(newsrc, lock); + + group = g_hash_table_lookup (newsrc->groups, group_name); if (group) { - return group->subscribed; - } - else { - return FALSE; + ret = group->subscribed; } + + NEWSRC_UNLOCK(newsrc, lock); + + return ret; } void camel_nntp_newsrc_subscribe_group (CamelNNTPNewsrc *newsrc, const char *group_name) { - NewsrcGroup *group = g_hash_table_lookup (newsrc->groups, group_name); + NewsrcGroup *group; + + NEWSRC_LOCK(newsrc, lock); + + group = g_hash_table_lookup (newsrc->groups, group_name); if (group) { if (!group->subscribed) @@ -265,13 +310,18 @@ camel_nntp_newsrc_subscribe_group (CamelNNTPNewsrc *newsrc, const char *group_na else { camel_nntp_newsrc_group_add (newsrc, group_name, TRUE); } + + NEWSRC_UNLOCK(newsrc, lock); } void camel_nntp_newsrc_unsubscribe_group (CamelNNTPNewsrc *newsrc, const char *group_name) { - NewsrcGroup *group = g_hash_table_lookup (newsrc->groups, group_name); + NewsrcGroup *group; + + NEWSRC_LOCK(newsrc, lock); + group = g_hash_table_lookup (newsrc->groups, group_name); if (group) { if (group->subscribed) newsrc->dirty = TRUE; @@ -280,6 +330,8 @@ camel_nntp_newsrc_unsubscribe_group (CamelNNTPNewsrc *newsrc, const char *group_ else { camel_nntp_newsrc_group_add (newsrc, group_name, FALSE); } + + NEWSRC_UNLOCK(newsrc, lock); } struct newsrc_ptr_array { @@ -287,6 +339,7 @@ struct newsrc_ptr_array { gboolean subscribed_only; }; +/* this needs to strdup the grup_name, if the group array is likely to change */ static void get_group_foreach (char *group_name, NewsrcGroup *group, struct newsrc_ptr_array *npa) { @@ -302,12 +355,16 @@ camel_nntp_newsrc_get_subscribed_group_names (CamelNNTPNewsrc *newsrc) g_return_val_if_fail (newsrc, NULL); + NEWSRC_LOCK(newsrc, lock); + npa.ptr_array = g_ptr_array_new(); npa.subscribed_only = TRUE; g_hash_table_foreach (newsrc->groups, (GHFunc)get_group_foreach, &npa); + NEWSRC_UNLOCK(newsrc, lock); + return npa.ptr_array; } @@ -318,12 +375,16 @@ camel_nntp_newsrc_get_all_group_names (CamelNNTPNewsrc *newsrc) g_return_val_if_fail (newsrc, NULL); + NEWSRC_LOCK(newsrc, lock); + npa.ptr_array = g_ptr_array_new(); npa.subscribed_only = FALSE; g_hash_table_foreach (newsrc->groups, (GHFunc)get_group_foreach, &npa); + NEWSRC_UNLOCK(newsrc, lock); + return npa.ptr_array; } @@ -395,9 +456,13 @@ camel_nntp_newsrc_write_to_file(CamelNNTPNewsrc *newsrc, FILE *fp) newsrc_fp.newsrc = newsrc; newsrc_fp.fp = fp; + NEWSRC_LOCK(newsrc, lock); + g_hash_table_foreach (newsrc->groups, (GHFunc)camel_nntp_newsrc_write_group_line, &newsrc_fp); + + NEWSRC_UNLOCK(newsrc, lock); } void @@ -407,17 +472,21 @@ camel_nntp_newsrc_write(CamelNNTPNewsrc *newsrc) g_return_if_fail (newsrc); + NEWSRC_LOCK(newsrc, lock); + if (!newsrc->dirty) return; if ((fp = fopen(newsrc->filename, "w")) == NULL) { g_warning ("Couldn't open newsrc file '%s'.\n", newsrc->filename); + NEWSRC_UNLOCK(newsrc, lock); return; } - camel_nntp_newsrc_write_to_file(newsrc, fp); - newsrc->dirty = FALSE; + NEWSRC_UNLOCK(newsrc, lock); + + camel_nntp_newsrc_write_to_file(newsrc, fp); fclose(fp); } @@ -535,6 +604,9 @@ camel_nntp_newsrc_read_for_server (const char *server) newsrc = g_new0(CamelNNTPNewsrc, 1); newsrc->filename = filename; newsrc->groups = g_hash_table_new (g_str_hash, g_str_equal); +#ifdef ENABLE_THREADS + newsrc->lock = g_mutex_new(); +#endif if ((fd = open(filename, O_RDONLY)) == -1) { g_warning ("~/.newsrc-%s not present.\n", server); diff --git a/camel/providers/pop3/camel-pop3-folder.c b/camel/providers/pop3/camel-pop3-folder.c index 91760c80c5..cf55a95661 100644 --- a/camel/providers/pop3/camel-pop3-folder.c +++ b/camel/providers/pop3/camel-pop3-folder.c @@ -122,7 +122,8 @@ camel_pop3_folder_new (CamelStore *parent, CamelException *ex) folder = CAMEL_FOLDER (camel_object_new (CAMEL_POP3_FOLDER_TYPE)); camel_folder_construct (folder, parent, "inbox", "inbox"); - camel_folder_refresh_info (folder, ex); + /* mt-ok, since we dont have the folder-lock for new() */ + camel_folder_refresh_info (folder, ex);/* mt-ok */ if (camel_exception_is_set (ex)) { camel_object_unref (CAMEL_OBJECT (folder)); folder = NULL; diff --git a/camel/providers/vee/camel-vee-folder.c b/camel/providers/vee/camel-vee-folder.c index c8ac7f2059..7bfbd6d052 100644 --- a/camel/providers/vee/camel-vee-folder.c +++ b/camel/providers/vee/camel-vee-folder.c @@ -34,6 +34,8 @@ #include <string.h> +#define d(x) + /* our message info includes the parent folder */ typedef struct _CamelVeeMessageInfo { CamelMessageInfo info; @@ -47,27 +49,22 @@ struct _CamelVeeFolderPrivate { #define _PRIVATE(o) (((CamelVeeFolder *)(o))->priv) static void vee_sync (CamelFolder *folder, gboolean expunge, CamelException *ex); +static void vee_expunge (CamelFolder *folder, CamelException *ex); -static GPtrArray *vee_get_uids (CamelFolder *folder); -GPtrArray *vee_get_summary (CamelFolder *folder); - -static gint vee_get_message_count (CamelFolder *folder); -static gint vee_get_unread_message_count (CamelFolder *folder); static CamelMimeMessage *vee_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex); -static const CamelMessageInfo *vee_get_message_info (CamelFolder *folder, const char *uid); static GPtrArray *vee_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex); -static guint32 vee_get_message_flags (CamelFolder *folder, const char *uid); static void vee_set_message_flags (CamelFolder *folder, const char *uid, guint32 flags, guint32 set); -static gboolean vee_get_message_user_flag (CamelFolder *folder, const char *uid, const char *name); static void vee_set_message_user_flag (CamelFolder *folder, const char *uid, const char *name, gboolean value); - static void camel_vee_folder_class_init (CamelVeeFolderClass *klass); static void camel_vee_folder_init (CamelVeeFolder *obj); static void camel_vee_folder_finalise (CamelObject *obj); +static void folder_changed(CamelFolder *sub, gpointer type, CamelVeeFolder *vf); +static void message_changed(CamelFolder *f, const char *uid, CamelVeeFolder *mf); + static void vee_folder_build(CamelVeeFolder *vf, CamelException *ex); static void vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex); @@ -99,22 +96,13 @@ camel_vee_folder_class_init (CamelVeeFolderClass *klass) camel_vee_folder_parent = CAMEL_FOLDER_CLASS(camel_type_get_global_classfuncs (camel_folder_get_type ())); folder_class->sync = vee_sync; + folder_class->expunge = vee_expunge; - folder_class->get_uids = vee_get_uids; - folder_class->free_uids = camel_folder_free_deep; - folder_class->get_summary = vee_get_summary; - folder_class->free_summary = camel_folder_free_nop; folder_class->get_message = vee_get_message; - folder_class->get_message_info = vee_get_message_info; - - folder_class->get_message_count = vee_get_message_count; - folder_class->get_unread_message_count = vee_get_unread_message_count; folder_class->search_by_expression = vee_search_by_expression; - folder_class->get_message_flags = vee_get_message_flags; folder_class->set_message_flags = vee_set_message_flags; - folder_class->get_message_user_flag = vee_get_message_user_flag; folder_class->set_message_user_flag = vee_set_message_user_flag; } @@ -154,10 +142,15 @@ camel_vee_folder_finalise (CamelObject *obj) node = p->folders; while (node) { CamelFolder *f = node->data; + camel_object_unhook_event ((CamelObject *)f, "folder_changed", (CamelObjectEventHookFunc) folder_changed, vf); + camel_object_unhook_event ((CamelObject *)f, "message_changed", (CamelObjectEventHookFunc) message_changed, vf); camel_object_unref((CamelObject *)f); node = g_list_next(node); } + g_free(vf->expression); + g_free(vf->vname); + camel_folder_change_info_free(vf->changes); #ifdef DYNAMIC camel_object_unref((CamelObject *)vf->search); @@ -195,8 +188,8 @@ camel_vee_folder_new (CamelStore *parent_store, const char *name, CamelException *searchpart++ = 0; } - vf->messages = g_ptr_array_new(); - vf->messages_uid = g_hash_table_new(g_str_hash, g_str_equal); + folder->summary = camel_folder_summary_new(); + folder->summary->message_info_size = sizeof(CamelVeeMessageInfo); vf->expression = g_strdup(searchpart); vf->vname = namepart; @@ -210,6 +203,43 @@ camel_vee_folder_new (CamelStore *parent_store, const char *name, CamelException return folder; } +static CamelVeeMessageInfo * +vee_folder_add(CamelVeeFolder *vf, CamelFolder *f, CamelMessageInfo *info) +{ + CamelVeeMessageInfo *mi; + char *uid; + CamelFolder *folder = (CamelFolder *)vf; + + mi = (CamelVeeMessageInfo *)camel_folder_summary_info_new(folder->summary); + camel_message_info_dup_to(info, (CamelMessageInfo *)mi); + uid = g_strdup_printf("%p:%s", f, camel_message_info_uid(info)); +#ifdef DOESTRV + mi->info.strings = e_strv_set_ref_free(mi->info.strings, CAMEL_MESSAGE_INFO_UID, uid); + mi->info.strings = e_strv_pack(mi->info.strings); +#else + g_free(mi->info.uid); + mi->info.uid = uid; +#endif + mi->folder = f; + camel_folder_summary_add(folder->summary, (CamelMessageInfo *)mi); + + return mi; +} + +static CamelVeeMessageInfo * +vee_folder_add_uid(CamelVeeFolder *vf, CamelFolder *f, const char *inuid) +{ + CamelMessageInfo *info; + CamelVeeMessageInfo *mi = NULL; + + info = camel_folder_get_message_info(f, inuid); + if (info) { + mi = vee_folder_add(vf, f, info); + camel_folder_free_message_info(f, info); + } + return mi; +} + #ifdef DYNAMIC static void vfolder_remove_match(CamelVeeFolder *vf, CamelVeeMessageInfo *vinfo) @@ -218,38 +248,21 @@ vfolder_remove_match(CamelVeeFolder *vf, CamelVeeMessageInfo *vinfo) printf("removing match %s\n", uid); - g_hash_table_remove(vf->messages_uid, uid); - g_ptr_array_remove_fast(vf->messages, vinfo); + camel_folder_summary_remove(((CamelFolder *)vf)->summary, (CamelMessageInfo *)vinfo); camel_folder_change_info_remove_uid(vf->changes, uid); - camel_message_info_free((CamelMessageInfo *)vinfo); } static CamelVeeMessageInfo * -vfolder_add_match(CamelVeeFolder *vf, CamelFolder *f, const CamelMessageInfo *info) +vee_folder_add_change(CamelVeeFolder *vf, CamelFolder *f, CamelMessageInfo *info) { - CamelVeeMessageInfo *mi; - char *uid; + CamelVeeMessageInfo *mi = NULL; - mi = g_malloc0(sizeof(*mi)); - camel_message_info_dup_to(info, (CamelMessageInfo*)mi); - uid = g_strdup_printf("%p:%s", f, camel_message_info_uid(info)); -#ifdef DOESTRV - mi->info.strings = e_strv_set_ref_free(mi->info.strings, CAMEL_MESSAGE_INFO_UID, uid); - mi->info.strings = e_strv_pack(mi->info.strings); -#else - g_free (mi->info.uid); - mi->info.uid = uid; -#endif - mi->folder = f; - g_ptr_array_add(vf->messages, mi); - uid = (char *)camel_message_info_uid(mi); - g_hash_table_insert(vf->messages_uid, uid, mi); - - printf("adding match %s\n", uid); - - camel_folder_change_info_add_uid(vf->changes, uid); + mi = vee_folder_add(vf, f, info); + camel_folder_change_info_add_uid(vf->changes, camel_message_info_uid(mi)); + return mi; } + #endif static void @@ -258,7 +271,7 @@ vfolder_change_match(CamelVeeFolder *vf, CamelVeeMessageInfo *vinfo, const Camel CamelFlag *flag; CamelTag *tag; - printf("changing match %s\n", camel_message_info_uid(vinfo)); + d(printf("changing match %s\n", camel_message_info_uid(vinfo))); vinfo->info.flags = info->flags; camel_flag_list_free(&vinfo->info.user_flags); @@ -276,6 +289,8 @@ vfolder_change_match(CamelVeeFolder *vf, CamelVeeMessageInfo *vinfo, const Camel camel_folder_change_info_change_uid(vf->changes, camel_message_info_uid(vinfo)); } +/* FIXME: This code is a big race, as it is never called locked ... */ + static void folder_changed(CamelFolder *sub, gpointer type, CamelVeeFolder *vf) { @@ -283,6 +298,7 @@ folder_changed(CamelFolder *sub, gpointer type, CamelVeeFolder *vf) #ifdef DYNAMIC CamelFolderChangeInfo *changes = type; + CamelFolder *folder = (CamelFolder *)vf; /* assume its faster to search a long list in whole, than by part */ if (changes && (changes->uid_added->len + changes->uid_changed->len) < 500) { @@ -290,10 +306,18 @@ folder_changed(CamelFolder *sub, gpointer type, CamelVeeFolder *vf) char *vuid; CamelVeeMessageInfo *vinfo; gboolean match; - const CamelMessageInfo *info; + CamelMessageInfo *info; ex = camel_exception_new(); + /* FIXME: We dont search body contents with this search, so, it isn't as + useful as it might be. + We shold probably just perform a whole search if we need to, i.e. there + are added items. Changed items we are unlikely to want to remove immediately + anyway, although I guess it might be useful. + Removed items can always just be removed. + */ + /* see if added ones now match us */ for (i=0;i<changes->uid_added->len;i++) { info = camel_folder_get_message_info(sub, changes->uid_added->pdata[i]); @@ -301,7 +325,8 @@ folder_changed(CamelFolder *sub, gpointer type, CamelVeeFolder *vf) camel_folder_search_set_folder(vf->search, sub); match = camel_folder_search_match_expression(vf->search, vf->expression, info, ex); if (match) - vinfo = vfolder_add_match(vf, sub, info); + vinfo = vee_folder_add_change(vf, sub, info); + camel_folder_free_message_info(sub, info); } } @@ -309,20 +334,31 @@ folder_changed(CamelFolder *sub, gpointer type, CamelVeeFolder *vf) for (i=0;i<changes->uid_changed->len;i++) { info = camel_folder_get_message_info(sub, changes->uid_changed->pdata[i]); vuid = g_strdup_printf("%p:%s", sub, (char *)changes->uid_changed->pdata[i]); - vinfo = (CamelVeeMessageInfo *)vee_get_message_info((CamelFolder *)vf, vuid); + vinfo = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, vuid); if (info) { camel_folder_search_set_folder(vf->search, sub); +#if 0 match = camel_folder_search_match_expression(vf->search, vf->expression, info, ex); +#endif if (vinfo) { - if (match) - vfolder_change_match(vf, vinfo, info); - else +#if 0 + if (!match) vfolder_remove_match(vf, vinfo); - } else if (match) - vfolder_add_match(vf, sub, info); + else +#endif + vfolder_change_match(vf, vinfo, info); + } +#if 0 + else if (match) + vee_folder_add_change(vf, sub, info); +#endif + camel_folder_free_message_info(sub, info); } else if (vinfo) vfolder_remove_match(vf, vinfo); + if (vinfo) + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)vinfo); + g_free(vuid); } @@ -331,9 +367,11 @@ folder_changed(CamelFolder *sub, gpointer type, CamelVeeFolder *vf) /* mirror removes directly, if they used to match */ for (i=0;i<changes->uid_removed->len;i++) { vuid = g_strdup_printf("%p:%s", sub, (char *)changes->uid_removed->pdata[i]); - vinfo = (CamelVeeMessageInfo *)vee_get_message_info((CamelFolder *)vf, vuid); - if (vinfo) + vinfo = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, vuid); + if (vinfo) { vfolder_remove_match(vf, vinfo); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)vinfo); + } g_free(vuid); } } else { @@ -352,21 +390,24 @@ folder_changed(CamelFolder *sub, gpointer type, CamelVeeFolder *vf) } } +/* FIXME: This code is a race, as it is never called locked */ + /* track flag changes in the summary */ static void message_changed(CamelFolder *f, const char *uid, CamelVeeFolder *mf) { - const CamelMessageInfo *info; + CamelMessageInfo *info; CamelVeeMessageInfo *vinfo; char *vuid; + CamelFolder *folder = (CamelFolder *)mf; #ifdef DYNAMIC - gboolean match; + /*gboolean match;*/ CamelException *ex; #endif info = camel_folder_get_message_info(f, uid); vuid = g_strdup_printf("%p:%s", f, uid); - vinfo = (CamelVeeMessageInfo *)vee_get_message_info((CamelFolder *)mf, vuid); + vinfo = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, vuid); /* see if this message now matches/doesn't match anymore */ @@ -376,16 +417,23 @@ message_changed(CamelFolder *f, const char *uid, CamelVeeFolder *mf) #ifdef DYNAMIC camel_folder_search_set_folder(mf->search, f); ex = camel_exception_new(); +#if 0 match = camel_folder_search_match_expression(mf->search, mf->expression, info, ex); +#endif camel_exception_free(ex); if (info) { if (vinfo) { - if (match) - vfolder_change_match(mf, vinfo, info); - else +#if 0 + if (!match) vfolder_remove_match(mf, vinfo); - } else if (match) - vfolder_add_match(mf, f, info); + else +#endif + vfolder_change_match(mf, vinfo, info); + } +#if 0 + else if (match) + vee_folder_add_change(mf, f, info); +#endif } else if (vinfo) vfolder_remove_match(mf, vinfo); #else @@ -393,6 +441,11 @@ message_changed(CamelFolder *f, const char *uid, CamelVeeFolder *mf) vfolder_change_match(mf, vinfo, info); #endif + if (info) + camel_folder_free_message_info(f, info); + if (vinfo) + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)vinfo); + /* cascade up, if required. This could probably be delayed, but doesn't matter really, that is what freeze is for. */ if (camel_folder_change_info_changed(mf->changes)) { @@ -432,97 +485,53 @@ camel_vee_folder_add_folder(CamelVeeFolder *vf, CamelFolder *sub) } - static void vee_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) { - ; -} - -static gint vee_get_message_count (CamelFolder *folder) -{ CamelVeeFolder *vf = (CamelVeeFolder *)folder; + struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); + GList *node; - return vf->messages->len; -} - -static gint -vee_get_unread_message_count (CamelFolder *folder) -{ - CamelVeeFolder *vee_folder = CAMEL_VEE_FOLDER (folder); - CamelMessageInfo *info; - GPtrArray *infolist; - gint i, count = 0; - - g_return_val_if_fail (folder != NULL, -1); + node = p->folders; + while (node) { + CamelFolder *f = node->data; - infolist = vee_folder->messages; - - for (i = 0; i < infolist->len; i++) { - info = (CamelMessageInfo *) g_ptr_array_index (infolist, i); - if (!(info->flags & CAMEL_MESSAGE_SEEN)) - count++; + camel_folder_sync(f, expunge, ex); + node = node->next; } - - return count; } -static gboolean -get_real_message(CamelFolder *folder, const char *uid, CamelFolder **out_folder, const char **out_uid) +static void +vee_expunge (CamelFolder *folder, CamelException *ex) { - CamelVeeMessageInfo *mi; + CamelVeeFolder *vf = (CamelVeeFolder *)folder; + struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); + GList *node; - mi = (CamelVeeMessageInfo *)vee_get_message_info(folder, uid); - g_return_val_if_fail(mi != NULL, FALSE); + node = p->folders; + while (node) { + CamelFolder *f = node->data; - *out_folder = mi->folder; - *out_uid = strchr(camel_message_info_uid(mi), ':')+1; - return TRUE; + camel_folder_expunge(f, ex); + node = node->next; + } } static CamelMimeMessage *vee_get_message(CamelFolder *folder, const gchar *uid, CamelException *ex) { - const char *real_uid; - CamelFolder *real_folder; + CamelVeeMessageInfo *mi; + CamelMimeMessage *msg = NULL; - if (!get_real_message(folder, uid, &real_folder, &real_uid)) { + mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, uid); + if (mi == NULL) camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, "No such message %s in %s", uid, folder->name); - return NULL; - } - - return camel_folder_get_message (real_folder, real_uid, ex); -} - -GPtrArray *vee_get_summary(CamelFolder *folder) -{ - CamelVeeFolder *vf = (CamelVeeFolder *)folder; + else + msg = camel_folder_get_message(mi->folder, strchr(camel_message_info_uid(mi), ':') + 1, ex); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)mi); - return vf->messages; -} - -static const CamelMessageInfo *vee_get_message_info(CamelFolder *f, const char *uid) -{ - CamelVeeFolder *vf = (CamelVeeFolder *)f; - - return g_hash_table_lookup(vf->messages_uid, uid); -} - -static GPtrArray *vee_get_uids (CamelFolder *folder) -{ - GPtrArray *result; - int i; - CamelVeeFolder *vf = (CamelVeeFolder *)folder; - - result = g_ptr_array_new (); - g_ptr_array_set_size (result, vf->messages->len); - for (i=0;i<vf->messages->len;i++) { - CamelMessageInfo *mi = g_ptr_array_index(vf->messages, i); - result->pdata[i] = g_strdup(camel_message_info_uid(mi)); - } - - return result; + return msg; } static GPtrArray * @@ -551,55 +560,32 @@ vee_search_by_expression(CamelFolder *folder, const char *expression, CamelExcep return result; } -static guint32 -vee_get_message_flags(CamelFolder *folder, const char *uid) -{ - const char *real_uid; - CamelFolder *real_folder; - - if (!get_real_message (folder, uid, &real_folder, &real_uid)) - return 0; - - return camel_folder_get_message_flags(real_folder, real_uid); -} - static void vee_set_message_flags(CamelFolder *folder, const char *uid, guint32 flags, guint32 set) { - const char *real_uid; - CamelFolder *real_folder; - - if (!get_real_message(folder, uid, &real_folder, &real_uid)) - return; - - camel_folder_set_message_flags(real_folder, real_uid, flags, set); -} - -static gboolean -vee_get_message_user_flag(CamelFolder *folder, const char *uid, const char *name) -{ - const char *real_uid; - CamelFolder *real_folder; - - if (!get_real_message(folder, uid, &real_folder, &real_uid)) - return FALSE; + CamelVeeMessageInfo *mi; - return camel_folder_get_message_user_flag(real_folder, real_uid, name); + mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, uid); + if (mi) { + ((CamelFolderClass *)camel_vee_folder_parent)->set_message_flags(folder, uid, flags, set); + camel_folder_set_message_flags(mi->folder, strchr(camel_message_info_uid(mi), ':') + 1, flags, set); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)mi); + } } static void vee_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value) { - const char *real_uid; - CamelFolder *real_folder; - - if (!get_real_message(folder, uid, &real_folder, &real_uid)) - return; + CamelVeeMessageInfo *mi; - return camel_folder_set_message_user_flag(real_folder, real_uid, name, value); + mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, uid); + if (mi) { + ((CamelFolderClass *)camel_vee_folder_parent)->set_message_user_flag(folder, uid, name, value); + camel_folder_set_message_user_flag(mi->folder, strchr(camel_message_info_uid(mi), ':') + 1, name, value); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)mi); + } } - /* need incremental update, based on folder. Need to watch folders for changes and update accordingly. @@ -609,54 +595,22 @@ vee_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name static void vee_folder_build(CamelVeeFolder *vf, CamelException *ex) { + CamelFolder *folder = (CamelFolder *)vf; struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); GList *node; - int i; - GPtrArray *messages; - GHashTable *messages_uid; - for (i=0;i<vf->messages->len;i++) { - CamelMessageInfo *mi = g_ptr_array_index(vf->messages, i); - camel_message_info_free(mi); - } - - messages = g_ptr_array_new(); - messages_uid = g_hash_table_new(g_str_hash, g_str_equal); - - g_ptr_array_free(vf->messages, TRUE); - vf->messages = messages; - g_hash_table_destroy(vf->messages_uid); - vf->messages_uid = messages_uid; + camel_folder_summary_clear(folder->summary); node = p->folders; while (node) { GPtrArray *matches; CamelFolder *f = node->data; - CamelVeeMessageInfo *mi; - const CamelMessageInfo *info; int i; matches = camel_folder_search_by_expression(f, vf->expression, ex); - for (i = 0; i < matches->len; i++) { - info = camel_folder_get_message_info(f, matches->pdata[i]); - if (info) { - char *uid; + for (i = 0; i < matches->len; i++) + vee_folder_add_uid(vf, f, matches->pdata[i]); - mi = g_malloc0(sizeof(*mi)); - camel_message_info_dup_to(info, (CamelMessageInfo *)mi); - uid = g_strdup_printf("%p:%s", f, camel_message_info_uid(info)); -#ifdef DOESTRV - mi->info.strings = e_strv_set_ref_free(mi->info.strings, CAMEL_MESSAGE_INFO_UID, uid); - mi->info.strings = e_strv_pack(mi->info.strings); -#else - g_free(mi->info.uid); - mi->info.uid = uid; -#endif - mi->folder = f; - g_ptr_array_add(messages, mi); - g_hash_table_insert(messages_uid, (char *)camel_message_info_uid(mi), mi); - } - } camel_folder_search_free(f, matches); node = g_list_next(node); } @@ -670,50 +624,27 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException GPtrArray *matches; CamelFolder *f = source; CamelVeeMessageInfo *mi; - const CamelMessageInfo *info; - - GPtrArray *messages; - GHashTable *messages_uid; + CamelFolder *folder = (CamelFolder *)vf; int i; + int count; - for (i=0;i<vf->messages->len;i++) { - CamelVeeMessageInfo *mi = g_ptr_array_index(vf->messages, i); - if (mi->folder == source) { + count = camel_folder_summary_count(folder->summary); + for (i=0;i<count;i++) { + CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_index(folder->summary, i); + if (mi && mi->folder == source) { const char *uid = camel_message_info_uid(mi); camel_folder_change_info_add_source(vf->changes, uid); - g_hash_table_remove(vf->messages_uid, uid); - g_ptr_array_remove_index_fast(vf->messages, i); - - camel_message_info_free((CamelMessageInfo *)mi); + camel_folder_summary_remove(folder->summary, (CamelMessageInfo *)mi); i--; } + camel_message_info_free((CamelMessageInfo *)mi); } - messages = vf->messages; - messages_uid = vf->messages_uid; - matches = camel_folder_search_by_expression(f, vf->expression, ex); for (i = 0; i < matches->len; i++) { - info = camel_folder_get_message_info(f, matches->pdata[i]); - if (info) { - char *uid; - - mi = g_malloc0(sizeof(*mi)); - camel_message_info_dup_to(info, (CamelMessageInfo*)mi); - uid = g_strdup_printf("%p:%s", f, camel_message_info_uid(info)); -#ifdef DOESTRV - mi->info.strings = e_strv_set_ref_free(mi->info.strings, CAMEL_MESSAGE_INFO_UID, uid); - mi->info.strings = e_strv_pack(mi->info.strings); -#else - g_free (mi->info.uid); - mi->info.uid = uid; -#endif - mi->folder = f; - g_ptr_array_add(messages, mi); - uid = (char *)camel_message_info_uid(mi); - g_hash_table_insert(messages_uid, uid, mi); - camel_folder_change_info_add_update(vf->changes, uid); - } + mi = vee_folder_add_uid(vf, f, matches->pdata[i]); + if (mi) + camel_folder_change_info_add_update(vf->changes, camel_message_info_uid(mi)); } camel_folder_search_free(f, matches); diff --git a/camel/providers/vee/camel-vee-folder.h b/camel/providers/vee/camel-vee-folder.h index 3b6676d281..65c718a8d6 100644 --- a/camel/providers/vee/camel-vee-folder.h +++ b/camel/providers/vee/camel-vee-folder.h @@ -43,9 +43,6 @@ struct _CamelVeeFolder { char *vname; /* local name */ CamelFolder *local; /* local storage for folder */ - /* FIXME: Move this to a summary object??? */ - GPtrArray *messages; /* message info's */ - GHashTable *messages_uid; CamelFolderChangeInfo *changes; #ifdef DYNAMIC CamelFolderSearch *search; |