[evolution-data-server] Make CamelPOP3Store a bit more thread-safe.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Make CamelPOP3Store a bit more thread-safe.
- Date: Mon, 20 May 2013 22:00:35 +0000 (UTC)
commit 0338a31f78160beadaba421698c79635737c6b8c
Author: Matthew Barnes <mbarnes redhat com>
Date: Mon May 20 17:43:46 2013 -0400
Make CamelPOP3Store a bit more thread-safe.
* Make CamelPOP3Store's cache and engine members private.
* Guard the private cache and engine members with a mutex.
* Add thread-safe accessors which return a new reference:
camel_pop3_store_ref_cache()
camel_pop3_store_ref_engine()
TODO: CamelPOP3Engine itself should also be made thread-safe, but that
will be considerably more work. This commit merely prevents the
CamelPOP3Engine from being finalized while still in use.
camel/providers/pop3/camel-pop3-folder.c | 154 +++++++++++++-------
camel/providers/pop3/camel-pop3-store.c | 239 +++++++++++++++++++++++-------
camel/providers/pop3/camel-pop3-store.h | 7 +-
3 files changed, 287 insertions(+), 113 deletions(-)
---
diff --git a/camel/providers/pop3/camel-pop3-folder.c b/camel/providers/pop3/camel-pop3-folder.c
index 5e6f438..96d45fa 100644
--- a/camel/providers/pop3/camel-pop3-folder.c
+++ b/camel/providers/pop3/camel-pop3-folder.c
@@ -41,19 +41,26 @@
G_DEFINE_TYPE (CamelPOP3Folder, camel_pop3_folder, CAMEL_TYPE_FOLDER)
static void
-free_fi (CamelPOP3Folder *pop3_folder,CamelPOP3FolderInfo *fi)
+free_fi (CamelPOP3Folder *pop3_folder,
+ CamelPOP3FolderInfo *fi)
{
CamelPOP3Store *pop3_store;
CamelStore *store;
- store = camel_folder_get_parent_store ((CamelFolder *) pop3_folder);
+ store = camel_folder_get_parent_store (CAMEL_FOLDER (pop3_folder));
pop3_store = CAMEL_POP3_STORE (store);
g_hash_table_remove (pop3_folder->uids_id, GINT_TO_POINTER (fi->id));
- if (fi->cmd) {
- camel_pop3_engine_command_free (pop3_store->engine, fi->cmd);
+ if (fi->cmd != NULL) {
+ CamelPOP3Engine *pop3_engine;
+
+ pop3_engine = camel_pop3_store_ref_engine (pop3_store);
+
+ camel_pop3_engine_command_free (pop3_engine, fi->cmd);
fi->cmd = NULL;
+
+ g_object_unref (pop3_engine);
}
g_free (fi->uid);
g_free (fi);
@@ -155,7 +162,6 @@ cmd_list (CamelPOP3Engine *pe,
guchar *line;
CamelFolder *folder = data;
CamelStore *parent_store;
- CamelPOP3Store *pop3_store;
CamelPOP3FolderInfo *fi;
gint i = 0, total, last_uid=-1;
CamelPOP3Folder *pop3_folder;
@@ -164,7 +170,6 @@ cmd_list (CamelPOP3Engine *pe,
gint batch_fetch_count;
parent_store = camel_folder_get_parent_store (folder);
- pop3_store = CAMEL_POP3_STORE (parent_store);
pop3_folder = (CamelPOP3Folder *) folder;
service = (CamelService *) parent_store;
@@ -183,7 +188,7 @@ cmd_list (CamelPOP3Engine *pe,
fi->size = size;
fi->id = id;
fi->index = ((CamelPOP3Folder *) folder)->uids->len;
- if ((pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL) == 0)
+ if ((pe->capa & CAMEL_POP3_CAP_UIDL) == 0)
fi->cmd = camel_pop3_engine_command_new (
pe,
CAMEL_POP3_COMMAND_MULTI,
@@ -384,9 +389,15 @@ pop3_folder_dispose (GObject *object)
for (i = 0; i < pop3_folder->uids->len; i++, fi++) {
if (fi[0]->cmd && pop3_store && is_online) {
- while (camel_pop3_engine_iterate (pop3_store->engine, fi[0]->cmd, NULL, NULL)
0)
+ CamelPOP3Engine *pop3_engine;
+
+ pop3_engine = camel_pop3_store_ref_engine (pop3_store);
+
+ while (camel_pop3_engine_iterate (pop3_engine, fi[0]->cmd, NULL, NULL) > 0)
;
- camel_pop3_engine_command_free (pop3_store->engine, fi[0]->cmd);
+ camel_pop3_engine_command_free (pop3_engine, fi[0]->cmd);
+
+ g_clear_object (&pop3_engine);
}
g_free (fi[0]->uid);
@@ -438,7 +449,9 @@ pop3_folder_get_filename (CamelFolder *folder,
CamelStore *parent_store;
CamelPOP3Folder *pop3_folder;
CamelPOP3Store *pop3_store;
+ CamelDataCache *pop3_cache;
CamelPOP3FolderInfo *fi;
+ gchar *filename;
parent_store = camel_folder_get_parent_store (folder);
@@ -454,8 +467,12 @@ pop3_folder_get_filename (CamelFolder *folder,
return NULL;
}
- return camel_data_cache_get_filename (
- pop3_store->cache, "cache", fi->uid);
+ pop3_cache = camel_pop3_store_ref_cache (pop3_store);
+ filename = camel_data_cache_get_filename (
+ pop3_cache, "cache", fi->uid);
+ g_clear_object (&pop3_cache);
+
+ return filename;
}
static gboolean
@@ -491,6 +508,8 @@ pop3_folder_get_message_sync (CamelFolder *folder,
CamelMimeMessage *message = NULL;
CamelPOP3Store *pop3_store;
CamelPOP3Folder *pop3_folder;
+ CamelDataCache *pop3_cache;
+ CamelPOP3Engine *pop3_engine;
CamelPOP3Command *pcr;
CamelPOP3FolderInfo *fi;
gchar buffer[1];
@@ -541,16 +560,19 @@ pop3_folder_get_message_sync (CamelFolder *folder,
camel_operation_push_message (
cancellable, _("Retrieving POP message %d"), fi->id);
+ pop3_cache = camel_pop3_store_ref_cache (pop3_store);
+ pop3_engine = camel_pop3_store_ref_engine (pop3_store);
+
/* If we have an oustanding retrieve message running, wait for that to complete
* & then retrieve from cache, otherwise, start a new one, and similar */
if (fi->cmd != NULL) {
- while ((i = camel_pop3_engine_iterate (pop3_store->engine, fi->cmd, cancellable, error)) > 0)
+ while ((i = camel_pop3_engine_iterate (pop3_engine, fi->cmd, cancellable, error)) > 0)
;
/* getting error code? */
/*g_assert (fi->cmd->state == CAMEL_POP3_COMMAND_DATA);*/
- camel_pop3_engine_command_free (pop3_store->engine, fi->cmd);
+ camel_pop3_engine_command_free (pop3_engine, fi->cmd);
fi->cmd = NULL;
if (i == -1) {
@@ -561,20 +583,20 @@ pop3_folder_get_message_sync (CamelFolder *folder,
}
/* check to see if we have safely written flag set */
- if (pop3_store->cache == NULL
- || (stream = camel_data_cache_get (pop3_store->cache, "cache", fi->uid, NULL)) == NULL
+ if (pop3_cache == NULL
+ || (stream = camel_data_cache_get (pop3_cache, "cache", fi->uid, NULL)) == NULL
|| camel_stream_read (stream, buffer, 1, cancellable, NULL) != 1
|| buffer[0] != '#') {
/* Initiate retrieval, if disk backing fails, use a memory backing */
- if (pop3_store->cache == NULL
- || (stream = camel_data_cache_add (pop3_store->cache, "cache", fi->uid, NULL)) == NULL)
+ if (pop3_cache == NULL
+ || (stream = camel_data_cache_add (pop3_cache, "cache", fi->uid, NULL)) == NULL)
stream = camel_stream_mem_new ();
/* ref it, the cache storage routine unref's when done */
fi->stream = g_object_ref (stream);
pcr = camel_pop3_engine_command_new (
- pop3_store->engine,
+ pop3_engine,
CAMEL_POP3_COMMAND_MULTI,
cmd_tocache, fi,
cancellable, error,
@@ -582,7 +604,7 @@ pop3_folder_get_message_sync (CamelFolder *folder,
/* Also initiate retrieval of some of the following
* messages, assume we'll be receiving them. */
- if (auto_fetch && pop3_store->cache != NULL) {
+ if (auto_fetch && pop3_cache != NULL) {
/* This should keep track of the last one retrieved,
* also how many are still oustanding incase of random
* access on large folders. */
@@ -593,11 +615,11 @@ pop3_folder_get_message_sync (CamelFolder *folder,
if (pfi->uid && pfi->cmd == NULL) {
pfi->stream = camel_data_cache_add (
- pop3_store->cache,
+ pop3_cache,
"cache", pfi->uid, NULL);
if (pfi->stream) {
pfi->cmd = camel_pop3_engine_command_new (
- pop3_store->engine,
+ pop3_engine,
CAMEL_POP3_COMMAND_MULTI,
cmd_tocache, pfi,
cancellable, error,
@@ -608,12 +630,12 @@ pop3_folder_get_message_sync (CamelFolder *folder,
}
/* now wait for the first one to finish */
- while ((i = camel_pop3_engine_iterate (pop3_store->engine, pcr, cancellable, error)) > 0)
+ while ((i = camel_pop3_engine_iterate (pop3_engine, pcr, cancellable, error)) > 0)
;
/* getting error code? */
/*g_assert (pcr->state == CAMEL_POP3_COMMAND_DATA);*/
- camel_pop3_engine_command_free (pop3_store->engine, pcr);
+ camel_pop3_engine_command_free (pop3_engine, pcr);
g_seekable_seek (
G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, NULL);
@@ -649,6 +671,9 @@ pop3_folder_get_message_sync (CamelFolder *folder,
done:
g_object_unref (stream);
fail:
+ g_clear_object (&pop3_cache);
+ g_clear_object (&pop3_engine);
+
camel_operation_pop_message (cancellable);
return message;
@@ -662,6 +687,7 @@ pop3_folder_refresh_info_sync (CamelFolder *folder,
CamelStore *parent_store;
CamelPOP3Store *pop3_store;
CamelPOP3Folder *pop3_folder = (CamelPOP3Folder *) folder;
+ CamelPOP3Engine *pop3_engine;
CamelPOP3Command *pcl, *pcu = NULL;
gboolean success = TRUE;
GError *local_error = NULL;
@@ -681,6 +707,8 @@ pop3_folder_refresh_info_sync (CamelFolder *folder,
camel_operation_push_message (
cancellable, _("Retrieving POP summary"));
+ pop3_engine = camel_pop3_store_ref_engine (pop3_store);
+
/* Get rid of the old cache */
if (pop3_folder->uids) {
gint i;
@@ -698,7 +726,7 @@ pop3_folder_refresh_info_sync (CamelFolder *folder,
for (i = 0; i < pop3_folder->uids->len; i++) {
CamelPOP3FolderInfo *fi = pop3_folder->uids->pdata[i];
if (fi->cmd) {
- camel_pop3_engine_command_free (pop3_store->engine, fi->cmd);
+ camel_pop3_engine_command_free (pop3_engine, fi->cmd);
fi->cmd = NULL;
}
g_free (fi->uid);
@@ -721,19 +749,19 @@ pop3_folder_refresh_info_sync (CamelFolder *folder,
pop3_folder->uids_id = g_hash_table_new (NULL, NULL);
pcl = camel_pop3_engine_command_new (
- pop3_store->engine,
+ pop3_engine,
CAMEL_POP3_COMMAND_MULTI,
cmd_list, folder,
cancellable, &local_error,
"LIST\r\n");
- if (!local_error && (pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL) != 0)
+ if (!local_error && (pop3_engine->capa & CAMEL_POP3_CAP_UIDL) != 0)
pcu = camel_pop3_engine_command_new (
- pop3_store->engine,
+ pop3_engine,
CAMEL_POP3_COMMAND_MULTI,
cmd_uidl, folder,
cancellable, &local_error,
"UIDL\r\n");
- while ((i = camel_pop3_engine_iterate (pop3_store->engine, NULL, cancellable, &local_error)) > 0)
+ while ((i = camel_pop3_engine_iterate (pop3_engine, NULL, cancellable, &local_error)) > 0)
;
if (local_error) {
@@ -757,7 +785,7 @@ pop3_folder_refresh_info_sync (CamelFolder *folder,
g_set_error_literal (error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot get
POP summary: "));
}
- camel_pop3_engine_command_free (pop3_store->engine, pcl);
+ camel_pop3_engine_command_free (pop3_engine, pcl);
}
if (pcu) {
@@ -770,7 +798,7 @@ pop3_folder_refresh_info_sync (CamelFolder *folder,
g_set_error_literal (error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot get
POP summary: "));
}
- camel_pop3_engine_command_free (pop3_store->engine, pcu);
+ camel_pop3_engine_command_free (pop3_engine, pcu);
} else {
for (i = 0; i < pop3_folder->uids->len; i++) {
CamelPOP3FolderInfo *fi = pop3_folder->uids->pdata[i];
@@ -784,7 +812,7 @@ pop3_folder_refresh_info_sync (CamelFolder *folder,
g_set_error_literal (error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
_("Cannot get POP summary: "));
}
- camel_pop3_engine_command_free (pop3_store->engine, fi->cmd);
+ camel_pop3_engine_command_free (pop3_engine, fi->cmd);
fi->cmd = NULL;
}
if (fi->uid) {
@@ -797,6 +825,8 @@ pop3_folder_refresh_info_sync (CamelFolder *folder,
g_hash_table_destroy (pop3_folder->uids_id);
pop3_folder->uids_id = NULL;
+ g_clear_object (&pop3_engine);
+
camel_operation_pop_message (cancellable);
return success;
@@ -860,6 +890,8 @@ pop3_folder_synchronize_sync (CamelFolder *folder,
CamelStore *parent_store;
CamelPOP3Folder *pop3_folder;
CamelPOP3Store *pop3_store;
+ CamelDataCache *pop3_cache;
+ CamelPOP3Engine *pop3_engine;
CamelPOP3FolderInfo *fi;
gint delete_after_days;
gboolean delete_expunged;
@@ -910,26 +942,29 @@ pop3_folder_synchronize_sync (CamelFolder *folder,
camel_operation_push_message (
cancellable, _("Expunging deleted messages"));
+ pop3_cache = camel_pop3_store_ref_cache (pop3_store);
+ pop3_engine = camel_pop3_store_ref_engine (pop3_store);
+
for (i = 0; i < pop3_folder->uids->len; i++) {
fi = pop3_folder->uids->pdata[i];
/* busy already? wait for that to finish first */
if (fi->cmd) {
- while (camel_pop3_engine_iterate (pop3_store->engine, fi->cmd, cancellable, NULL) > 0)
+ while (camel_pop3_engine_iterate (pop3_engine, fi->cmd, cancellable, NULL) > 0)
;
- camel_pop3_engine_command_free (pop3_store->engine, fi->cmd);
+ camel_pop3_engine_command_free (pop3_engine, fi->cmd);
fi->cmd = NULL;
}
if (fi->flags & CAMEL_MESSAGE_DELETED) {
fi->cmd = camel_pop3_engine_command_new (
- pop3_store->engine,
+ pop3_engine,
0, NULL, NULL,
cancellable, NULL,
"DELE %u\r\n", fi->id);
/* also remove from cache */
- if (pop3_store->cache && fi->uid)
- camel_data_cache_remove (pop3_store->cache, "cache", fi->uid, NULL);
+ if (pop3_cache != NULL && fi->uid)
+ camel_data_cache_remove (pop3_cache, "cache", fi->uid, NULL);
}
}
@@ -937,15 +972,18 @@ pop3_folder_synchronize_sync (CamelFolder *folder,
fi = pop3_folder->uids->pdata[i];
/* wait for delete commands to finish */
if (fi->cmd) {
- while (camel_pop3_engine_iterate (pop3_store->engine, fi->cmd, cancellable, NULL) > 0)
+ while (camel_pop3_engine_iterate (pop3_engine, fi->cmd, cancellable, NULL) > 0)
;
- camel_pop3_engine_command_free (pop3_store->engine, fi->cmd);
+ camel_pop3_engine_command_free (pop3_engine, fi->cmd);
fi->cmd = NULL;
}
camel_operation_progress (
cancellable, (i + 1) * 100 / pop3_folder->uids->len);
}
+ g_clear_object (&pop3_cache);
+ g_clear_object (&pop3_engine);
+
camel_operation_pop_message (cancellable);
return camel_pop3_store_expunge (pop3_store, cancellable, error);
@@ -1039,6 +1077,7 @@ pop3_get_message_time_from_cache (CamelFolder *folder,
{
CamelStore *parent_store;
CamelPOP3Store *pop3_store;
+ CamelDataCache *pop3_cache;
CamelStream *stream = NULL;
gchar buffer[1];
gboolean res = FALSE;
@@ -1050,9 +1089,10 @@ pop3_get_message_time_from_cache (CamelFolder *folder,
parent_store = camel_folder_get_parent_store (folder);
pop3_store = CAMEL_POP3_STORE (parent_store);
- g_return_val_if_fail (pop3_store->cache != NULL, FALSE);
+ pop3_cache = camel_pop3_store_ref_cache (pop3_store);
+ g_return_val_if_fail (pop3_cache != NULL, FALSE);
- if ((stream = camel_data_cache_get (pop3_store->cache, "cache", uid, NULL)) != NULL
+ if ((stream = camel_data_cache_get (pop3_cache, "cache", uid, NULL)) != NULL
&& camel_stream_read (stream, buffer, 1, NULL, NULL) == 1
&& buffer[0] == '#') {
CamelMimeMessage *message;
@@ -1077,9 +1117,9 @@ pop3_get_message_time_from_cache (CamelFolder *folder,
}
}
- if (stream) {
- g_object_unref (stream);
- }
+ g_clear_object (&stream);
+ g_clear_object (&pop3_cache);
+
return res;
}
@@ -1092,10 +1132,12 @@ camel_pop3_delete_old (CamelFolder *folder,
CamelStore *parent_store;
CamelPOP3Folder *pop3_folder;
CamelPOP3FolderInfo *fi;
- gint i;
+ CamelPOP3Engine *pop3_engine;
CamelPOP3Store *pop3_store;
+ CamelDataCache *pop3_cache;
CamelMimeMessage *message;
time_t temp, message_time;
+ gint i;
parent_store = camel_folder_get_parent_store (folder);
@@ -1109,6 +1151,9 @@ camel_pop3_delete_old (CamelFolder *folder,
pop3_folder = CAMEL_POP3_FOLDER (folder);
pop3_store = CAMEL_POP3_STORE (parent_store);
+ pop3_cache = camel_pop3_store_ref_cache (pop3_store);
+ pop3_engine = camel_pop3_store_ref_engine (pop3_store);
+
temp = time (&temp);
d (printf ("%s(%d): pop3_folder->uids->len=[%d]\n", __FILE__, __LINE__, pop3_folder->uids->len));
@@ -1117,11 +1162,11 @@ camel_pop3_delete_old (CamelFolder *folder,
fi = pop3_folder->uids->pdata[i];
if (fi->cmd) {
- while (camel_pop3_engine_iterate (pop3_store->engine, fi->cmd, cancellable, NULL) >
0) {
+ while (camel_pop3_engine_iterate (pop3_engine, fi->cmd, cancellable, NULL) > 0) {
; /* do nothing - iterating until end */
}
- camel_pop3_engine_command_free (pop3_store->engine, fi->cmd);
+ camel_pop3_engine_command_free (pop3_engine, fi->cmd);
fi->cmd = NULL;
}
@@ -1153,24 +1198,24 @@ camel_pop3_delete_old (CamelFolder *folder,
if (day_lag > days_to_delete) {
if (fi->cmd) {
- while (camel_pop3_engine_iterate (pop3_store->engine, fi->cmd,
cancellable, NULL) > 0) {
+ while (camel_pop3_engine_iterate (pop3_engine, fi->cmd, cancellable,
NULL) > 0) {
; /* do nothing - iterating until end */
}
- camel_pop3_engine_command_free (pop3_store->engine, fi->cmd);
+ camel_pop3_engine_command_free (pop3_engine, fi->cmd);
fi->cmd = NULL;
}
d (printf (
"%s(%d): Deleting old messages\n",
__FILE__, __LINE__));
fi->cmd = camel_pop3_engine_command_new (
- pop3_store->engine,
+ pop3_engine,
0, NULL, NULL,
cancellable, NULL,
"DELE %u\r\n", fi->id);
/* also remove from cache */
- if (pop3_store->cache && fi->uid) {
- camel_data_cache_remove (pop3_store->cache, "cache", fi->uid, NULL);
+ if (pop3_cache != NULL && fi->uid) {
+ camel_data_cache_remove (pop3_cache, "cache", fi->uid, NULL);
}
}
}
@@ -1180,14 +1225,17 @@ camel_pop3_delete_old (CamelFolder *folder,
fi = pop3_folder->uids->pdata[i];
/* wait for delete commands to finish */
if (fi->cmd) {
- while (camel_pop3_engine_iterate (pop3_store->engine, fi->cmd, cancellable, NULL) > 0)
+ while (camel_pop3_engine_iterate (pop3_engine, fi->cmd, cancellable, NULL) > 0)
;
- camel_pop3_engine_command_free (pop3_store->engine, fi->cmd);
+ camel_pop3_engine_command_free (pop3_engine, fi->cmd);
fi->cmd = NULL;
}
camel_operation_progress (
cancellable, (i + 1) * 100 / pop3_folder->uids->len);
}
+ g_clear_object (&pop3_cache);
+ g_clear_object (&pop3_engine);
+
return camel_pop3_store_expunge (pop3_store, cancellable, error);
}
diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c
index 92574f8..8890c47 100644
--- a/camel/providers/pop3/camel-pop3-store.c
+++ b/camel/providers/pop3/camel-pop3-store.c
@@ -45,6 +45,10 @@
#include <ws2tcpip.h>
#endif
+#define CAMEL_POP3_STORE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), CAMEL_TYPE_POP3_STORE, CamelPOP3StorePrivate))
+
/* Specified in RFC 1939 */
#define POP3_PORT 110
#define POP3S_PORT 995
@@ -52,6 +56,12 @@
/* defines the length of the server error message we can display in the error dialog */
#define POP3_ERROR_SIZE_LIMIT 60
+struct _CamelPOP3StorePrivate {
+ GMutex property_lock;
+ CamelDataCache *cache;
+ CamelPOP3Engine *engine;
+};
+
enum {
PROP_0,
PROP_CONNECTABLE,
@@ -102,6 +112,7 @@ connect_to_server (CamelService *service,
CamelNetworkSecurityMethod method;
CamelSettings *settings;
CamelStream *tcp_stream;
+ CamelPOP3Engine *pop3_engine = NULL;
CamelPOP3Command *pc;
gboolean disable_extensions;
gboolean success = TRUE;
@@ -140,7 +151,7 @@ connect_to_server (CamelService *service,
if (disable_extensions)
flags |= CAMEL_POP3_ENGINE_DISABLE_EXTENSIONS;
- if (!(store->engine = camel_pop3_engine_new (tcp_stream, flags, cancellable, &local_error)) ||
+ if (!(pop3_engine = camel_pop3_engine_new (tcp_stream, flags, cancellable, &local_error)) ||
local_error != NULL) {
if (local_error)
g_propagate_error (error, local_error);
@@ -159,7 +170,7 @@ connect_to_server (CamelService *service,
goto exit;
}
- if (!(store->engine->capa & CAMEL_POP3_CAP_STLS)) {
+ if (!(pop3_engine->capa & CAMEL_POP3_CAP_STLS)) {
g_set_error (
error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
_("Failed to connect to POP server %s in secure mode: %s"),
@@ -168,18 +179,18 @@ connect_to_server (CamelService *service,
}
pc = camel_pop3_engine_command_new (
- store->engine, 0, NULL, NULL,
+ pop3_engine, 0, NULL, NULL,
cancellable, error, "STLS\r\n");
- while (camel_pop3_engine_iterate (store->engine, NULL, cancellable, NULL) > 0)
+ while (camel_pop3_engine_iterate (pop3_engine, NULL, cancellable, NULL) > 0)
;
ret = pc->state == CAMEL_POP3_COMMAND_OK;
- camel_pop3_engine_command_free (store->engine, pc);
+ camel_pop3_engine_command_free (pop3_engine, pc);
if (ret == FALSE) {
gchar *tmp;
- tmp = get_valid_utf8_error ((gchar *) store->engine->line);
+ tmp = get_valid_utf8_error ((gchar *) pop3_engine->line);
g_set_error (
error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
/* Translators: Last %s is an optional
@@ -206,7 +217,7 @@ connect_to_server (CamelService *service,
/* rfc2595, section 4 states that after a successful STLS
* command, the client MUST discard prior CAPA responses */
- if (!camel_pop3_engine_reget_capabilities (store->engine, cancellable, error))
+ if (!camel_pop3_engine_reget_capabilities (pop3_engine, cancellable, error))
goto exception;
goto exit;
@@ -217,23 +228,30 @@ stls_exception:
/* if (clean_quit) {
/ * try to disconnect cleanly * /
pc = camel_pop3_engine_command_new (
- store->engine, 0, NULL, NULL,
+ pop3_engine, 0, NULL, NULL,
cancellable, NULL, "QUIT\r\n");
- while (camel_pop3_engine_iterate (store->engine, NULL, cancellable, NULL) > 0)
+ while (camel_pop3_engine_iterate (pop3_engine, NULL, cancellable, NULL) > 0)
;
- camel_pop3_engine_command_free (store->engine, pc);
+ camel_pop3_engine_command_free (pop3_engine, pc);
}*/
- exception:
- g_object_unref (store->engine);
+exception:
g_object_unref (tcp_stream);
- store->engine = NULL;
+
+ g_clear_object (&pop3_engine);
success = FALSE;
exit:
g_free (host);
+ g_mutex_lock (&store->priv->property_lock);
+ if (pop3_engine != NULL)
+ store->priv->engine = g_object_ref (pop3_engine);
+ g_mutex_unlock (&store->priv->property_lock);
+
+ g_clear_object (&pop3_engine);
+
return success;
}
@@ -243,7 +261,8 @@ try_sasl (CamelPOP3Store *store,
GCancellable *cancellable,
GError **error)
{
- CamelPOP3Stream *stream = store->engine->stream;
+ CamelPOP3Engine *pop3_engine;
+ CamelPOP3Stream *pop3_stream;
CamelNetworkSettings *network_settings;
CamelAuthenticationResult result;
CamelSettings *settings;
@@ -264,6 +283,9 @@ try_sasl (CamelPOP3Store *store,
g_object_unref (settings);
+ pop3_engine = camel_pop3_store_ref_engine (store);
+ pop3_stream = pop3_engine->stream;
+
sasl = camel_sasl_new ("pop", mechanism, service);
if (sasl == NULL) {
g_set_error (
@@ -276,14 +298,14 @@ try_sasl (CamelPOP3Store *store,
string = g_strdup_printf ("AUTH %s\r\n", mechanism);
ret = camel_stream_write_string (
- CAMEL_STREAM (stream), string, cancellable, error);
+ CAMEL_STREAM (pop3_stream), string, cancellable, error);
g_free (string);
if (ret == -1)
goto ioerror;
while (1) {
- if (camel_pop3_stream_line (stream, &line, &len, cancellable, error) == -1)
+ if (camel_pop3_stream_line (pop3_stream, &line, &len, cancellable, error) == -1)
goto ioerror;
if (strncmp ((gchar *) line, "+OK", 3) == 0) {
@@ -303,8 +325,8 @@ try_sasl (CamelPOP3Store *store,
|| camel_sasl_get_authenticated (sasl)
|| (resp = (guchar *) camel_sasl_challenge_base64_sync (sasl, (const gchar *) line + 2,
cancellable, NULL)) == NULL) {
camel_stream_write_string (
- CAMEL_STREAM (stream), "*\r\n", cancellable, NULL);
- camel_pop3_stream_line (stream, &line, &len, cancellable, NULL);
+ CAMEL_STREAM (pop3_stream), "*\r\n", cancellable, NULL);
+ camel_pop3_stream_line (pop3_stream, &line, &len, cancellable, NULL);
g_set_error (
error, CAMEL_SERVICE_ERROR,
CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
@@ -316,7 +338,7 @@ try_sasl (CamelPOP3Store *store,
string = g_strdup_printf ("%s\r\n", resp);
ret = camel_stream_write_string (
- CAMEL_STREAM (stream), string, cancellable, error);
+ CAMEL_STREAM (pop3_stream), string, cancellable, error);
g_free (string);
g_free (resp);
@@ -339,6 +361,8 @@ exit:
g_free (host);
+ g_clear_object (&pop3_engine);
+
return result;
}
@@ -387,12 +411,17 @@ pop3_store_get_property (GObject *object,
static void
pop3_store_dispose (GObject *object)
{
- CamelPOP3Store *pop3_store = CAMEL_POP3_STORE (object);
+ CamelPOP3StorePrivate *priv;
+
+ priv = CAMEL_POP3_STORE_GET_PRIVATE (object);
/* Force disconnect so we dont have it run
* later, after we've cleaned up some stuff. */
camel_service_disconnect_sync (
- CAMEL_SERVICE (pop3_store), TRUE, NULL, NULL);
+ CAMEL_SERVICE (object), TRUE, NULL, NULL);
+
+ g_clear_object (&priv->cache);
+ g_clear_object (&priv->engine);
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (camel_pop3_store_parent_class)->dispose (object);
@@ -401,12 +430,11 @@ pop3_store_dispose (GObject *object)
static void
pop3_store_finalize (GObject *object)
{
- CamelPOP3Store *pop3_store = CAMEL_POP3_STORE (object);
+ CamelPOP3StorePrivate *priv;
+
+ priv = CAMEL_POP3_STORE_GET_PRIVATE (object);
- if (pop3_store->engine)
- g_object_unref (pop3_store->engine);
- if (pop3_store->cache)
- g_object_unref (pop3_store->cache);
+ g_mutex_clear (&priv->property_lock);
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (camel_pop3_store_parent_class)->finalize (object);
@@ -449,6 +477,7 @@ pop3_store_connect_sync (CamelService *service,
GError **error)
{
CamelPOP3Store *store = (CamelPOP3Store *) service;
+ CamelPOP3Engine *pop3_engine;
CamelSettings *settings;
CamelSession *session;
const gchar *user_data_dir;
@@ -474,16 +503,26 @@ pop3_store_connect_sync (CamelService *service,
goto exit;
}
- if (store->cache == NULL) {
- store->cache = camel_data_cache_new (user_data_dir, error);
- if (store->cache) {
+ g_mutex_lock (&store->priv->property_lock);
+
+ if (store->priv->cache == NULL) {
+ CamelDataCache *cache;
+
+ cache = camel_data_cache_new (user_data_dir, error);
+ if (cache != NULL) {
/* Ensure cache will never expire, otherwise
* it causes redownload of messages. */
- camel_data_cache_set_expire_age (store->cache, -1);
- camel_data_cache_set_expire_access (store->cache, -1);
+ camel_data_cache_set_expire_age (cache, -1);
+ camel_data_cache_set_expire_access (cache, -1);
+
+ store->priv->cache = g_object_ref (cache);
+
+ g_object_unref (cache);
}
}
+ g_mutex_unlock (&store->priv->property_lock);
+
success = connect_to_server (service, cancellable, error);
if (!success)
@@ -500,9 +539,11 @@ pop3_store_connect_sync (CamelService *service,
/* Now that we are in the TRANSACTION state,
* try regetting the capabilities */
- store->engine->state = CAMEL_POP3_ENGINE_TRANSACTION;
- if (!camel_pop3_engine_reget_capabilities (store->engine, cancellable, error))
+ pop3_engine = camel_pop3_store_ref_engine (store);
+ pop3_engine->state = CAMEL_POP3_ENGINE_TRANSACTION;
+ if (!camel_pop3_engine_reget_capabilities (pop3_engine, cancellable, error))
success = FALSE;
+ g_clear_object (&pop3_engine);
exit:
g_free (mechanism);
@@ -523,14 +564,19 @@ pop3_store_disconnect_sync (CamelService *service,
gboolean success;
if (clean) {
+ CamelPOP3Engine *pop3_engine;
CamelPOP3Command *pc;
+ pop3_engine = camel_pop3_store_ref_engine (store);
+
pc = camel_pop3_engine_command_new (
- store->engine, 0, NULL, NULL,
+ pop3_engine, 0, NULL, NULL,
cancellable, error, "QUIT\r\n");
- while (camel_pop3_engine_iterate (store->engine, NULL, cancellable, NULL) > 0)
+ while (camel_pop3_engine_iterate (pop3_engine, NULL, cancellable, NULL) > 0)
;
- camel_pop3_engine_command_free (store->engine, pc);
+ camel_pop3_engine_command_free (pop3_engine, pc);
+
+ g_clear_object (&pop3_engine);
}
/* Chain up to parent's disconnect() method. */
@@ -538,8 +584,9 @@ pop3_store_disconnect_sync (CamelService *service,
success = service_class->disconnect_sync (service, clean, cancellable, error);
- g_object_unref (store->engine);
- store->engine = NULL;
+ g_mutex_lock (&store->priv->property_lock);
+ g_clear_object (&store->priv->engine);
+ g_mutex_unlock (&store->priv->property_lock);
return success;
}
@@ -556,6 +603,7 @@ pop3_store_authenticate_sync (CamelService *service,
CamelSettings *settings;
CamelPOP3Command *pcu = NULL;
CamelPOP3Command *pcp = NULL;
+ CamelPOP3Engine *pop3_engine;
const gchar *password;
gchar *host;
gchar *user;
@@ -571,6 +619,8 @@ pop3_store_authenticate_sync (CamelService *service,
g_object_unref (settings);
+ pop3_engine = camel_pop3_store_ref_engine (store);
+
if (mechanism == NULL) {
if (password == NULL) {
g_set_error_literal (
@@ -583,13 +633,13 @@ pop3_store_authenticate_sync (CamelService *service,
/* pop engine will take care of pipelining ability */
pcu = camel_pop3_engine_command_new (
- store->engine, 0, NULL, NULL, cancellable, error,
+ pop3_engine, 0, NULL, NULL, cancellable, error,
"USER %s\r\n", user);
pcp = camel_pop3_engine_command_new (
- store->engine, 0, NULL, NULL, cancellable, error,
+ pop3_engine, 0, NULL, NULL, cancellable, error,
"PASS %s\r\n", password);
- } else if (strcmp (mechanism, "+APOP") == 0 && store->engine->apop) {
+ } else if (strcmp (mechanism, "+APOP") == 0 && pop3_engine->apop) {
gchar *secret, *md5asc, *d;
if (password == NULL) {
@@ -601,7 +651,7 @@ pop3_store_authenticate_sync (CamelService *service,
goto exit;
}
- d = store->engine->apop;
+ d = pop3_engine->apop;
while (*d != '\0') {
if (!isascii ((gint) * d)) {
@@ -622,20 +672,20 @@ pop3_store_authenticate_sync (CamelService *service,
}
secret = g_alloca (
- strlen (store->engine->apop) +
+ strlen (pop3_engine->apop) +
strlen (password) + 1);
- sprintf (secret, "%s%s", store->engine->apop, password);
+ sprintf (secret, "%s%s", pop3_engine->apop, password);
md5asc = g_compute_checksum_for_string (
G_CHECKSUM_MD5, secret, -1);
pcp = camel_pop3_engine_command_new (
- store->engine, 0, NULL, NULL, cancellable, error,
+ pop3_engine, 0, NULL, NULL, cancellable, error,
"APOP %s %s\r\n", user, md5asc);
g_free (md5asc);
} else {
GList *link;
- link = store->engine->auth;
+ link = pop3_engine->auth;
while (link != NULL) {
CamelServiceAuthType *auth = link->data;
@@ -656,7 +706,7 @@ pop3_store_authenticate_sync (CamelService *service,
goto exit;
}
- while ((status = camel_pop3_engine_iterate (store->engine, pcp, cancellable, error)) > 0)
+ while ((status = camel_pop3_engine_iterate (pop3_engine, pcp, cancellable, error)) > 0)
;
if (status == -1) {
@@ -671,7 +721,7 @@ pop3_store_authenticate_sync (CamelService *service,
/* Abort authentication if the server rejects the user
* name. Reprompting for a password won't do any good. */
- tmp = get_valid_utf8_error ((gchar *) store->engine->line);
+ tmp = get_valid_utf8_error ((gchar *) pop3_engine->line);
g_set_error (
error, CAMEL_SERVICE_ERROR,
CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
@@ -683,20 +733,23 @@ pop3_store_authenticate_sync (CamelService *service,
g_free (tmp);
result = CAMEL_AUTHENTICATION_ERROR;
- } else if (pcp->state != CAMEL_POP3_COMMAND_OK)
+ } else if (pcp->state != CAMEL_POP3_COMMAND_OK) {
result = CAMEL_AUTHENTICATION_REJECTED;
- else
+ } else {
result = CAMEL_AUTHENTICATION_ACCEPTED;
+ }
- camel_pop3_engine_command_free (store->engine, pcp);
+ camel_pop3_engine_command_free (pop3_engine, pcp);
if (pcu != NULL)
- camel_pop3_engine_command_free (store->engine, pcu);
+ camel_pop3_engine_command_free (pop3_engine, pcu);
exit:
g_free (host);
g_free (user);
+ g_clear_object (&pop3_engine);
+
return result;
}
@@ -721,8 +774,14 @@ pop3_store_query_auth_types_sync (CamelService *service,
}
if (connect_to_server (service, cancellable, error)) {
- types = g_list_concat (types, g_list_copy (store->engine->auth));
+ CamelPOP3Engine *pop3_engine;
+
+ pop3_engine = camel_pop3_store_ref_engine (store);
+
+ types = g_list_concat (types, g_list_copy (pop3_engine->auth));
pop3_store_disconnect_sync (service, TRUE, cancellable, NULL);
+
+ g_clear_object (&pop3_engine);
}
return types;
@@ -824,6 +883,8 @@ camel_pop3_store_class_init (CamelPOP3StoreClass *class)
CamelServiceClass *service_class;
CamelStoreClass *store_class;
+ g_type_class_add_private (class, sizeof (CamelPOP3StorePrivate));
+
object_class = G_OBJECT_CLASS (class);
object_class->set_property = pop3_store_set_property;
object_class->get_property = pop3_store_get_property;
@@ -867,11 +928,70 @@ camel_network_service_init (CamelNetworkServiceInterface *interface)
static void
camel_pop3_store_init (CamelPOP3Store *pop3_store)
{
+ pop3_store->priv = CAMEL_POP3_STORE_GET_PRIVATE (pop3_store);
+
+ g_mutex_init (&pop3_store->priv->property_lock);
+}
+
+/**
+ * camel_pop3_store_ref_cache:
+ * @store: a #CamelPOP3Store
+ *
+ * Returns the #CamelDataCache for @store.
+ *
+ * The returned #CamelDataCache is referenced for thread-safety and must be
+ * unreferenced with g_object_unref() when finished with it.
+ *
+ * Returns: a #CamelDataCache
+ **/
+CamelDataCache *
+camel_pop3_store_ref_cache (CamelPOP3Store *store)
+{
+ CamelDataCache *cache = NULL;
+
+ g_return_val_if_fail (CAMEL_IS_POP3_STORE (store), NULL);
+
+ g_mutex_lock (&store->priv->property_lock);
+
+ if (store->priv->cache != NULL)
+ cache = g_object_ref (store->priv->cache);
+
+ g_mutex_unlock (&store->priv->property_lock);
+
+ return cache;
+}
+
+/**
+ * camel_pop3_store_ref_engine:
+ * @store: a #CamelPOP3Store
+ *
+ * Returns the #CamelPOP3Engine for @store.
+ *
+ * The returned #CamelPOP3Engine is referenced for thread-safety and must be
+ * unreferenced with g_object_unref() when finished with it.
+ *
+ * Returns: a #CamelPOP3Store
+ **/
+CamelPOP3Engine *
+camel_pop3_store_ref_engine (CamelPOP3Store *store)
+{
+ CamelPOP3Engine *engine = NULL;
+
+ g_return_val_if_fail (CAMEL_IS_POP3_STORE (store), NULL);
+
+ g_mutex_lock (&store->priv->property_lock);
+
+ if (store->priv->engine != NULL)
+ engine = g_object_ref (store->priv->engine);
+
+ g_mutex_unlock (&store->priv->property_lock);
+
+ return engine;
}
/**
* camel_pop3_store_expunge:
- * @store: the store
+ * @store: a #CamelPOP3Store
* @error: return location for a #GError, or %NULL
* @cancellable: optional #GCancellable object, or %NULL
*
@@ -885,6 +1005,7 @@ camel_pop3_store_expunge (CamelPOP3Store *store,
GError **error)
{
CamelPOP3Command *pc;
+ CamelPOP3Engine *pop3_engine;
CamelServiceConnectionStatus status;
status = camel_service_get_connection_status (CAMEL_SERVICE (store));
@@ -897,13 +1018,17 @@ camel_pop3_store_expunge (CamelPOP3Store *store,
return FALSE;
}
+ pop3_engine = camel_pop3_store_ref_engine (store);
+
pc = camel_pop3_engine_command_new (
- store->engine, 0, NULL, NULL, cancellable, error, "QUIT\r\n");
+ pop3_engine, 0, NULL, NULL, cancellable, error, "QUIT\r\n");
- while (camel_pop3_engine_iterate (store->engine, NULL, cancellable, NULL) > 0)
+ while (camel_pop3_engine_iterate (pop3_engine, NULL, cancellable, NULL) > 0)
;
- camel_pop3_engine_command_free (store->engine, pc);
+ camel_pop3_engine_command_free (pop3_engine, pc);
+
+ g_clear_object (&pop3_engine);
return TRUE;
}
diff --git a/camel/providers/pop3/camel-pop3-store.h b/camel/providers/pop3/camel-pop3-store.h
index 77630a1..07776b6 100644
--- a/camel/providers/pop3/camel-pop3-store.h
+++ b/camel/providers/pop3/camel-pop3-store.h
@@ -58,9 +58,6 @@ typedef struct _CamelPOP3StorePrivate CamelPOP3StorePrivate;
struct _CamelPOP3Store {
CamelStore parent;
CamelPOP3StorePrivate *priv;
-
- CamelPOP3Engine *engine; /* pop processing engine */
- CamelDataCache *cache;
};
struct _CamelPOP3StoreClass {
@@ -68,6 +65,10 @@ struct _CamelPOP3StoreClass {
};
GType camel_pop3_store_get_type (void);
+CamelDataCache *
+ camel_pop3_store_ref_cache (CamelPOP3Store *store);
+CamelPOP3Engine *
+ camel_pop3_store_ref_engine (CamelPOP3Store *store);
gboolean camel_pop3_store_expunge (CamelPOP3Store *store,
GCancellable *cancellable,
GError **error);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]