aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers
diff options
context:
space:
mode:
authorNot Zed <NotZed@HelixCode.com>2000-12-24 08:46:20 +0800
committerMichael Zucci <zucchi@src.gnome.org>2000-12-24 08:46:20 +0800
commit6de256c2a2b23f30d35e4a2213ad5839bf141d06 (patch)
treea34d8be64c0718070c4e1ea9548282912f37b387 /camel/providers
parent6183d89039ba67a7f3869f460c13aff09a548471 (diff)
downloadgsoc2013-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')
-rw-r--r--camel/providers/imap/Makefile.am3
-rw-r--r--camel/providers/imap/camel-imap-auth.c15
-rw-r--r--camel/providers/imap/camel-imap-command.c5
-rw-r--r--camel/providers/imap/camel-imap-folder.c233
-rw-r--r--camel/providers/imap/camel-imap-folder.h2
-rw-r--r--camel/providers/imap/camel-imap-private.h74
-rw-r--r--camel/providers/imap/camel-imap-search.c32
-rw-r--r--camel/providers/imap/camel-imap-store.c55
-rw-r--r--camel/providers/imap/camel-imap-store.h3
-rw-r--r--camel/providers/local/Makefile.am3
-rw-r--r--camel/providers/local/camel-local-folder.c263
-rw-r--r--camel/providers/local/camel-local-folder.h2
-rw-r--r--camel/providers/local/camel-local-private.h60
-rw-r--r--camel/providers/local/camel-local-summary.c159
-rw-r--r--camel/providers/local/camel-maildir-folder.c7
-rw-r--r--camel/providers/local/camel-maildir-summary.c34
-rw-r--r--camel/providers/local/camel-mbox-folder.c58
-rw-r--r--camel/providers/local/camel-mbox-summary.c21
-rw-r--r--camel/providers/local/camel-mh-folder.c7
-rw-r--r--camel/providers/local/camel-mh-summary.c31
-rw-r--r--camel/providers/nntp/camel-nntp-folder.c87
-rw-r--r--camel/providers/nntp/camel-nntp-newsrc.c96
-rw-r--r--camel/providers/pop3/camel-pop3-folder.c3
-rw-r--r--camel/providers/vee/camel-vee-folder.c413
-rw-r--r--camel/providers/vee/camel-vee-folder.h3
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;