dovecot-2.2: pop3: Use POP3 order sorting only when directly lis...
dovecot at dovecot.org
dovecot at dovecot.org
Fri Feb 7 20:03:43 UTC 2014
details: http://hg.dovecot.org/dovecot-2.2/rev/59decc957b39
changeset: 17135:59decc957b39
user: Timo Sirainen <tss at iki.fi>
date: Fri Feb 07 15:03:33 2014 -0500
description:
pop3: Use POP3 order sorting only when directly listing UIDLs.
"Message ordering changed unexpectedly" errors can be completely avoided by
using either pop3_lock_session=yes or adding %u to pop3_logout_format.
diffstat:
src/pop3/pop3-commands.c | 74 +++++++++++++++++++++++++++--------------------
1 files changed, 43 insertions(+), 31 deletions(-)
diffs (136 lines):
diff -r 36d11bf4e58d -r 59decc957b39 src/pop3/pop3-commands.c
--- a/src/pop3/pop3-commands.c Fri Feb 07 14:24:44 2014 -0500
+++ b/src/pop3/pop3-commands.c Fri Feb 07 15:03:33 2014 -0500
@@ -237,6 +237,7 @@
struct mail_search_args *search_args;
struct mail_search_context *ctx;
struct mail *mail;
+ ARRAY_TYPE(seq_range) deleted_msgs, seen_msgs;
uint32_t msgnum, bit;
bool ret = TRUE;
@@ -245,27 +246,35 @@
return TRUE;
}
+ /* translate msgnums to sequences (in case POP3 ordering is
+ different) */
+ t_array_init(&deleted_msgs, 8);
+ if (client->deleted_bitmask != NULL) {
+ for (msgnum = 0; msgnum < client->messages_count; msgnum++) {
+ bit = 1 << (msgnum % CHAR_BIT);
+ if ((client->deleted_bitmask[msgnum / CHAR_BIT] & bit) != 0)
+ seq_range_array_add(&deleted_msgs, client->msgnum_to_seq_map[msgnum]);
+ }
+ }
+ t_array_init(&seen_msgs, 8);
+ if (client->seen_bitmask != NULL) {
+ for (msgnum = 0; msgnum < client->messages_count; msgnum++) {
+ bit = 1 << (msgnum % CHAR_BIT);
+ if ((client->seen_bitmask[msgnum / CHAR_BIT] & bit) != 0)
+ seq_range_array_add(&seen_msgs, client->msgnum_to_seq_map[msgnum]);
+ }
+ }
+
search_args = pop3_search_build(client, 0);
- ctx = mailbox_search_init(client->trans, search_args,
- pop3_sort_program, 0, NULL);
+ ctx = mailbox_search_init(client->trans, search_args, NULL, 0, NULL);
mail_search_args_unref(&search_args);
msgnum = 0;
while (mailbox_search_next(ctx, &mail)) {
- if (client_verify_ordering(client, mail, msgnum) < 0) {
- ret = FALSE;
- break;
- }
-
- bit = 1 << (msgnum % CHAR_BIT);
- if (client->deleted_bitmask != NULL &&
- (client->deleted_bitmask[msgnum / CHAR_BIT] & bit) != 0) {
+ if (seq_range_exists(&deleted_msgs, mail->seq))
client_expunge(client, mail);
- } else if (client->seen_bitmask != NULL &&
- (client->seen_bitmask[msgnum / CHAR_BIT] & bit) != 0) {
+ else if (seq_range_exists(&seen_msgs, mail->seq))
mail_update_flags(mail, MODIFY_ADD, MAIL_SEEN);
- }
- msgnum++;
}
client->seen_change_count = 0;
@@ -762,6 +771,7 @@
struct mail_search_args *search_args;
struct mail *mail;
HASH_TABLE_TYPE(uidl_counter) prev_uidls;
+ const char **seq_uidls;
string_t *str;
char *uidl;
enum mail_fetch_field wanted_fields;
@@ -776,47 +786,49 @@
wanted_fields |= MAIL_FETCH_HEADER_MD5;
search_ctx = mailbox_search_init(client->trans, search_args,
- pop3_sort_program,
- wanted_fields, NULL);
+ NULL, wanted_fields, NULL);
mail_search_args_unref(&search_args);
uidl_duplicates_rename =
strcmp(client->set->pop3_uidl_duplicates, "rename") == 0;
hash_table_create(&prev_uidls, default_pool, 0, str_hash, strcmp);
client->uidl_pool = pool_alloconly_create("message uidls", 1024);
- client->message_uidls = p_new(client->uidl_pool, const char *,
- client->messages_count+1);
- str = t_str_new(128); msgnum = 0;
+ /* first read all the UIDLs into a temporary [seq] array */
+ seq_uidls = i_new(const char *, client->messages_count);
+ str = t_str_new(128);
while (mailbox_search_next(search_ctx, &mail)) {
- if (client_verify_ordering(client, mail, msgnum) < 0) {
- failed = TRUE;
- break;
- }
-
str_truncate(str, 0);
if (pop3_get_uid(client, mail, str, &permanent_uidl) < 0) {
failed = TRUE;
break;
}
-
- if (client->set->pop3_save_uidl && !permanent_uidl)
- mail_update_pop3_uidl(mail, str_c(str));
-
if (uidl_duplicates_rename)
uidl_rename_duplicate(str, prev_uidls);
+
uidl = p_strdup(client->uidl_pool, str_c(str));
- client->message_uidls[msgnum] = uidl;
+ if (client->set->pop3_save_uidl && !permanent_uidl)
+ mail_update_pop3_uidl(mail, uidl);
+
+ seq_uidls[mail->seq-1] = uidl;
hash_table_insert(prev_uidls, uidl, POINTER_CAST(1));
- msgnum++;
}
(void)mailbox_search_deinit(&search_ctx);
hash_table_destroy(&prev_uidls);
if (failed) {
pool_unref(&client->uidl_pool);
- client->message_uidls = NULL;
+ i_free(seq_uidls);
+ return;
}
+ /* map UIDLs to msgnums (in case POP3 sort ordering is different) */
+ client->message_uidls = p_new(client->uidl_pool, const char *,
+ client->messages_count+1);
+ for (msgnum = 0; msgnum < client->messages_count; msgnum++) {
+ client->message_uidls[msgnum] =
+ seq_uidls[client->msgnum_to_seq_map[msgnum]];
+ }
+ i_free(seq_uidls);
}
static struct cmd_uidl_context *
More information about the dovecot-cvs
mailing list