[dovecot-cvs] dovecot/src/pop3 client.c, 1.40, 1.41 client.h, 1.8, 1.9 commands.c, 1.32, 1.33

cras at dovecot.org cras at dovecot.org
Sun Oct 10 19:25:09 EEST 2004


Update of /var/lib/cvs/dovecot/src/pop3
In directory talvi:/tmp/cvs-serv10857

Modified Files:
	client.c client.h commands.c 
Log Message:
Use only a single transaction for the whole duration of pop3 session. Avoids
constant locking/unlocking the indexes.



Index: client.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/pop3/client.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- client.c	10 Oct 2004 14:32:33 -0000	1.40
+++ client.c	10 Oct 2004 16:25:06 -0000	1.41
@@ -1,6 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "common.h"
+#include "buffer.h"
 #include "ioloop.h"
 #include "network.h"
 #include "istream.h"
@@ -54,43 +55,33 @@
         struct mailbox_transaction_context *t;
 	struct mail_search_context *ctx;
 	struct mail *mail;
-	struct mailbox_status status;
+	buffer_t *message_sizes_buf;
 	int i, failed;
 
+	message_sizes_buf = buffer_create_dynamic(default_pool, 512);
+
 	memset(&search_arg, 0, sizeof(search_arg));
 	search_arg.type = SEARCH_ALL;
 
 	for (i = 0; i < 2; i++) {
 		if (sync_mailbox(client->mailbox) < 0) {
 			client_send_storage_error(client);
-			return FALSE;
-		}
-		if (mailbox_get_status(client->mailbox, STATUS_MESSAGES,
-				       &status) < 0) {
-			client_send_storage_error(client);
-			return FALSE;
+			break;
 		}
 
-		client->last_seen = 0;
-		client->messages_count = status.messages;
-		client->total_size = 0;
-		client->deleted_size = 0;
-
-		if (client->messages_count == 0)
-			return TRUE;
-
-		i_free(client->message_sizes);
-		client->message_sizes = i_new(uoff_t, client->messages_count);
-
 		t = mailbox_transaction_begin(client->mailbox, FALSE);
 		ctx = mailbox_search_init(t, NULL, &search_arg, NULL,
 					  MAIL_FETCH_VIRTUAL_SIZE, NULL);
 		if (ctx == NULL) {
 			client_send_storage_error(client);
-                        mailbox_transaction_rollback(t);
-			return FALSE;
+			mailbox_transaction_rollback(t);
+			break;
 		}
 
+		client->last_seen = 0;
+		client->total_size = 0;
+		buffer_set_used_size(message_sizes_buf, 0);
+
 		failed = FALSE;
 		while ((mail = mailbox_search_next(ctx)) != NULL) {
 			uoff_t size = mail->get_virtual_size(mail);
@@ -107,18 +98,21 @@
 				client->last_seen = mail->seq;
                         client->total_size += size;
 
-			i_assert(mail->seq <= client->messages_count);
-			client->message_sizes[mail->seq-1] = size;
+			buffer_append(message_sizes_buf, &size, sizeof(size));
 		}
+		client->messages_count =
+			message_sizes_buf->used / sizeof(uoff_t);
 
 		if (mailbox_search_deinit(ctx) < 0) {
 			client_send_storage_error(client);
-                        mailbox_transaction_rollback(t);
-			return FALSE;
+			mailbox_transaction_rollback(t);
+			break;
 		}
 
 		if (!failed) {
-			mailbox_transaction_commit(t, 0);
+			client->trans = t;
+			client->message_sizes =
+				buffer_free_without_data(message_sizes_buf);
 			return TRUE;
 		}
 
@@ -126,67 +120,12 @@
 		mailbox_transaction_rollback(t);
 	}
 
-	client_send_line(client, "-ERR [IN-USE] Couldn't sync mailbox.");
+	if (i == 2)
+		client_send_line(client, "-ERR [IN-USE] Couldn't sync mailbox.");
+	buffer_free(message_sizes_buf);
 	return FALSE;
 }
 
-int client_update_mailbox(struct client *client, struct mailbox *box,
-			  int delete_mails)
-{
-	struct mail_search_arg search_arg;
-        struct mailbox_transaction_context *t;
-	struct mail_search_context *ctx;
-	struct mail *mail;
-	struct mail_full_flags seen_flag;
-	uint32_t i, bitmask;
-	int failed = FALSE;
-
-	if (delete_mails && client->deleted_bitmask == NULL)
-                delete_mails = FALSE;
-
-	memset(&search_arg, 0, sizeof(search_arg));
-	search_arg.type = SEARCH_ALL;
-
-	t = mailbox_transaction_begin(box, FALSE);
-	ctx = mailbox_search_init(t, NULL, &search_arg, NULL, 0, NULL);
-	if (ctx == NULL) {
-		mailbox_transaction_rollback(t);
-		return FALSE;
-	}
-
-	memset(&seen_flag, 0, sizeof(seen_flag));
-	seen_flag.flags = MAIL_SEEN;
-
-	while ((mail = mailbox_search_next(ctx)) != NULL) {
-		i = mail->seq-1;
-
-		bitmask = 1 << (i % CHAR_BIT);
-		if (delete_mails &&
-		    (client->deleted_bitmask[i/CHAR_BIT] & bitmask) != 0) {
-			if (mail->expunge(mail) < 0) {
-				failed = TRUE;
-				break;
-			}
-		} else if (client->seen_bitmask != NULL &&
-			   (client->seen_bitmask[i/CHAR_BIT] & bitmask) != 0) {
-			if (mail->update_flags(mail, &seen_flag,
-					       MODIFY_ADD) < 0) {
-				failed = TRUE;
-				break;
-			}
-		}
-	}
-
-	if (mailbox_search_deinit(ctx) < 0 || failed) {
-		mailbox_transaction_rollback(t);
-		return FALSE;
-	}
-
-	mailbox_transaction_commit(t, MAILBOX_SYNC_FLAG_FULL_READ |
-				   MAILBOX_SYNC_FLAG_FULL_WRITE);
-	return TRUE;
-}
-
 struct client *client_create(int hin, int hout, struct mail_storage *storage)
 {
 	struct client *client;
@@ -244,18 +183,14 @@
 		client->cmd(client);
 		i_assert(client->cmd == NULL);
 	}
-	if (client->mailbox != NULL) {
-		if (client->seen_bitmask != NULL) {
-			(void)client_update_mailbox(client, client->mailbox,
-						    FALSE);
-		}
+	if (client->trans != NULL)
+		mailbox_transaction_rollback(client->trans);
+	if (client->mailbox != NULL)
 		mailbox_close(client->mailbox);
-	}
 	mail_storage_destroy(client->storage);
 
 	i_free(client->message_sizes);
 	i_free(client->deleted_bitmask);
-	i_free(client->seen_bitmask);
 
 	if (client->io != NULL)
 		io_remove(client->io);

Index: client.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/pop3/client.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- client.h	8 Oct 2004 20:25:00 -0000	1.8
+++ client.h	10 Oct 2004 16:25:06 -0000	1.9
@@ -17,6 +17,7 @@
 
 	struct mail_storage *storage;
 	struct mailbox *mailbox;
+	struct mailbox_transaction_context *trans;
 
 	time_t last_input, last_output;
 	unsigned int bad_counter;
@@ -29,7 +30,6 @@
 	uint32_t last_seen;
 
 	unsigned char *deleted_bitmask;
-	unsigned char *seen_bitmask;
 
 	unsigned int deleted:1;
 	unsigned int waiting_input:1;
@@ -43,9 +43,6 @@
 /* Disconnect client connection */
 void client_disconnect(struct client *client);
 
-int client_update_mailbox(struct client *client, struct mailbox *box,
-			  int delete_mails);
-
 /* Send a line of data to client */
 int client_send_line(struct client *client, const char *fmt, ...)
 	__attr_format__(2, 3);

Index: commands.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/pop3/commands.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- commands.c	10 Oct 2004 14:32:33 -0000	1.32
+++ commands.c	10 Oct 2004 16:25:06 -0000	1.33
@@ -178,20 +178,46 @@
 	return TRUE;
 }
 
+static int expunge_mails(struct client *client)
+{
+	struct mail_search_arg search_arg;
+	struct mail_search_context *ctx;
+	struct mail *mail;
+	uint32_t idx;
+
+	if (client->deleted_bitmask == NULL)
+		return TRUE;
+
+	memset(&search_arg, 0, sizeof(search_arg));
+	search_arg.type = SEARCH_ALL;
+
+	ctx = mailbox_search_init(client->trans, NULL, &search_arg,
+				  NULL, 0, NULL);
+	while ((mail = mailbox_search_next(ctx)) != NULL) {
+		idx = mail->seq - 1;
+		if ((client->deleted_bitmask[idx / CHAR_BIT] &
+		     1 << (idx % CHAR_BIT)) != 0) {
+			if (mail->expunge(mail) < 0)
+				return FALSE;
+		}
+	}
+
+	return mailbox_search_deinit(ctx) == 0;
+}
+
 static int cmd_quit(struct client *client, const char *args __attr_unused__)
 {
 	if (client->deleted) {
-		if (!client_update_mailbox(client, client->mailbox, TRUE)) {
+		if (!expunge_mails(client)) {
 			client_send_storage_error(client);
 			client_disconnect(client);
 			return TRUE;
 		}
-
-		/* don't sync them again at client_destroy() */
-		i_free(client->seen_bitmask);
-                client->seen_bitmask = NULL;
 	}
 
+	mailbox_transaction_commit(client->trans, MAILBOX_SYNC_FLAG_FULL_WRITE);
+	client->trans = NULL;
+
 	if (!client->deleted)
 		client_send_line(client, "+OK Logging out.");
 	else
@@ -202,7 +228,6 @@
 }
 
 struct fetch_context {
-        struct mailbox_transaction_context *t;
 	struct mail_search_context *search_ctx;
 	struct istream *stream;
 	uoff_t body_lines;
@@ -217,7 +242,6 @@
 static void fetch_deinit(struct fetch_context *ctx)
 {
 	(void)mailbox_search_deinit(ctx->search_ctx);
-	(void)mailbox_transaction_commit(ctx->t, 0);
 	i_free(ctx);
 }
 
@@ -320,8 +344,8 @@
 	ctx->search_arg.type = SEARCH_SEQSET;
 	ctx->search_arg.value.seqset = &ctx->seqset;
 
-	ctx->t = mailbox_transaction_begin(client->mailbox, FALSE);
-	ctx->search_ctx = mailbox_search_init(ctx->t, NULL, &ctx->search_arg,
+	ctx->search_ctx = mailbox_search_init(client->trans, NULL,
+					      &ctx->search_arg,
 					      NULL, MAIL_FETCH_STREAM_HEADER |
 					      MAIL_FETCH_STREAM_BODY, NULL);
 	mail = mailbox_search_next(ctx->search_ctx);
@@ -334,12 +358,11 @@
 
 	if (body_lines == (uoff_t)-1 && !no_flag_updates) {
 		/* mark the message seen with RETR command */
-		if (client->seen_bitmask == NULL) {
-			client->seen_bitmask =
-				i_malloc(MSGS_BITMASK_SIZE(client));
-		}
-		client->seen_bitmask[msgnum / CHAR_BIT] |=
-			1 << (msgnum % CHAR_BIT);
+		struct mail_full_flags seen_flag;
+		memset(&seen_flag, 0, sizeof(seen_flag));
+		seen_flag.flags = MAIL_SEEN;
+
+		(void)mail->update_flags(mail, &seen_flag, MODIFY_ADD);
 	}
 
 	ctx->body_lines = body_lines;
@@ -372,7 +395,6 @@
 
 static int cmd_rset(struct client *client, const char *args __attr_unused__)
 {
-	struct mailbox_transaction_context *t;
 	struct mail_search_context *search_ctx;
 	struct mail *mail;
 	struct mail_search_arg search_arg;
@@ -387,6 +409,10 @@
 		client->deleted_size = 0;
 	}
 
+	/* forget all our seen flag updates as well.. */
+	mailbox_transaction_rollback(client->trans);
+	client->trans = mailbox_transaction_begin(client->mailbox, FALSE);
+
 	if (enable_last_command) {
 		/* remove all \Seen flags */
 		memset(&search_arg, 0, sizeof(search_arg));
@@ -395,16 +421,14 @@
 		memset(&seen_flag, 0, sizeof(seen_flag));
 		seen_flag.flags = MAIL_SEEN;
 
-		t = mailbox_transaction_begin(client->mailbox, FALSE);
-		search_ctx = mailbox_search_init(t, NULL, &search_arg,
-						 NULL, 0, NULL);
+		search_ctx = mailbox_search_init(client->trans, NULL,
+						 &search_arg, NULL, 0, NULL);
 		while ((mail = mailbox_search_next(search_ctx)) != NULL) {
 			if (mail->update_flags(mail, &seen_flag,
 					       MODIFY_REMOVE) < 0)
 				break;
 		}
 		(void)mailbox_search_deinit(search_ctx);
-		(void)mailbox_transaction_commit(t, 0);
 	}
 
 	client_send_line(client, "+OK");
@@ -435,7 +459,6 @@
 }
 
 struct cmd_uidl_context {
-        struct mailbox_transaction_context *t;
 	struct mail_search_context *search_ctx;
 	unsigned int message;
 
@@ -474,7 +497,6 @@
 
 	/* finished */
 	(void)mailbox_search_deinit(ctx->search_ctx);
-	(void)mailbox_transaction_commit(ctx->t, 0);
 
 	client->cmd = NULL;
 
@@ -507,9 +529,8 @@
 		ctx->search_arg.value.seqset = &ctx->seqset;
 	}
 
-	ctx->t = mailbox_transaction_begin(client->mailbox, FALSE);
-	ctx->search_ctx = mailbox_search_init(ctx->t, NULL, &ctx->search_arg,
-					      NULL, 0, NULL);
+	ctx->search_ctx = mailbox_search_init(client->trans, NULL,
+					      &ctx->search_arg, NULL, 0, NULL);
 	if (message == 0) {
 		client->cmd = cmd_uidl_callback;
 		client->cmd_context = ctx;



More information about the dovecot-cvs mailing list