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
This commit is contained in:
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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,13 +130,32 @@ 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:
|
||||
*
|
||||
@ -129,46 +164,14 @@ 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)
|
||||
cc = (CamelOperation *)pthread_getspecific(operation_key);
|
||||
|
||||
if (cc == NULL && operation_active) {
|
||||
cc = g_hash_table_lookup(operation_active, (void *)pthread_self());
|
||||
}
|
||||
|
||||
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)
|
||||
cc = (CamelOperation *)pthread_getspecific(operation_key);
|
||||
|
||||
if (cc == NULL && operation_active) {
|
||||
cc = g_hash_table_lookup(operation_active, (void *)pthread_self());
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (cc == NULL || cc->status == NULL || cc->status_stack == NULL) {
|
||||
CAMEL_ACTIVE_UNLOCK();
|
||||
LOCK();
|
||||
|
||||
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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 }
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user