dovecot: FLAGS/PERMENENTFLAGS weren't always sent to client earl...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Dec 29 07:11:16 EET 2007
details: http://hg.dovecot.org/dovecot/rev/81f4c9689c18
changeset: 7057:81f4c9689c18
user: Timo Sirainen <tss at iki.fi>
date: Sat Dec 29 07:11:12 2007 +0200
description:
FLAGS/PERMENENTFLAGS weren't always sent to client early enough. Also
optimized sending keywords with FETCH FLAGS.
diffstat:
10 files changed, 88 insertions(+), 118 deletions(-)
src/imap/client.c | 2
src/imap/client.h | 10 +++-
src/imap/cmd-close.c | 1
src/imap/cmd-select.c | 12 ++---
src/imap/cmd-unselect.c | 1
src/imap/commands-util.c | 98 +++++++++++++++++++++-------------------------
src/imap/commands-util.h | 18 ++++----
src/imap/imap-fetch.c | 7 ++-
src/imap/imap-fetch.h | 1
src/imap/imap-sync.c | 56 +++++---------------------
diffs (truncated from 405 to 300 lines):
diff -r 097c70cfa55e -r 81f4c9689c18 src/imap/client.c
--- a/src/imap/client.c Sat Dec 29 06:54:40 2007 +0200
+++ b/src/imap/client.c Sat Dec 29 07:11:12 2007 +0200
@@ -41,7 +41,6 @@ struct client *client_create(int fd_in,
client->last_input = ioloop_time;
client->command_pool = pool_alloconly_create("client command", 8192);
- client->keywords.pool = pool_alloconly_create("mailbox_keywords", 512);
client->namespaces = namespaces;
while (namespaces != NULL) {
@@ -144,7 +143,6 @@ void client_destroy(struct client *clien
i_error("close(client out) failed: %m");
}
- pool_unref(&client->keywords.pool);
pool_unref(&client->command_pool);
i_free(client);
diff -r 097c70cfa55e -r 81f4c9689c18 src/imap/client.h
--- a/src/imap/client.h Sat Dec 29 06:54:40 2007 +0200
+++ b/src/imap/client.h Sat Dec 29 07:11:12 2007 +0200
@@ -11,9 +11,13 @@ struct imap_arg;
struct imap_arg;
struct mailbox_keywords {
- pool_t pool; /* will be p_clear()ed when changed */
-
- ARRAY_DEFINE(keywords, const char *);
+ /* All keyword names. The array itself exists in mail_index.
+ Keywords are currently only appended, they're never removed. */
+ const ARRAY_TYPE(keywords) *names;
+ /* Number of keywords announced to client via FLAGS/PERMANENTFLAGS.
+ This relies on keywords not being removed while mailbox is
+ selected. */
+ unsigned int announce_count;
};
struct client_command_context {
diff -r 097c70cfa55e -r 81f4c9689c18 src/imap/cmd-close.c
--- a/src/imap/cmd-close.c Sat Dec 29 06:54:40 2007 +0200
+++ b/src/imap/cmd-close.c Sat Dec 29 07:11:12 2007 +0200
@@ -21,6 +21,7 @@ bool cmd_close(struct client_command_con
if (mailbox_close(&mailbox) < 0)
client_send_untagged_storage_error(client, storage);
+ client_update_mailbox_flags(client, NULL);
client_send_tagline(cmd, "OK Close completed.");
return TRUE;
diff -r 097c70cfa55e -r 81f4c9689c18 src/imap/cmd-select.c
--- a/src/imap/cmd-select.c Sat Dec 29 06:54:40 2007 +0200
+++ b/src/imap/cmd-select.c Sat Dec 29 07:11:12 2007 +0200
@@ -45,17 +45,17 @@ bool cmd_select_full(struct client_comma
return TRUE;
}
- client_save_keywords(&client->keywords, status.keywords);
- client->messages_count = status.messages;
- client->recent_count = status.recent;
- client->uidvalidity = status.uidvalidity;
-
/* set client's mailbox only after getting status to make sure
we're not sending any expunge/exists replies too early to client */
client->mailbox = box;
client->select_counter++;
- client_send_mailbox_flags(client, box, status.keywords);
+ client->messages_count = status.messages;
+ client->recent_count = status.recent;
+ client->uidvalidity = status.uidvalidity;
+
+ client_update_mailbox_flags(client, status.keywords);
+ client_send_mailbox_flags(client, TRUE);
client_send_line(client,
t_strdup_printf("* %u EXISTS", status.messages));
diff -r 097c70cfa55e -r 81f4c9689c18 src/imap/cmd-unselect.c
--- a/src/imap/cmd-unselect.c Sat Dec 29 06:54:40 2007 +0200
+++ b/src/imap/cmd-unselect.c Sat Dec 29 07:11:12 2007 +0200
@@ -17,6 +17,7 @@ bool cmd_unselect(struct client_command_
storage = mailbox_get_storage(mailbox);
if (mailbox_close(&mailbox) < 0)
client_send_untagged_storage_error(client, storage);
+ client_update_mailbox_flags(client, NULL);
client_send_tagline(cmd, "OK Unselect completed.");
return TRUE;
diff -r 097c70cfa55e -r 81f4c9689c18 src/imap/commands-util.c
--- a/src/imap/commands-util.c Sat Dec 29 06:54:40 2007 +0200
+++ b/src/imap/commands-util.c Sat Dec 29 07:11:12 2007 +0200
@@ -251,9 +251,6 @@ static const char *get_keywords_string(c
const char *const *names;
unsigned int i, count;
- if (array_count(keywords) == 0)
- return "";
-
str = t_str_new(256);
names = array_get(keywords, &count);
for (i = 0; i < count; i++) {
@@ -265,65 +262,62 @@ static const char *get_keywords_string(c
#define SYSTEM_FLAGS "\\Answered \\Flagged \\Deleted \\Seen \\Draft"
-void client_send_mailbox_flags(struct client *client, struct mailbox *box,
- const ARRAY_TYPE(keywords) *keywords)
-{
+void client_send_mailbox_flags(struct client *client, bool selecting)
+{
+ unsigned int count = array_count(client->keywords.names);
const char *str;
- str = get_keywords_string(keywords);
+ if (!selecting && count == client->keywords.announce_count) {
+ /* no changes to keywords and we're not selecting a mailbox */
+ return;
+ }
+
+ client->keywords.announce_count = count;
+ str = count == 0 ? "" : get_keywords_string(client->keywords.names);
client_send_line(client,
t_strconcat("* FLAGS ("SYSTEM_FLAGS, str, ")", NULL));
- if (mailbox_is_readonly(box)) {
+ if (mailbox_is_readonly(client->mailbox)) {
client_send_line(client, "* OK [PERMANENTFLAGS ()] "
"Read-only mailbox.");
} else {
+ bool star = mailbox_allow_new_keywords(client->mailbox);
+
client_send_line(client,
t_strconcat("* OK [PERMANENTFLAGS ("SYSTEM_FLAGS, str,
- mailbox_allow_new_keywords(box) ?
- " \\*" : "", ")] Flags permitted.", NULL));
- }
-}
-
-bool client_save_keywords(struct mailbox_keywords *dest,
- const ARRAY_TYPE(keywords) *keywords)
-{
- const char *const *names, *const *old_names;
- unsigned int i, count, old_count;
- bool changed;
-
- names = array_get(keywords, &count);
-
- /* first check if anything changes */
- if (!array_is_created(&dest->keywords))
- changed = count != 0;
- else {
- old_names = array_get(&dest->keywords, &old_count);
- if (count != old_count)
- changed = TRUE;
- else {
- changed = FALSE;
- for (i = 0; i < count; i++) {
- if (strcmp(names[i], old_names[i]) != 0) {
- changed = TRUE;
- break;
- }
- }
- }
- }
-
- if (!changed)
- return FALSE;
-
- p_clear(dest->pool);
- p_array_init(&dest->keywords, dest->pool, array_count(keywords));
-
- for (i = 0; i < count; i++) {
- const char *name = p_strdup(dest->pool, names[i]);
-
- array_append(&dest->keywords, &name, 1);
- }
- return TRUE;
+ star ? " \\*" : "",
+ ")] Flags permitted.", NULL));
+ }
+}
+
+void client_update_mailbox_flags(struct client *client,
+ const ARRAY_TYPE(keywords) *keywords)
+{
+ client->keywords.names = keywords;
+ client->keywords.announce_count = 0;
+}
+
+const char *const *
+client_get_keyword_names(struct client *client, ARRAY_TYPE(keywords) *dest,
+ const ARRAY_TYPE(keyword_indexes) *src)
+{
+ const unsigned int *kw_indexes;
+ const char *const *all_names;
+ unsigned int i, kw_count, all_count;
+
+ client_send_mailbox_flags(client, FALSE);
+
+ all_names = array_get(client->keywords.names, &all_count);
+ kw_indexes = array_get(src, &kw_count);
+
+ /* convert indexes to names */
+ for (i = 0; i < kw_count; i++) {
+ i_assert(kw_indexes[i] < all_count);
+ array_append(dest, &all_names[kw_indexes[i]], 1);
+ }
+
+ (void)array_append_space(dest);
+ return array_idx(dest, 0);
}
bool mailbox_equals(struct mailbox *box1, struct mail_storage *storage2,
diff -r 097c70cfa55e -r 81f4c9689c18 src/imap/commands-util.h
--- a/src/imap/commands-util.h Sat Dec 29 06:54:40 2007 +0200
+++ b/src/imap/commands-util.h Sat Dec 29 07:11:12 2007 +0200
@@ -50,14 +50,16 @@ bool client_parse_mail_flags(struct clie
enum mail_flags *flags_r,
const char *const **keywords_r);
-/* Send FLAGS + PERMANENTFLAGS to client. */
-void client_send_mailbox_flags(struct client *client, struct mailbox *box,
- const ARRAY_TYPE(keywords) *keywords);
-
-/* Copy keywords into dest. dest must have been initialized. Returns TRUE if
- keywords changed. */
-bool client_save_keywords(struct mailbox_keywords *dest,
- const ARRAY_TYPE(keywords) *keywords);
+/* Send FLAGS + PERMANENTFLAGS to client if they have changed,
+ or if selecting=TRUE. */
+void client_send_mailbox_flags(struct client *client, bool selecting);
+/* Update client->keywords array. Use keywords=NULL when unselecting. */
+void client_update_mailbox_flags(struct client *client,
+ const ARRAY_TYPE(keywords) *keywords);
+/* Convert keyword indexes to keyword names in selected mailbox. */
+const char *const *
+client_get_keyword_names(struct client *client, ARRAY_TYPE(keywords) *dest,
+ const ARRAY_TYPE(keyword_indexes) *src);
bool mailbox_equals(struct mailbox *box1, struct mail_storage *storage2,
const char *name2);
diff -r 097c70cfa55e -r 81f4c9689c18 src/imap/imap-fetch.c
--- a/src/imap/imap-fetch.c Sat Dec 29 06:54:40 2007 +0200
+++ b/src/imap/imap-fetch.c Sat Dec 29 07:11:12 2007 +0200
@@ -99,6 +99,8 @@ struct imap_fetch_context *imap_fetch_in
ctx->cur_str = str_new(default_pool, 8192);
ctx->all_headers_buf = buffer_create_dynamic(cmd->pool, 128);
p_array_init(&ctx->handlers, cmd->pool, 16);
+ p_array_init(&ctx->tmp_keywords, cmd->pool,
+ client->keywords.announce_count + 8);
ctx->line_finished = TRUE;
return ctx;
}
@@ -514,8 +516,6 @@ static int fetch_flags(struct imap_fetch
const char *const *keywords;
flags = mail_get_flags(mail);
- keywords = mail_get_keywords(mail);
-
if (ctx->flags_update_seen && (flags & MAIL_SEEN) == 0) {
/* Add \Seen flag */
ctx->seen_flags_changed = TRUE;
@@ -524,6 +524,9 @@ static int fetch_flags(struct imap_fetch
} else if (ctx->flags_show_only_seen_changes) {
return 1;
}
+
+ keywords = client_get_keyword_names(ctx->client, &ctx->tmp_keywords,
+ mail_get_keyword_indexes(mail));
str_append(ctx->cur_str, "FLAGS (");
imap_write_flags(ctx->cur_str, flags, keywords);
diff -r 097c70cfa55e -r 81f4c9689c18 src/imap/imap-fetch.h
--- a/src/imap/imap-fetch.h Sat Dec 29 06:54:40 2007 +0200
+++ b/src/imap/imap-fetch.h Sat Dec 29 07:11:12 2007 +0200
@@ -51,6 +51,7 @@ struct imap_fetch_context {
bool skip_cr;
int (*cont_handler)(struct imap_fetch_context *ctx);
+ ARRAY_TYPE(keywords) tmp_keywords;
unsigned int select_counter;
unsigned int flags_have_handler:1;
diff -r 097c70cfa55e -r 81f4c9689c18 src/imap/imap-sync.c
--- a/src/imap/imap-sync.c Sat Dec 29 06:54:40 2007 +0200
+++ b/src/imap/imap-sync.c Sat Dec 29 07:11:12 2007 +0200
@@ -21,10 +21,8 @@ struct imap_sync_context {
struct mailbox_sync_context *sync_ctx;
struct mail *mail;
- const ARRAY_TYPE(keywords) *keywords;
- unsigned int keyword_announce_count;
-
struct mailbox_sync_rec sync_rec;
+ ARRAY_TYPE(keywords) tmp_keywords;
uint32_t seq;
unsigned int messages_count;
@@ -33,19 +31,11 @@ struct imap_sync_context {
unsigned int no_newmail:1;
More information about the dovecot-cvs
mailing list