dovecot-1.2: pop3: Track \Seen flag changes in a bitmask and do ...
dovecot at dovecot.org
dovecot at dovecot.org
Wed Feb 4 22:36:40 EET 2009
details: http://hg.dovecot.org/dovecot-1.2/rev/6f29380ba3a0
changeset: 8717:6f29380ba3a0
user: Timo Sirainen <tss at iki.fi>
date: Wed Feb 04 15:28:31 2009 -0500
description:
pop3: Track \Seen flag changes in a bitmask and do the changes at QUIT.
This way RSET doesn't need to rollback the transaction.
diffstat:
3 files changed, 28 insertions(+), 21 deletions(-)
src/pop3/client.c | 4 ++++
src/pop3/client.h | 7 +++++--
src/pop3/commands.c | 38 +++++++++++++++++++-------------------
diffs (150 lines):
diff -r 8cca2bf6ab76 -r 6f29380ba3a0 src/pop3/client.c
--- a/src/pop3/client.c Wed Feb 04 15:13:01 2009 -0500
+++ b/src/pop3/client.c Wed Feb 04 15:28:31 2009 -0500
@@ -197,6 +197,9 @@ struct client *client_create(int fd_in,
return NULL;
}
+ if (!no_flag_updates)
+ client->seen_bitmask = i_malloc(MSGS_BITMASK_SIZE(client));
+
i_assert(my_client == NULL);
my_client = client;
@@ -276,6 +279,7 @@ void client_destroy(struct client *clien
i_free(client->message_sizes);
i_free(client->deleted_bitmask);
+ i_free(client->seen_bitmask);
if (client->io != NULL)
io_remove(&client->io);
diff -r 8cca2bf6ab76 -r 6f29380ba3a0 src/pop3/client.h
--- a/src/pop3/client.h Wed Feb 04 15:13:01 2009 -0500
+++ b/src/pop3/client.h Wed Feb 04 15:28:31 2009 -0500
@@ -5,6 +5,9 @@ struct mail_storage;
struct mail_storage;
typedef void command_func_t(struct client *client);
+
+#define MSGS_BITMASK_SIZE(client) \
+ (((client)->messages_count + (CHAR_BIT-1)) / CHAR_BIT)
struct client {
int fd_in, fd_out;
@@ -27,8 +30,7 @@ struct client {
unsigned int uid_validity;
unsigned int messages_count;
- unsigned int deleted_count;
- unsigned int expunged_count;
+ unsigned int deleted_count, expunged_count, seen_change_count;
uoff_t *message_sizes;
uoff_t total_size;
uoff_t deleted_size;
@@ -43,6 +45,7 @@ struct client {
uoff_t byte_counter_offset;
unsigned char *deleted_bitmask;
+ unsigned char *seen_bitmask;
unsigned int disconnected:1;
unsigned int deleted:1;
diff -r 8cca2bf6ab76 -r 6f29380ba3a0 src/pop3/commands.c
--- a/src/pop3/commands.c Wed Feb 04 15:13:01 2009 -0500
+++ b/src/pop3/commands.c Wed Feb 04 15:28:31 2009 -0500
@@ -12,9 +12,6 @@
#include "capability.h"
#include "commands.h"
-#define MSGS_BITMASK_SIZE(client) \
- ((client->messages_count + (CHAR_BIT-1)) / CHAR_BIT)
-
static const char *get_msgnum(struct client *client, const char *args,
unsigned int *msgnum)
{
@@ -198,15 +195,12 @@ pop3_search_build(struct client *client,
return search_args;
}
-static bool expunge_mails(struct client *client)
+static bool update_mails(struct client *client)
{
struct mail_search_args *search_args;
struct mail_search_context *ctx;
struct mail *mail;
- uint32_t idx;
-
- if (client->deleted_bitmask == NULL)
- return TRUE;
+ uint32_t idx, bit;
if (mailbox_is_readonly(client->mailbox)) {
/* silently ignore */
@@ -220,10 +214,14 @@ static bool expunge_mails(struct client
mail = mail_alloc(client->trans, 0, NULL);
while (mailbox_search_next(ctx, mail) > 0) {
idx = mail->seq - 1;
- if ((client->deleted_bitmask[idx / CHAR_BIT] &
- 1 << (idx % CHAR_BIT)) != 0) {
+ bit = 1 << (idx % CHAR_BIT);
+ if (client->deleted_bitmask != NULL &&
+ (client->deleted_bitmask[idx / CHAR_BIT] & bit) != 0) {
mail_expunge(mail);
client->expunged_count++;
+ } else if (client->seen_bitmask != NULL &&
+ (client->seen_bitmask[idx / CHAR_BIT] & bit) != 0) {
+ mail_update_flags(mail, MODIFY_ADD, MAIL_SEEN);
}
}
mail_free(&mail);
@@ -233,8 +231,8 @@ static bool expunge_mails(struct client
static int cmd_quit(struct client *client, const char *args ATTR_UNUSED)
{
- if (client->deleted) {
- if (!expunge_mails(client)) {
+ if (client->deleted || client->seen_bitmask != NULL) {
+ if (!update_mails(client)) {
client_send_storage_error(client);
client_disconnect(client,
"Storage error during logout.");
@@ -408,11 +406,11 @@ static int fetch(struct client *client,
return ret;
}
- if (body_lines == (uoff_t)-1 && !no_flag_updates) {
+ if (body_lines == (uoff_t)-1 && client->seen_bitmask != NULL) {
if ((mail_get_flags(ctx->mail) & MAIL_SEEN) == 0) {
/* mark the message seen with RETR command */
- (void)mail_update_flags(ctx->mail,
- MODIFY_ADD, MAIL_SEEN);
+ client->seen_bitmask[msgnum / CHAR_BIT] |= 1 << (msgnum % CHAR_BIT);
+ client->seen_change_count++;
}
}
@@ -462,6 +460,10 @@ static int cmd_rset(struct client *clien
client->deleted_count = 0;
client->deleted_size = 0;
}
+ if (client->seen_change_count > 0) {
+ memset(client->seen_bitmask, 0, MSGS_BITMASK_SIZE(client));
+ client->seen_change_count = 0;
+ }
if (enable_last_command) {
/* remove all \Seen flags (as specified by RFC 1460) */
@@ -475,10 +477,8 @@ static int cmd_rset(struct client *clien
mail_update_flags(mail, MODIFY_REMOVE, MAIL_SEEN);
mail_free(&mail);
(void)mailbox_search_deinit(&search_ctx);
- } else {
- /* forget all our seen flag updates.
- FIXME: is this needed? it loses data added to cache file */
- mailbox_transaction_rollback(&client->trans);
+
+ mailbox_transaction_commit(&client->trans);
client->trans = mailbox_transaction_begin(client->mailbox, 0);
}
More information about the dovecot-cvs
mailing list