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:
Not Zed
2003-09-22 18:48:34 +00:00
committed by Michael Zucci
parent 5d47e3740b
commit 6abd6e01b3
11 changed files with 316 additions and 204 deletions

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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 */

View File

@ -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);

View File

@ -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);

View File

@ -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))

View File

@ -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:

View File

@ -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

View File

@ -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);

View File

@ -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 }
};