[dovecot-cvs] dovecot/src/pop3 client.c,1.1,1.2 client.h,1.1,1.2 commands.c,1.1,1.2

cras at procontrol.fi cras at procontrol.fi
Mon Jan 27 08:44:52 EET 2003


Update of /home/cvs/dovecot/src/pop3
In directory danu:/tmp/cvs-serv26645

Modified Files:
	client.c client.h commands.c 
Log Message:
Read the sizes of all messages to memory at startup. More failsafe and
faster.



Index: client.c
===================================================================
RCS file: /home/cvs/dovecot/src/pop3/client.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- client.c	27 Jan 2003 05:45:47 -0000	1.1
+++ client.c	27 Jan 2003 06:44:49 -0000	1.2
@@ -37,10 +37,72 @@
 	o_stream_close(client->output);
 }
 
+static int init_mailbox(struct client *client)
+{
+	struct mail_fetch_context *ctx;
+	struct mail *mail;
+	struct mailbox_status status;
+	const char *messageset;
+	int i, all_found, failed;
+
+	if (!client->mailbox->get_status(client->mailbox,
+					 STATUS_MESSAGES | STATUS_UIDVALIDITY,
+					 &status)) {
+		client_send_storage_error(client);
+		return FALSE;
+	}
+
+	client->messages_count = status.messages;
+	client->uidvalidity = status.uidvalidity;
+	client->message_sizes = i_new(uoff_t, client->messages_count);
+
+	messageset = t_strdup_printf("1:%u", client->messages_count);
+	for (i = 0; i < 2; i++) {
+		ctx = client->mailbox->fetch_init(client->mailbox,
+						  MAIL_FETCH_SIZE,
+						  NULL, messageset, FALSE);
+		if (ctx == NULL) {
+			client_send_storage_error(client);
+			return FALSE;
+		}
+
+		client->total_size = 0;
+		failed = FALSE;
+		while ((mail = client->mailbox->fetch_next(ctx)) != NULL) {
+			uoff_t size = mail->get_size(mail);
+
+			if (size == (uoff_t)-1) {
+				failed = TRUE;
+				break;
+			}
+                        client->total_size += size;
+
+			i_assert(mail->seq <= client->messages_count);
+			client->message_sizes[mail->seq-1] = size;
+		}
+
+		if (!client->mailbox->fetch_deinit(ctx, &all_found)) {
+			client_send_storage_error(client);
+			return FALSE;
+		}
+
+		if (!failed && all_found)
+			return TRUE;
+
+		/* well, sync and try again */
+		if (!client->mailbox->sync(client->mailbox, TRUE)) {
+			client_send_storage_error(client);
+			return FALSE;
+		}
+	}
+
+	client_send_line(client, "-ERR Couldn't sync mailbox.");
+	return FALSE;
+}
+
 struct client *client_create(int hin, int hout, struct mailbox *mailbox)
 {
 	struct client *client;
-	struct mailbox_status status;
 
 	client = i_new(struct client, 1);
 	client->input = i_stream_create_file(hin, default_pool,
@@ -64,11 +126,10 @@
 	i_assert(my_client == NULL);
 	my_client = client;
 
-	if (!mailbox->get_status(mailbox, STATUS_MESSAGES, &status)) {
+	if (!init_mailbox(client)) {
 		client_destroy(client);
-		return NULL;
+		client = NULL;
 	}
-	client->messages_count = status.messages;
 
 	return client;
 }
@@ -81,8 +142,8 @@
 		client->mailbox->close(client->mailbox);
 	mail_storage_destroy(client->storage);
 
-	if (client->deleted_bitmask != NULL)
-		i_free(client->deleted_bitmask);
+	i_free(client->message_sizes);
+	i_free(client->deleted_bitmask);
 
 	io_remove(client->io);
 
@@ -115,6 +176,14 @@
 	(void)o_stream_send_str(client->output, t_strdup_vprintf(fmt, va));
 	(void)o_stream_send(client->output, "\r\n", 2);
 	va_end(va);
+}
+
+void client_send_storage_error(struct client *client)
+{
+	const char *error;
+
+	error = client->storage->get_last_error(client->storage, NULL);
+	client_send_line(client, "-ERR %s", error);
 }
 
 static void client_input(void *context)

Index: client.h
===================================================================
RCS file: /home/cvs/dovecot/src/pop3/client.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- client.h	27 Jan 2003 05:45:47 -0000	1.1
+++ client.h	27 Jan 2003 06:44:49 -0000	1.2
@@ -16,6 +16,10 @@
 	unsigned int bad_counter;
 
 	unsigned int messages_count;
+	unsigned int uidvalidity;
+	uoff_t *message_sizes;
+	uoff_t total_size;
+
 	unsigned char *deleted_bitmask;
 
 	unsigned int deleted:1;
@@ -32,6 +36,7 @@
 /* Send a line of data to client */
 void client_send_line(struct client *client, const char *fmt, ...)
 	__attr_format__(2, 3);
+void client_send_storage_error(struct client *client);
 
 void clients_init(void);
 void clients_deinit(void);

Index: commands.c
===================================================================
RCS file: /home/cvs/dovecot/src/pop3/commands.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- commands.c	27 Jan 2003 05:45:47 -0000	1.1
+++ commands.c	27 Jan 2003 06:44:49 -0000	1.2
@@ -9,14 +9,6 @@
 #define MSGS_BITMASK_SIZE(client) \
 	((client->messages_count + (CHAR_BIT-1)) / CHAR_BIT)
 
-static void client_send_storage_error(struct client *client)
-{
-	const char *error;
-
-	error = client->storage->get_last_error(client->storage, NULL);
-	client_send_line(client, "-ERR %s", error);
-}
-
 static const char *get_msgnum(struct client *client, const char *args,
 			      unsigned int *msgnum)
 {
@@ -106,53 +98,25 @@
 	client_send_line(client, "+OK Marked to be deleted.");
 }
 
-static void list_sizes(struct client *client, unsigned int message)
-{
-	struct mail_fetch_context *ctx;
-	struct mail *mail;
-	const char *messageset;
-	int found = FALSE;
-
-	if (client->messages_count == 0 && message == 0)
-		return;
-
-	messageset = message == 0 ?
-		t_strdup_printf("1:%u", client->messages_count) :
-		t_strdup_printf("%u", message);
-
-	ctx = client->mailbox->fetch_init(client->mailbox, MAIL_FETCH_SIZE,
-					  NULL, messageset, FALSE);
-	if (ctx == NULL) {
-		client_send_storage_error(client);
-		return;
-	}
-
-	while ((mail = client->mailbox->fetch_next(ctx)) != NULL) {
-		uoff_t size = mail->get_size(mail);
-
-		client_send_line(client, message == 0 ? "%u %"PRIuUOFF_T :
-				 "+OK %u %"PRIuUOFF_T, mail->seq, size);
-		found = TRUE;
-	}
-
-	(void)client->mailbox->fetch_deinit(ctx, NULL);
-
-	if (!found && message != 0)
-		client_send_line(client, "-ERR Message not found.");
-}
-
 static void cmd_list(struct client *client, const char *args)
 {
+	unsigned int i;
+
 	if (*args == '\0') {
 		client_send_line(client, "+OK %u messages:",
 				 client->messages_count);
-		list_sizes(client, 0);
+		for (i = 0; i < client->messages_count; i++) {
+			client_send_line(client, "%u %"PRIuUOFF_T,
+					 i, client->message_sizes[i]);
+		}
 		client_send_line(client, ".");
 	} else {
 		unsigned int msgnum;
 
-		if (get_msgnum(client, args, &msgnum) != NULL)
-			list_sizes(client, msgnum);
+		if (get_msgnum(client, args, &msgnum) != NULL) {
+			client_send_line(client, "+OK %u %"PRIuUOFF_T,
+					 msgnum, client->message_sizes[msgnum]);
+		}
 	}
 }
 
@@ -223,7 +187,6 @@
 	struct mail_fetch_context *ctx;
 	struct mail *mail;
 	struct istream *stream;
-	struct message_size hdr_size, body_size;
 
 	ctx = client->mailbox->fetch_init(client->mailbox,
 					  MAIL_FETCH_STREAM_HEADER |
@@ -239,15 +202,18 @@
 	if (mail == NULL)
 		client_send_line(client, "-ERR Message not found.");
 	else {
-		stream = mail->get_stream(mail, &hdr_size, &body_size);
-		message_size_add(&body_size, &hdr_size);
+		stream = mail->get_stream(mail, NULL, NULL);
 
-		client_send_line(client, "+OK %"PRIuUOFF_T" octets",
-				 body_size.virtual_size);
+		if (max_lines == (uoff_t)-1) {
+			client_send_line(client, "+OK %"PRIuUOFF_T" octets",
+					 client->message_sizes[msgnum]);
+		} else {
+			client_send_line(client, "+OK");
+		}
 
 		// FIXME: "." lines needs to be escaped
 		// FIXME: and send only max_lines
-		message_send(client->output, stream, &body_size, 0, (uoff_t)-1);
+		client_send_line(client, ".");
 	}
 
 	(void)client->mailbox->fetch_deinit(ctx, NULL);
@@ -273,35 +239,8 @@
 
 static void cmd_stat(struct client *client, const char *args __attr_unused__)
 {
-	struct mail_fetch_context *ctx;
-	struct mail *mail;
-	uoff_t size, total_size;
-	const char *messageset;
-
-	if (client->messages_count == 0) {
-		client_send_line(client, "+OK 0 0");
-		return;
-	}
-
-	messageset = t_strdup_printf("1:%u", client->messages_count);
-	ctx = client->mailbox->fetch_init(client->mailbox, MAIL_FETCH_SIZE,
-					  NULL, messageset, FALSE);
-	if (ctx == NULL) {
-		client_send_storage_error(client);
-		return;
-	}
-
-	total_size = 0;
-	while ((mail = client->mailbox->fetch_next(ctx)) != NULL) {
-		size = mail->get_size(mail);
-		if (size != (uoff_t)-1)
-			total_size += size;
-	}
-
-	(void)client->mailbox->fetch_deinit(ctx, NULL);
-
-	client_send_line(client, "+OK %u %"PRIuUOFF_T,
-			 client->messages_count, total_size);
+	client_send_line(client, "+OK %u %"PRIuUOFF_T, client->
+			 messages_count, client->total_size);
 }
 
 static void cmd_top(struct client *client, const char *args)
@@ -337,7 +276,8 @@
 
 	while ((mail = client->mailbox->fetch_next(ctx)) != NULL) {
 		client_send_line(client, message == 0 ?
-				 "%u %u" : "+OK %u %u", mail->seq, mail->uid);
+				 "%u %u.%u" : "+OK %u %u.%u",
+				 mail->seq, client->uidvalidity, mail->uid);
 		found = TRUE;
 	}
 




More information about the dovecot-cvs mailing list