dovecot-2.0: dsync: Queue local msg-get requests instead of asse...

dovecot at dovecot.org dovecot at dovecot.org
Wed Jul 21 17:20:04 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/e3519ec18f03
changeset: 11880:e3519ec18f03
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Jul 21 13:33:35 2010 +0100
description:
dsync: Queue local msg-get requests instead of assert-crashing.

diffstat:

 src/dsync/dsync-worker-local.c |  80 +++++++++++++++++++++++++++++++--------
 1 files changed, 63 insertions(+), 17 deletions(-)

diffs (172 lines):

diff -r 4fb7e5327efc -r e3519ec18f03 src/dsync/dsync-worker-local.c
--- a/src/dsync/dsync-worker-local.c	Wed Jul 21 00:15:34 2010 +0100
+++ b/src/dsync/dsync-worker-local.c	Wed Jul 21 13:33:35 2010 +0100
@@ -57,6 +57,7 @@
 
 	unsigned int deleted_mailbox:1;
 };
+
 struct local_dsync_dir_change {
 	mailbox_guid_t name_sha1;
 	struct mailbox_list *list;
@@ -69,6 +70,13 @@
 	unsigned int deleted_dir:1;
 };
 
+struct local_dsync_worker_msg_get {
+	mailbox_guid_t mailbox;
+	uint32_t uid;
+	dsync_worker_msg_callback_t *callback;
+	void *context;
+};
+
 struct local_dsync_worker {
 	struct dsync_worker worker;
 	struct mail_user *user;
@@ -91,6 +99,7 @@
 
 	mailbox_guid_t get_mailbox;
 	struct mail *get_mail;
+	ARRAY_DEFINE(msg_get_queue, struct local_dsync_worker_msg_get);
 
 	struct io *save_io;
 	struct mail_save_context *save_ctx;
@@ -110,6 +119,9 @@
 
 static void local_worker_mailbox_close(struct local_dsync_worker *worker);
 static void local_worker_msg_box_close(struct local_dsync_worker *worker);
+static void
+local_worker_msg_get_next(struct local_dsync_worker *worker,
+			  const struct local_dsync_worker_msg_get *get);
 
 static int mailbox_guid_cmp(const void *p1, const void *p2)
 {
@@ -187,6 +199,7 @@
 		hash_table_create(default_pool, pool, 0,
 				  mailbox_guid_hash, mailbox_guid_cmp);
 	i_array_init(&worker->saved_uids, 128);
+	i_array_init(&worker->msg_get_queue, 32);
 	return &worker->worker;
 }
 
@@ -204,6 +217,7 @@
 		hash_table_destroy(&worker->mailbox_changes_hash);
 	if (worker->dir_changes_hash != NULL)
 		hash_table_destroy(&worker->dir_changes_hash);
+	array_free(&worker->msg_get_queue);
 	array_free(&worker->saved_uids);
 	pool_unref(&worker->pool);
 }
@@ -1626,8 +1640,20 @@
 
 static void local_worker_msg_get_done(struct local_dsync_worker *worker)
 {
+	const struct local_dsync_worker_msg_get *gets;
+	struct local_dsync_worker_msg_get get;
+	unsigned int count;
+
 	worker->reading_mail = FALSE;
-	dsync_worker_try_finish(worker);
+
+	gets = array_get(&worker->msg_get_queue, &count);
+	if (count == 0)
+		dsync_worker_try_finish(worker);
+	else {
+		get = gets[0];
+		array_delete(&worker->msg_get_queue, 0, 1);
+		local_worker_msg_get_next(worker, &get);
+	}
 }
 
 static void local_worker_msg_box_close(struct local_dsync_worker *worker)
@@ -1648,32 +1674,31 @@
 }
 
 static void
-local_worker_msg_get(struct dsync_worker *_worker,
-		     const mailbox_guid_t *mailbox, uint32_t uid,
-		     dsync_worker_msg_callback_t *callback, void *context)
+local_worker_msg_get_next(struct local_dsync_worker *worker,
+			  const struct local_dsync_worker_msg_get *get)
 {
-	struct local_dsync_worker *worker =
-		(struct local_dsync_worker *)_worker;
 	struct dsync_msg_static_data data;
 	struct mailbox_transaction_context *trans;
 	struct mailbox *box;
 
 	i_assert(!worker->reading_mail);
 
-	if (!dsync_guid_equals(&worker->get_mailbox, mailbox)) {
+	if (!dsync_guid_equals(&worker->get_mailbox, &get->mailbox)) {
 		local_worker_msg_box_close(worker);
-		if (local_mailbox_open(worker, mailbox, &box) < 0) {
-			callback(DSYNC_MSG_GET_RESULT_FAILED, NULL, context);
+		if (local_mailbox_open(worker, &get->mailbox, &box) < 0) {
+			get->callback(DSYNC_MSG_GET_RESULT_FAILED,
+				      NULL, get->context);
 			return;
 		}
-		worker->get_mailbox = *mailbox;
+		worker->get_mailbox = get->mailbox;
 
 		trans = mailbox_transaction_begin(box, 0);
 		worker->get_mail = mail_alloc(trans, 0, NULL);
 	}
 
-	if (!mail_set_uid(worker->get_mail, uid)) {
-		callback(DSYNC_MSG_GET_RESULT_EXPUNGED, NULL, context);
+	if (!mail_set_uid(worker->get_mail, get->uid)) {
+		get->callback(DSYNC_MSG_GET_RESULT_EXPUNGED,
+			      NULL, get->context);
 		return;
 	}
 
@@ -1682,21 +1707,42 @@
 			     &data.pop3_uidl) < 0 ||
 	    mail_get_received_date(worker->get_mail, &data.received_date) < 0 ||
 	    mail_get_stream(worker->get_mail, NULL, NULL, &data.input) < 0) {
-		if (worker->get_mail->expunged)
-			callback(DSYNC_MSG_GET_RESULT_EXPUNGED, NULL, context);
-		else
-			callback(DSYNC_MSG_GET_RESULT_FAILED, NULL, context);
+		get->callback(worker->get_mail->expunged ?
+			      DSYNC_MSG_GET_RESULT_EXPUNGED :
+			      DSYNC_MSG_GET_RESULT_FAILED, NULL, get->context);
 	} else {
 		worker->reading_mail = TRUE;
 		data.input = i_stream_create_limit(data.input, (uoff_t)-1);
 		i_stream_set_destroy_callback(data.input,
 					      local_worker_msg_get_done,
 					      worker);
-		callback(DSYNC_MSG_GET_RESULT_SUCCESS, &data, context);
+		get->callback(DSYNC_MSG_GET_RESULT_SUCCESS,
+			      &data, get->context);
 	}
 }
 
 static void
+local_worker_msg_get(struct dsync_worker *_worker,
+		     const mailbox_guid_t *mailbox, uint32_t uid,
+		     dsync_worker_msg_callback_t *callback, void *context)
+{
+	struct local_dsync_worker *worker =
+		(struct local_dsync_worker *)_worker;
+	struct local_dsync_worker_msg_get get;
+
+	memset(&get, 0, sizeof(get));
+	get.mailbox = *mailbox;
+	get.uid = uid;
+	get.callback = callback;
+	get.context = context;
+
+	if (!worker->reading_mail)
+		local_worker_msg_get_next(worker, &get);
+	else
+		array_append(&worker->msg_get_queue, &get, 1);
+}
+
+static void
 local_worker_finish(struct dsync_worker *_worker,
 		    dsync_worker_finish_callback_t *callback, void *context)
 {


More information about the dovecot-cvs mailing list