aboutsummaryrefslogtreecommitdiffstats
path: root/camel
diff options
context:
space:
mode:
authorNot Zed <NotZed@Ximian.com>2003-09-23 02:48:34 +0800
committerMichael Zucci <zucchi@src.gnome.org>2003-09-23 02:48:34 +0800
commit6abd6e01b3f220a127c780ffdf2ea9a80f028238 (patch)
treece0575d5ed607aaf29739724859318649cf8860c /camel
parent5d47e3740be4786532d412529a1d53f32ef4faf5 (diff)
downloadgsoc2013-evolution-6abd6e01b3f220a127c780ffdf2ea9a80f028238.tar.gz
gsoc2013-evolution-6abd6e01b3f220a127c780ffdf2ea9a80f028238.tar.zst
gsoc2013-evolution-6abd6e01b3f220a127c780ffdf2ea9a80f028238.zip
Added "offline_sync" option, which lets you synchronise all mail to local
2003-09-22 Not Zed <NotZed@Ximian.com> * providers/imap/camel-imap-provider.c: Added "offline_sync" option, which lets you synchronise all mail to local storage automagically. * camel-disco-folder.c (cdf_folder_changed): hook onto the folder changed single, for all new messages, check that they are online using another thread, if the offline_sync option has been enabled for this store. 2003-09-21 Not Zed <NotZed@Ximian.com> * camel-session.c (session_thread_destroy): call proper entry point for freeing the message. 2003-09-18 Not Zed <NotZed@Ximian.com> * camel-folder.c (filter_filter): register the filtering process for progress, and do progress of the filtering process. 2003-09-17 Not Zed <NotZed@Ximian.com> * camel.c (camel_init): init camel operation. * camel-operation.c (camel_operation_reset): removed, not used, not worth it. (camel_operation_mute): new method to stop all status updates permanently. (*): Changed to use thread specific data and a list rather than a hashtable. (cancel_thread): removed. (camel_operation_register): return the previously registered op. svn path=/trunk/; revision=22648
Diffstat (limited to 'camel')
-rw-r--r--camel/ChangeLog34
-rw-r--r--camel/camel-disco-folder.c77
-rw-r--r--camel/camel-folder.c7
-rw-r--r--camel/camel-object.h22
-rw-r--r--camel/camel-operation.c319
-rw-r--r--camel/camel-operation.h9
-rw-r--r--camel/camel-private.h2
-rw-r--r--camel/camel-session.c34
-rw-r--r--camel/camel-session.h10
-rw-r--r--camel/camel.c4
-rw-r--r--camel/providers/imap/camel-imap-provider.c2
11 files changed, 316 insertions, 204 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index f3a1ee8888..b22b8703b3 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,37 @@
+2003-09-22 Not Zed <NotZed@Ximian.com>
+
+ * providers/imap/camel-imap-provider.c: Added "offline_sync"
+ option, which lets you synchronise all mail to local storage
+ automagically.
+
+ * camel-disco-folder.c (cdf_folder_changed): hook onto the folder
+ changed single, for all new messages, check that they are online
+ using another thread, if the offline_sync option has been enabled
+ for this store.
+
+2003-09-21 Not Zed <NotZed@Ximian.com>
+
+ * camel-session.c (session_thread_destroy): call proper entry
+ point for freeing the message.
+
+2003-09-18 Not Zed <NotZed@Ximian.com>
+
+ * camel-folder.c (filter_filter): register the filtering process
+ for progress, and do progress of the filtering process.
+
+2003-09-17 Not Zed <NotZed@Ximian.com>
+
+ * camel.c (camel_init): init camel operation.
+
+ * camel-operation.c (camel_operation_reset): removed, not used,
+ not worth it.
+ (camel_operation_mute): new method to stop all status updates
+ permanently.
+ (*): Changed to use thread specific data and a list rather than a
+ hashtable.
+ (cancel_thread): removed.
+ (camel_operation_register): return the previously registered op.
+
2003-09-22 Jeffrey Stedfast <fejj@ximian.com>
* providers/nntp/camel-nntp-store.c (connect_to_server): Fix the
diff --git a/camel/camel-disco-folder.c b/camel/camel-disco-folder.c
index 3d3d9212bd..61e825020c 100644
--- a/camel/camel-disco-folder.c
+++ b/camel/camel-disco-folder.c
@@ -29,6 +29,8 @@
#include "camel-disco-store.h"
#include "camel-exception.h"
+#include "camel-session.h"
+
#define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS (o)))
#define CDF_CLASS(o) (CAMEL_DISCO_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS (o)))
@@ -72,6 +74,77 @@ camel_disco_folder_class_init (CamelDiscoFolderClass *camel_disco_folder_class)
camel_folder_class->transfer_messages_to = disco_transfer_messages_to;
}
+struct _cdf_sync_msg {
+ CamelSessionThreadMsg msg;
+
+ CamelFolder *folder;
+ CamelFolderChangeInfo *changes;
+};
+
+static void
+cdf_sync_offline(CamelSession *session, CamelSessionThreadMsg *mm)
+{
+ struct _cdf_sync_msg *m = (struct _cdf_sync_msg *)mm;
+ int i;
+
+ camel_operation_start(NULL, _("Downloading new messages for offline mode"));
+
+ if (m->changes) {
+ for (i=0;i<m->changes->uid_added->len;i++) {
+ int pc = i * 100 / m->changes->uid_added->len;
+
+ camel_operation_progress(NULL, pc);
+ camel_disco_folder_cache_message((CamelDiscoFolder *)m->folder,
+ m->changes->uid_added->pdata[i],
+ &mm->ex);
+ }
+ } else {
+ camel_disco_folder_prepare_for_offline((CamelDiscoFolder *)m->folder,
+ "(match-all)",
+ &mm->ex);
+ }
+
+ camel_operation_end(NULL);
+}
+
+static void
+cdf_sync_free(CamelSession *session, CamelSessionThreadMsg *mm)
+{
+ struct _cdf_sync_msg *m = (struct _cdf_sync_msg *)mm;
+
+ if (m->changes)
+ camel_folder_change_info_free(m->changes);
+ camel_object_unref(m->folder);
+}
+
+static CamelSessionThreadOps cdf_sync_ops = {
+ cdf_sync_offline,
+ cdf_sync_free,
+};
+
+static void
+cdf_folder_changed(CamelFolder *folder, CamelFolderChangeInfo *changes, void *dummy)
+{
+ if (changes->uid_added->len > 0
+ && camel_url_get_param(((CamelService *)folder->parent_store)->url, "offline_sync")) {
+ CamelSession *session = ((CamelService *)folder->parent_store)->session;
+ struct _cdf_sync_msg *m;
+
+ m = camel_session_thread_msg_new(session, &cdf_sync_ops, sizeof(*m));
+ m->changes = camel_folder_change_info_new();
+ camel_folder_change_info_cat(m->changes, changes);
+ m->folder = folder;
+ camel_object_ref(folder);
+ camel_session_thread_queue(session, &m->msg, 0);
+ }
+}
+
+static void
+camel_disco_folder_init(CamelDiscoFolder *folder)
+{
+ camel_object_hook_event(folder, "folder_changed", (CamelObjectEventHookFunc)cdf_folder_changed, NULL);
+}
+
CamelType
camel_disco_folder_get_type (void)
{
@@ -82,8 +155,8 @@ camel_disco_folder_get_type (void)
CAMEL_FOLDER_TYPE, "CamelDiscoFolder",
sizeof (CamelDiscoFolder),
sizeof (CamelDiscoFolderClass),
- (CamelObjectClassInitFunc) camel_disco_folder_class_init,
- NULL, NULL, NULL);
+ (CamelObjectClassInitFunc)camel_disco_folder_class_init, NULL,
+ (CamelObjectInitFunc)camel_disco_folder_init, NULL);
}
return camel_disco_folder_type;
diff --git a/camel/camel-folder.c b/camel/camel-folder.c
index 00106ca86a..79b7ecaf62 100644
--- a/camel/camel-folder.c
+++ b/camel/camel-folder.c
@@ -1568,7 +1568,7 @@ filter_filter(CamelSession *session, CamelSessionThreadMsg *msg)
char *source_url;
CamelException ex;
- /* FIXME: progress? (old code didn't have useful progress either) */
+ camel_operation_start(NULL, _("Filtering new message(s)"));
source_url = camel_service_get_url((CamelService *)m->folder->parent_store);
uri = camel_url_new(source_url, NULL);
@@ -1585,6 +1585,9 @@ filter_filter(CamelSession *session, CamelSessionThreadMsg *msg)
for (i=0;status == 0 && i<m->recents->len;i++) {
char *uid = m->recents->pdata[i];
+ int pc = 100 * i / m->recents->len;
+
+ camel_operation_progress(NULL, pc);
info = camel_folder_get_message_info(m->folder, uid);
if (info == NULL) {
@@ -1603,6 +1606,8 @@ filter_filter(CamelSession *session, CamelSessionThreadMsg *msg)
camel_exception_xfer(&m->ex, &ex);
g_free(source_url);
+
+ camel_operation_end(NULL);
}
static void
diff --git a/camel/camel-object.h b/camel/camel-object.h
index a13cf69325..33ecefbb0a 100644
--- a/camel/camel-object.h
+++ b/camel/camel-object.h
@@ -261,6 +261,28 @@ GPtrArray *camel_object_bag_list(CamelObjectBag *bag);
void camel_object_bag_remove(CamelObjectBag *bag, void *o);
void camel_object_bag_destroy(CamelObjectBag *bag);
+#define CAMEL_MAKE_CLASS(type, tname, parent, pname) \
+static CamelType type##_type; \
+static pname##Class * type##_parent_class; \
+ \
+CamelType \
+type##_get_type(void) \
+{ \
+ if (type##_type == 0) { \
+ type##_parent_class = (pname##Class *)parent##_get_type(); \
+ type##_type = camel_type_register( \
+ type##_parent_class, #tname "Class", \
+ sizeof(tname), \
+ sizeof(tname ## Class), \
+ (CamelObjectClassInitFunc) type##_class_init, \
+ NULL, \
+ (CamelObjectInitFunc) type##_init, \
+ (CamelObjectFinalizeFunc) type##_finalise); \
+ } \
+ \
+ return type##_type; \
+}
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/camel/camel-operation.c b/camel/camel-operation.c
index 3d5a9c8ada..03c0c77617 100644
--- a/camel/camel-operation.c
+++ b/camel/camel-operation.c
@@ -50,6 +50,9 @@ struct _status_stack {
};
struct _CamelOperation {
+ struct _CamelOperation *next;
+ struct _CamelOperation *prev;
+
pthread_t id; /* id of running thread */
guint32 flags; /* cancelled ? */
int blocked; /* cancellation blocked depth */
@@ -76,22 +79,35 @@ struct _CamelOperation {
/* Delay before a transient operation has any effect on the status */
#define CAMEL_OPERATION_TRANSIENT_DELAY (5)
-static pthread_mutex_t operation_active_lock = PTHREAD_MUTEX_INITIALIZER;
-#define CAMEL_ACTIVE_LOCK() pthread_mutex_lock(&operation_active_lock)
-#define CAMEL_ACTIVE_UNLOCK() pthread_mutex_unlock(&operation_active_lock)
+static pthread_mutex_t operation_lock = PTHREAD_MUTEX_INITIALIZER;
+#define LOCK() pthread_mutex_lock(&operation_lock)
+#define UNLOCK() pthread_mutex_unlock(&operation_lock)
static unsigned int stamp (void);
-
-static GHashTable *operation_active;
+static EDList operation_list = E_DLIST_INITIALISER(operation_list);
+static pthread_key_t operation_key;
typedef struct _CamelOperationMsg {
EMsg msg;
} CamelOperationMsg ;
/**
+ * camel_operation_init:
+ * @void:
+ *
+ * Init internal variables. Only call this once.
+ **/
+void
+camel_operation_init(void)
+{
+ pthread_key_create(&operation_key, NULL);
+}
+
+/**
* camel_operation_new:
- * @status: Callback for receiving status messages.
+ * @status: Callback for receiving status messages. This will always
+ * be called with an internal lock held.
* @status_data: User data.
*
* Create a new camel operation handle. Camel operation handles can
@@ -114,14 +130,33 @@ camel_operation_new (CamelOperationStatusFunc status, void *status_data)
cc->refcount = 1;
cc->status = status;
cc->status_data = status_data;
- cc->id = (pthread_t) ~0;
cc->cancel_port = e_msgport_new();
cc->cancel_fd = -1;
+
+ LOCK();
+ e_dlist_addtail(&operation_list, (EDListNode *)cc);
+ UNLOCK();
return cc;
}
/**
+ * camel_operation_mute:
+ * @cc:
+ *
+ * mutes a camel operation permanently. from this point on you will never
+ * receive operation updates, even if more are sent.
+ **/
+void
+camel_operation_mute(CamelOperation *cc)
+{
+ LOCK();
+ cc->status = NULL;
+ cc->status_data = NULL;
+ UNLOCK();
+}
+
+/**
* camel_operation_registered:
*
* Returns the registered operation, or %NULL if none registered.
@@ -129,47 +164,15 @@ camel_operation_new (CamelOperationStatusFunc status, void *status_data)
CamelOperation *
camel_operation_registered (void)
{
- CamelOperation *cc = NULL;
+ CamelOperation *cc = (CamelOperation *)pthread_getspecific(operation_key);
- CAMEL_ACTIVE_LOCK();
- if (operation_active != NULL
- && (cc = g_hash_table_lookup(operation_active, (void *)pthread_self()))) {
- g_assert(cc->refcount > 0);
- cc->refcount++;
- }
- CAMEL_ACTIVE_UNLOCK();
+ if (cc)
+ camel_operation_ref(cc);
return cc;
}
/**
- * camel_operation_reset:
- * @cc: operation context
- *
- * Resets an operation cancel state and message.
- **/
-void
-camel_operation_reset (CamelOperation *cc)
-{
- CamelOperationMsg *msg;
- GSList *n;
-
- while ((msg = (CamelOperationMsg *)e_msgport_get(cc->cancel_port)))
- g_free(msg);
-
- n = cc->status_stack;
- while (n) {
- g_free(n->data);
- n = n->next;
- }
- g_slist_free(cc->status_stack);
- cc->status_stack = NULL;
-
- cc->flags = 0;
- cc->blocked = 0;
-}
-
-/**
* camel_operation_ref:
* @cc: operation context
*
@@ -180,9 +183,9 @@ camel_operation_ref (CamelOperation *cc)
{
g_assert(cc->refcount > 0);
- CAMEL_ACTIVE_LOCK();
+ LOCK();
cc->refcount++;
- CAMEL_ACTIVE_UNLOCK();
+ UNLOCK();
}
/**
@@ -198,20 +201,17 @@ camel_operation_unref (CamelOperation *cc)
g_assert(cc->refcount > 0);
- CAMEL_ACTIVE_LOCK();
+ LOCK();
if (cc->refcount == 1) {
CamelOperationMsg *msg;
+ e_dlist_remove((EDListNode *)cc);
+
while ((msg = (CamelOperationMsg *)e_msgport_get(cc->cancel_port)))
g_free(msg);
e_msgport_destroy(cc->cancel_port);
- if (cc->id != (~0)) {
- g_warning("Unreffing operation status which was still registered: %p\n", cc);
- g_hash_table_remove(operation_active, (void *)cc->id);
- }
-
n = cc->status_stack;
while (n) {
g_warning("Camel operation status stack non empty: %s", (char *)n->data);
@@ -224,7 +224,7 @@ camel_operation_unref (CamelOperation *cc)
} else {
cc->refcount--;
}
- CAMEL_ACTIVE_UNLOCK();
+ UNLOCK();
}
/**
@@ -237,16 +237,14 @@ camel_operation_unref (CamelOperation *cc)
void
camel_operation_cancel_block (CamelOperation *cc)
{
- CAMEL_ACTIVE_LOCK();
- if (operation_active == NULL)
- operation_active = g_hash_table_new(NULL, NULL);
-
if (cc == NULL)
- cc = g_hash_table_lookup(operation_active, (void *)pthread_self());
+ cc = (CamelOperation *)pthread_getspecific(operation_key);
- if (cc)
+ if (cc) {
+ LOCK();
cc->blocked++;
- CAMEL_ACTIVE_UNLOCK();
+ UNLOCK();
+ }
}
/**
@@ -260,29 +258,13 @@ camel_operation_cancel_block (CamelOperation *cc)
void
camel_operation_cancel_unblock (CamelOperation *cc)
{
- CAMEL_ACTIVE_LOCK();
- if (operation_active == NULL)
- operation_active = g_hash_table_new(NULL, NULL);
-
if (cc == NULL)
- cc = g_hash_table_lookup(operation_active, (void *)pthread_self());
-
- if (cc)
- cc->blocked--;
- CAMEL_ACTIVE_UNLOCK();
-}
-
-static void
-cancel_thread(void *key, CamelOperation *cc, void *data)
-{
- CamelOperationMsg *msg;
+ cc = (CamelOperation *)pthread_getspecific(operation_key);
if (cc) {
- d(printf("cancelling thread %d\n", cc->id));
-
- cc->flags |= CAMEL_OPERATION_CANCELLED;
- msg = g_malloc0(sizeof(*msg));
- e_msgport_put(cc->cancel_port, (EMsg *)msg);
+ LOCK();
+ cc->blocked--;
+ UNLOCK();
}
}
@@ -298,11 +280,19 @@ camel_operation_cancel (CamelOperation *cc)
{
CamelOperationMsg *msg;
- CAMEL_ACTIVE_LOCK();
+ LOCK();
if (cc == NULL) {
- if (operation_active) {
- g_hash_table_foreach(operation_active, (GHFunc)cancel_thread, NULL);
+ CamelOperation *cn;
+
+ cc = (CamelOperation *)operation_list.head;
+ cn = cc->next;
+ while (cn) {
+ cc->flags |= CAMEL_OPERATION_CANCELLED;
+ msg = g_malloc0(sizeof(*msg));
+ e_msgport_put(cc->cancel_port, (EMsg *)msg);
+ cc = cn;
+ cn = cn->next;
}
} else if ((cc->flags & CAMEL_OPERATION_CANCELLED) == 0) {
d(printf("cancelling thread %d\n", cc->id));
@@ -312,7 +302,7 @@ camel_operation_cancel (CamelOperation *cc)
e_msgport_put(cc->cancel_port, (EMsg *)msg);
}
- CAMEL_ACTIVE_UNLOCK();
+ UNLOCK();
}
/**
@@ -320,75 +310,34 @@ camel_operation_cancel (CamelOperation *cc)
* @cc: operation context
*
* Register a thread or the main thread for cancellation through @cc.
- * If @cc is NULL, then a new cancellation is created for this thread,
- * but may only be cancelled from the same thread.
+ * If @cc is NULL, then a new cancellation is created for this thread.
*
* All calls to operation_register() should be matched with calls to
* operation_unregister(), or resources will be lost.
+ *
+ * Return Value: Returns @cc, or if NULL, the new operation.
+ *
**/
-void
+CamelOperation *
camel_operation_register (CamelOperation *cc)
{
- pthread_t id = pthread_self();
+ CamelOperation *oldcc = pthread_getspecific(operation_key);
- CAMEL_ACTIVE_LOCK();
+ pthread_setspecific(operation_key, cc);
- if (operation_active == NULL)
- operation_active = g_hash_table_new(NULL, NULL);
-
- if (cc == NULL) {
- cc = g_hash_table_lookup(operation_active, (void *)id);
- if (cc == NULL) {
- cc = camel_operation_new(NULL, NULL);
- }
- }
-
- if (cc->id == (~0)) {
- cc->id = id;
- g_hash_table_insert(operation_active, (void *)id, cc);
- } else {
- g_warning("Re-registering thread %lu for cancellation as thread %lu", cc->id, id);
- }
-
- d(printf("registering thread %ld for cancellation\n", id));
-
- CAMEL_ACTIVE_UNLOCK();
+ return oldcc;
}
/**
* camel_operation_unregister:
* @cc: operation context
*
- * Unregister a given operation from being cancelled. If @cc is NULL,
- * then the current thread is used.
+ * Unregister the current thread.
**/
void
camel_operation_unregister (CamelOperation *cc)
{
- CAMEL_ACTIVE_LOCK();
-
- if (operation_active == NULL)
- operation_active = g_hash_table_new(NULL, NULL);
-
- if (cc == NULL) {
- cc = g_hash_table_lookup(operation_active, (void *)pthread_self());
- if (cc == NULL) {
- g_warning("Trying to unregister a thread that was never registered for cancellation");
- }
- }
-
- if (cc) {
- if (cc->id != (~0)) {
- g_hash_table_remove(operation_active, (void *)cc->id);
- cc->id = ~0;
- } else {
- g_warning("Unregistering an operation that was already unregistered");
- }
- }
-
- CAMEL_ACTIVE_UNLOCK();
-
- d({if (cc) printf("unregistering thread %d for cancellation\n", cc->id);});
+ pthread_setspecific(operation_key, NULL);
}
/**
@@ -408,10 +357,10 @@ camel_operation_cancel_check (CamelOperation *cc)
d(printf("checking for cancel in thread %d\n", pthread_self()));
- CAMEL_ACTIVE_LOCK();
+ if (cc == NULL)
+ cc = (CamelOperation *)pthread_getspecific(operation_key);
- if (cc == NULL && operation_active)
- cc = g_hash_table_lookup(operation_active, (void *)pthread_self());
+ LOCK();
if (cc == NULL || cc->blocked > 0) {
d(printf("ahah! cancellation is blocked\n"));
@@ -427,7 +376,7 @@ camel_operation_cancel_check (CamelOperation *cc)
} else
cancelled = FALSE;
- CAMEL_ACTIVE_UNLOCK();
+ UNLOCK();
return cancelled;
}
@@ -445,22 +394,18 @@ camel_operation_cancel_check (CamelOperation *cc)
int
camel_operation_cancel_fd (CamelOperation *cc)
{
- CAMEL_ACTIVE_LOCK();
-
- if (cc == NULL && operation_active) {
- cc = g_hash_table_lookup(operation_active, (void *)pthread_self());
- }
+ if (cc == NULL)
+ cc = (CamelOperation *)pthread_getspecific(operation_key);
- if (cc == NULL
- || cc->blocked) {
- CAMEL_ACTIVE_UNLOCK();
+ if (cc == NULL || cc->blocked)
return -1;
- }
+
+ LOCK();
if (cc->cancel_fd == -1)
cc->cancel_fd = e_msgport_fd(cc->cancel_port);
- CAMEL_ACTIVE_UNLOCK();
+ UNLOCK();
return cc->cancel_fd;
}
@@ -479,22 +424,18 @@ camel_operation_cancel_fd (CamelOperation *cc)
PRFileDesc *
camel_operation_cancel_prfd (CamelOperation *cc)
{
- CAMEL_ACTIVE_LOCK();
-
- if (cc == NULL && operation_active) {
- cc = g_hash_table_lookup(operation_active, (void *)pthread_self());
- }
+ if (cc == NULL)
+ cc = (CamelOperation *)pthread_getspecific(operation_key);
- if (cc == NULL
- || cc->blocked) {
- CAMEL_ACTIVE_UNLOCK();
+ if (cc == NULL || cc->blocked)
return NULL;
- }
+
+ LOCK();
if (cc->cancel_prfd == NULL)
cc->cancel_prfd = e_msgport_prfd(cc->cancel_port);
- CAMEL_ACTIVE_UNLOCK();
+ UNLOCK();
return cc->cancel_prfd;
}
@@ -516,16 +457,16 @@ camel_operation_start (CamelOperation *cc, char *what, ...)
char *msg;
struct _status_stack *s;
- if (operation_active == NULL)
- return;
-
- CAMEL_ACTIVE_LOCK();
+ if (cc == NULL)
+ cc = (CamelOperation *)pthread_getspecific(operation_key);
if (cc == NULL)
- cc = g_hash_table_lookup(operation_active, (void *)pthread_self());
+ return;
- if (cc == NULL || cc->status == NULL) {
- CAMEL_ACTIVE_UNLOCK();
+ LOCK();
+
+ if (cc->status == NULL) {
+ UNLOCK();
return;
}
@@ -539,7 +480,7 @@ camel_operation_start (CamelOperation *cc, char *what, ...)
cc->lastreport = s;
cc->status_stack = g_slist_prepend(cc->status_stack, s);
- CAMEL_ACTIVE_UNLOCK();
+ UNLOCK();
cc->status(cc, msg, CAMEL_OPERATION_START, cc->status_data);
@@ -563,18 +504,13 @@ camel_operation_start_transient (CamelOperation *cc, char *what, ...)
char *msg;
struct _status_stack *s;
- if (operation_active == NULL)
- return;
-
- CAMEL_ACTIVE_LOCK();
-
if (cc == NULL)
- cc = g_hash_table_lookup(operation_active, (void *)pthread_self());
+ cc = (CamelOperation *)pthread_getspecific(operation_key);
- if (cc == NULL || cc->status == NULL) {
- CAMEL_ACTIVE_UNLOCK();
+ if (cc == NULL || cc->status == NULL)
return;
- }
+
+ LOCK();
va_start(ap, what);
msg = g_strdup_vprintf(what, ap);
@@ -587,7 +523,7 @@ camel_operation_start_transient (CamelOperation *cc, char *what, ...)
cc->status_stack = g_slist_prepend(cc->status_stack, s);
d(printf("start '%s'\n", msg, pc));
- CAMEL_ACTIVE_UNLOCK();
+ UNLOCK();
/* we dont report it yet */
/*cc->status(cc, msg, CAMEL_OPERATION_START, cc->status_data);*/
@@ -621,16 +557,16 @@ camel_operation_progress (CamelOperation *cc, int pc)
struct _status_stack *s;
char *msg = NULL;
- if (operation_active == NULL)
- return;
-
- CAMEL_ACTIVE_LOCK();
+ if (cc == NULL)
+ cc = (CamelOperation *)pthread_getspecific(operation_key);
if (cc == NULL)
- cc = g_hash_table_lookup(operation_active, (void *)pthread_self());
+ return;
- if (cc == NULL || cc->status == NULL || cc->status_stack == NULL) {
- CAMEL_ACTIVE_UNLOCK();
+ LOCK();
+
+ if (cc->status == NULL || cc->status_stack == NULL) {
+ UNLOCK();
return;
}
@@ -656,7 +592,7 @@ camel_operation_progress (CamelOperation *cc, int pc)
msg = g_strdup(s->msg);
}
- CAMEL_ACTIVE_UNLOCK();
+ UNLOCK();
if (cc) {
cc->status(cc, msg, pc, cc->status_data);
@@ -664,7 +600,6 @@ camel_operation_progress (CamelOperation *cc, int pc)
}
}
-
/**
* camel_operation_progress_count:
* @cc: operation context
@@ -694,16 +629,16 @@ camel_operation_end (CamelOperation *cc)
char *msg = NULL;
int pc = 0;
- if (operation_active == NULL)
- return;
-
- CAMEL_ACTIVE_LOCK();
+ if (cc == NULL)
+ cc = (CamelOperation *)pthread_getspecific(operation_key);
if (cc == NULL)
- cc = g_hash_table_lookup(operation_active, (void *)pthread_self());
+ return;
+
+ LOCK();
- if (cc == NULL || cc->status == NULL || cc->status_stack == NULL) {
- CAMEL_ACTIVE_UNLOCK();
+ if (cc->status == NULL || cc->status_stack == NULL) {
+ UNLOCK();
return;
}
@@ -743,7 +678,7 @@ camel_operation_end (CamelOperation *cc)
g_free(s);
cc->status_stack = g_slist_remove_link(cc->status_stack, cc->status_stack);
- CAMEL_ACTIVE_UNLOCK();
+ UNLOCK();
if (msg) {
cc->status(cc, msg, pc, cc->status_data);
diff --git a/camel/camel-operation.h b/camel/camel-operation.h
index 367d916b67..62e29dc2ac 100644
--- a/camel/camel-operation.h
+++ b/camel/camel-operation.h
@@ -39,14 +39,17 @@ enum _camel_operation_status_t {
};
/* main thread functions */
+void camel_operation_init(void);
+
CamelOperation *camel_operation_new(CamelOperationStatusFunc status, void *status_data);
+void camel_operation_mute(CamelOperation *cc);
void camel_operation_ref(CamelOperation *cc);
void camel_operation_unref(CamelOperation *cc);
-void camel_operation_reset(CamelOperation *cc);
void camel_operation_cancel(CamelOperation *cc);
/* subthread functions */
-void camel_operation_register(CamelOperation *cc);
-void camel_operation_unregister(CamelOperation *cc);
+CamelOperation *camel_operation_register(CamelOperation *cc);
+void camel_operation_unregister (CamelOperation *cc);
+
/* called internally by camel, for the current thread */
void camel_operation_cancel_block(CamelOperation *cc);
void camel_operation_cancel_unblock(CamelOperation *cc);
diff --git a/camel/camel-private.h b/camel/camel-private.h
index c9ce24fd01..87aeeff4b7 100644
--- a/camel/camel-private.h
+++ b/camel/camel-private.h
@@ -83,6 +83,8 @@ struct _CamelSessionPrivate {
int thread_id;
GHashTable *thread_active;
EThread *thread_queue;
+
+ GHashTable *thread_msg_op;
};
#define CAMEL_SESSION_LOCK(f, l) (g_mutex_lock(((CamelSession *)f)->priv->l))
diff --git a/camel/camel-session.c b/camel/camel-session.c
index d21ccc3ae8..9d5fd7ea9f 100644
--- a/camel/camel-session.c
+++ b/camel/camel-session.c
@@ -67,6 +67,7 @@ static void *session_thread_msg_new(CamelSession *session, CamelSessionThreadOps
static void session_thread_msg_free(CamelSession *session, CamelSessionThreadMsg *msg);
static int session_thread_queue(CamelSession *session, CamelSessionThreadMsg *msg, int flags);
static void session_thread_wait(CamelSession *session, int id);
+static void session_thread_status(CamelSession *session, CamelSessionThreadMsg *msg, const char *text, int pc);
/* The vfolder provider is always available */
static CamelProvider vee_provider = {
@@ -120,7 +121,7 @@ camel_session_finalise (CamelObject *o)
g_hash_table_destroy(session->priv->thread_active);
if (session->priv->thread_queue)
e_thread_destroy(session->priv->thread_queue);
-
+
g_free(session->storage_path);
g_hash_table_foreach_remove (session->providers,
camel_session_destroy_provider, NULL);
@@ -146,6 +147,7 @@ camel_session_class_init (CamelSessionClass *camel_session_class)
camel_session_class->thread_msg_free = session_thread_msg_free;
camel_session_class->thread_queue = session_thread_queue;
camel_session_class->thread_wait = session_thread_wait;
+ camel_session_class->thread_status = session_thread_status;
vee_provider.object_types[CAMEL_PROVIDER_STORE] = camel_vee_store_get_type ();
vee_provider.url_hash = camel_url_hash;
@@ -688,6 +690,14 @@ camel_session_get_filter_driver (CamelSession *session,
return CS_CLASS (session)->get_filter_driver (session, type, ex);
}
+static void
+cs_thread_status(CamelOperation *op, const char *what, int pc, void *data)
+{
+ CamelSessionThreadMsg *m = data;
+
+ CS_CLASS(m->session)->thread_status(m->session, m, what, pc);
+}
+
static void *session_thread_msg_new(CamelSession *session, CamelSessionThreadOps *ops, unsigned int size)
{
CamelSessionThreadMsg *m;
@@ -696,7 +706,10 @@ static void *session_thread_msg_new(CamelSession *session, CamelSessionThreadOps
m = g_malloc0(size);
m->ops = ops;
-
+ m->session = session;
+ camel_object_ref(session);
+ m->op = camel_operation_new(cs_thread_status, m);
+ camel_exception_init(&m->ex);
CAMEL_SESSION_LOCK(session, thread_lock);
m->id = session->priv->thread_id++;
g_hash_table_insert(session->priv->thread_active, GINT_TO_POINTER(m->id), m);
@@ -719,20 +732,29 @@ static void session_thread_msg_free(CamelSession *session, CamelSessionThreadMsg
if (msg->ops->free)
msg->ops->free(session, msg);
+ if (msg->op)
+ camel_operation_unref(msg->op);
+ camel_exception_clear(&msg->ex);
+ camel_object_unref(msg->session);
g_free(msg);
}
static void session_thread_destroy(EThread *thread, CamelSessionThreadMsg *msg, CamelSession *session)
{
d(printf("destroy message %p session %p\n", msg, session));
- session_thread_msg_free(session, msg);
+ camel_session_thread_msg_free(session, msg);
}
static void session_thread_received(EThread *thread, CamelSessionThreadMsg *msg, CamelSession *session)
{
d(printf("receive message %p session %p\n", msg, session));
- if (msg->ops->receive)
+ if (msg->ops->receive) {
+ CamelOperation *oldop;
+
+ oldop = camel_operation_register(msg->op);
msg->ops->receive(session, msg);
+ camel_operation_register(oldop);
+ }
}
static int session_thread_queue(CamelSession *session, CamelSessionThreadMsg *msg, int flags)
@@ -768,6 +790,10 @@ static void session_thread_wait(CamelSession *session, int id)
} while (wait);
}
+static void session_thread_status(CamelSession *session, CamelSessionThreadMsg *msg, const char *text, int pc)
+{
+}
+
/**
* camel_session_thread_msg_new:
* @session:
diff --git a/camel/camel-session.h b/camel/camel-session.h
index 8dbdfb9d3f..b9416ddc8d 100644
--- a/camel/camel-session.h
+++ b/camel/camel-session.h
@@ -110,6 +110,7 @@ typedef struct {
void (*thread_msg_free)(CamelSession *session, CamelSessionThreadMsg *msg);
int (*thread_queue)(CamelSession *session, CamelSessionThreadMsg *msg, int flags);
void (*thread_wait)(CamelSession *session, int id);
+ void (*thread_status)(CamelSession *session, CamelSessionThreadMsg *msg, const char *text, int pc);
#endif
} CamelSessionClass;
@@ -184,8 +185,14 @@ struct _CamelSessionThreadOps {
struct _CamelSessionThreadMsg {
EMsg msg;
- CamelSessionThreadOps *ops;
int id;
+
+ CamelException ex;
+ CamelSessionThreadOps *ops;
+ struct _CamelOperation *op;
+ CamelSession *session;
+
+ void *data; /* free for implementation to define, not used by camel, do not use in client code */
/* user fields follow */
};
@@ -193,6 +200,7 @@ void *camel_session_thread_msg_new(CamelSession *session, CamelSessionThreadOps
void camel_session_thread_msg_free(CamelSession *session, CamelSessionThreadMsg *msg);
int camel_session_thread_queue(CamelSession *session, CamelSessionThreadMsg *msg, int flags);
void camel_session_thread_wait(CamelSession *session, int id);
+
#endif
#ifdef __cplusplus
diff --git a/camel/camel.c b/camel/camel.c
index bebc1bbecc..ae99da74c2 100644
--- a/camel/camel.c
+++ b/camel/camel.c
@@ -64,6 +64,7 @@ camel_init (const char *configdir, gboolean nss_init)
{
CamelCertDB *certdb;
char *path;
+ void camel_operation_init(void);
if (getenv ("CAMEL_VERBOSE_DEBUG"))
camel_verbose_debug = TRUE;
@@ -72,7 +73,8 @@ camel_init (const char *configdir, gboolean nss_init)
camel_object_get_type ();
camel_mime_utils_init ();
-
+ camel_operation_init();
+
#ifdef HAVE_NSS
if (nss_init) {
PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 10);
diff --git a/camel/providers/imap/camel-imap-provider.c b/camel/providers/imap/camel-imap-provider.c
index 44e41a3d30..b7e92a7f73 100644
--- a/camel/providers/imap/camel-imap-provider.c
+++ b/camel/providers/imap/camel-imap-provider.c
@@ -55,6 +55,8 @@ CamelProviderConfEntry imap_conf_entries[] = {
{ CAMEL_PROVIDER_CONF_SECTION_END },
{ CAMEL_PROVIDER_CONF_CHECKBOX, "filter", NULL,
N_("Apply filters to new messages in INBOX on this server"), "0" },
+ { CAMEL_PROVIDER_CONF_CHECKBOX, "offline_sync", NULL,
+ N_("Automatically synchronize remote mail locally"), "0" },
{ CAMEL_PROVIDER_CONF_END }
};