comparison src/doveadm/doveadm-mail-mailbox-status.c @ 12550:2c299c0e3bc8

lib-storage: Moved some items from mailbox_get_status() to a new mailbox_get_metadata(). The idea is now that all status items are tracked all the time after mailbox is opened and they can always be looked up without failure. The metadata items are looked up lazily and the lookups may fail at any time. mailbox_get_status() can be used after mailbox_alloc() to indicate that the mailbox doesn't necessarily have to be opened, just that the status fields get returned. If mailbox is already known to be open, mailbox_get_open_status() can be used. It never fails.
author Timo Sirainen <tss@iki.fi>
date Sat, 01 Jan 2011 15:52:39 +0200
parents bbfa924bc4bc
children 02370eda76f8
comparison
equal deleted inserted replaced
12549:bbfa924bc4bc 12550:2c299c0e3bc8
10 #include "doveadm-mail-list-iter.h" 10 #include "doveadm-mail-list-iter.h"
11 11
12 #define ALL_STATUS_ITEMS \ 12 #define ALL_STATUS_ITEMS \
13 (STATUS_MESSAGES | STATUS_RECENT | \ 13 (STATUS_MESSAGES | STATUS_RECENT | \
14 STATUS_UIDNEXT | STATUS_UIDVALIDITY | \ 14 STATUS_UIDNEXT | STATUS_UIDVALIDITY | \
15 STATUS_UNSEEN | STATUS_HIGHESTMODSEQ | STATUS_VIRTUAL_SIZE) 15 STATUS_UNSEEN | STATUS_HIGHESTMODSEQ)
16 #define ALL_METADATA_ITEMS \
17 (MAILBOX_METADATA_VIRTUAL_SIZE | MAILBOX_METADATA_GUID)
16 18
17 #define TOTAL_STATUS_ITEMS \ 19 #define TOTAL_STATUS_ITEMS \
18 (STATUS_MESSAGES | STATUS_RECENT | STATUS_UNSEEN | STATUS_VIRTUAL_SIZE) 20 (STATUS_MESSAGES | STATUS_RECENT | STATUS_UNSEEN)
21 #define TOTAL_METADATA_ITEMS \
22 (MAILBOX_METADATA_VIRTUAL_SIZE)
19 23
20 struct status_cmd_context { 24 struct status_cmd_context {
21 struct doveadm_mail_cmd_context ctx; 25 struct doveadm_mail_cmd_context ctx;
22 struct mail_search_args *search_args; 26 struct mail_search_args *search_args;
23 enum mailbox_status_items items; 27
28 enum mailbox_status_items status_items;
29 enum mailbox_metadata_items metadata_items;
24 struct mailbox_status total_status; 30 struct mailbox_status total_status;
25 31 struct mailbox_metadata total_metadata;
26 unsigned int guid:1; 32
27 unsigned int total_sum:1; 33 unsigned int total_sum:1;
28 }; 34 };
29 35
30 static void status_parse_fields(struct status_cmd_context *ctx, 36 static void status_parse_fields(struct status_cmd_context *ctx,
31 const char *const *fields) 37 const char *const *fields)
35 41
36 for (; *fields != NULL; fields++) { 42 for (; *fields != NULL; fields++) {
37 const char *field = *fields; 43 const char *field = *fields;
38 44
39 if (strcmp(field, "all") == 0) { 45 if (strcmp(field, "all") == 0) {
40 if (ctx->total_sum) 46 if (ctx->total_sum) {
41 ctx->items |= TOTAL_STATUS_ITEMS; 47 ctx->status_items |= TOTAL_STATUS_ITEMS;
42 else { 48 ctx->metadata_items |= TOTAL_METADATA_ITEMS;
43 ctx->items |= ALL_STATUS_ITEMS; 49 } else {
44 ctx->guid = TRUE; 50 ctx->status_items |= ALL_STATUS_ITEMS;
51 ctx->metadata_items |= ALL_METADATA_ITEMS;
45 } 52 }
46 } else if (strcmp(field, "messages") == 0) 53 } else if (strcmp(field, "messages") == 0)
47 ctx->items |= STATUS_MESSAGES; 54 ctx->status_items |= STATUS_MESSAGES;
48 else if (strcmp(field, "recent") == 0) 55 else if (strcmp(field, "recent") == 0)
49 ctx->items |= STATUS_RECENT; 56 ctx->status_items |= STATUS_RECENT;
50 else if (strcmp(field, "uidnext") == 0) 57 else if (strcmp(field, "uidnext") == 0)
51 ctx->items |= STATUS_UIDNEXT; 58 ctx->status_items |= STATUS_UIDNEXT;
52 else if (strcmp(field, "uidvalidity") == 0) 59 else if (strcmp(field, "uidvalidity") == 0)
53 ctx->items |= STATUS_UIDVALIDITY; 60 ctx->status_items |= STATUS_UIDVALIDITY;
54 else if (strcmp(field, "unseen") == 0) 61 else if (strcmp(field, "unseen") == 0)
55 ctx->items |= STATUS_UNSEEN; 62 ctx->status_items |= STATUS_UNSEEN;
56 else if (strcmp(field, "highestmodseq") == 0) 63 else if (strcmp(field, "highestmodseq") == 0)
57 ctx->items |= STATUS_HIGHESTMODSEQ; 64 ctx->status_items |= STATUS_HIGHESTMODSEQ;
58 else if (strcmp(field, "vsize") == 0) 65 else if (strcmp(field, "vsize") == 0)
59 ctx->items |= STATUS_VIRTUAL_SIZE; 66 ctx->metadata_items |= MAILBOX_METADATA_VIRTUAL_SIZE;
60 else if (strcmp(field, "guid") == 0) 67 else if (strcmp(field, "guid") == 0)
61 ctx->guid = TRUE; 68 ctx->metadata_items |= MAILBOX_METADATA_GUID;
62 else 69 else
63 i_fatal("Unknown status field: %s", field); 70 i_fatal("Unknown status field: %s", field);
64 71
65 if (ctx->total_sum && 72 if (ctx->total_sum &&
66 ((ctx->items & ~TOTAL_STATUS_ITEMS) != 0 || ctx->guid)) 73 ((ctx->status_items & ~TOTAL_STATUS_ITEMS) != 0 ||
74 (ctx->metadata_items & ~TOTAL_METADATA_ITEMS) != 0))
67 i_fatal("Status field %s can't be used with -t", field); 75 i_fatal("Status field %s can't be used with -t", field);
68 } 76 }
69 } 77 }
70 78
71 static void status_output(struct status_cmd_context *ctx, struct mailbox *box, 79 static void status_output(struct status_cmd_context *ctx, struct mailbox *box,
72 const struct mailbox_status *status, 80 const struct mailbox_status *status,
73 uint8_t mailbox_guid[MAIL_GUID_128_SIZE]) 81 const struct mailbox_metadata *metadata)
74 { 82 {
75 string_t *name; 83 string_t *name;
76 84
77 if (box != NULL) { 85 if (box != NULL) {
78 name = t_str_new(128); 86 name = t_str_new(128);
81 str_append(name, mailbox_get_vname(box)); 89 str_append(name, mailbox_get_vname(box));
82 } 90 }
83 doveadm_print(str_c(name)); 91 doveadm_print(str_c(name));
84 } 92 }
85 93
86 if ((ctx->items & STATUS_MESSAGES) != 0) 94 if ((ctx->status_items & STATUS_MESSAGES) != 0)
87 doveadm_print_num(status->messages); 95 doveadm_print_num(status->messages);
88 if ((ctx->items & STATUS_RECENT) != 0) 96 if ((ctx->status_items & STATUS_RECENT) != 0)
89 doveadm_print_num(status->recent); 97 doveadm_print_num(status->recent);
90 if ((ctx->items & STATUS_UIDNEXT) != 0) 98 if ((ctx->status_items & STATUS_UIDNEXT) != 0)
91 doveadm_print_num(status->uidnext); 99 doveadm_print_num(status->uidnext);
92 if ((ctx->items & STATUS_UIDVALIDITY) != 0) 100 if ((ctx->status_items & STATUS_UIDVALIDITY) != 0)
93 doveadm_print_num(status->uidvalidity); 101 doveadm_print_num(status->uidvalidity);
94 if ((ctx->items & STATUS_UNSEEN) != 0) 102 if ((ctx->status_items & STATUS_UNSEEN) != 0)
95 doveadm_print_num(status->unseen); 103 doveadm_print_num(status->unseen);
96 if ((ctx->items & STATUS_HIGHESTMODSEQ) != 0) 104 if ((ctx->status_items & STATUS_HIGHESTMODSEQ) != 0)
97 doveadm_print_num(status->highest_modseq); 105 doveadm_print_num(status->highest_modseq);
98 if ((ctx->items & STATUS_VIRTUAL_SIZE) != 0) 106 if ((ctx->metadata_items & MAILBOX_METADATA_VIRTUAL_SIZE) != 0)
99 doveadm_print_num(status->virtual_size); 107 doveadm_print_num(metadata->virtual_size);
100 if (ctx->guid) 108 if ((ctx->metadata_items & MAILBOX_METADATA_GUID) != 0)
101 doveadm_print(mail_guid_128_to_string(mailbox_guid)); 109 doveadm_print(mail_guid_128_to_string(metadata->guid));
102 } 110 }
103 111
104 static void 112 static void
105 status_sum(struct status_cmd_context *ctx, 113 status_sum(struct status_cmd_context *ctx,
106 const struct mailbox_status *status) 114 const struct mailbox_status *status,
115 const struct mailbox_metadata *metadata)
107 { 116 {
108 struct mailbox_status *dest = &ctx->total_status; 117 struct mailbox_status *dest = &ctx->total_status;
109 118
110 dest->messages += status->messages; 119 dest->messages += status->messages;
111 dest->recent += status->recent; 120 dest->recent += status->recent;
112 dest->unseen += status->unseen; 121 dest->unseen += status->unseen;
113 dest->virtual_size += status->virtual_size; 122 ctx->total_metadata.virtual_size += metadata->virtual_size;
114 } 123 }
115 124
116 static void 125 static void
117 status_mailbox(struct status_cmd_context *ctx, const struct mailbox_info *info) 126 status_mailbox(struct status_cmd_context *ctx, const struct mailbox_info *info)
118 { 127 {
119 struct mailbox *box; 128 struct mailbox *box;
120 struct mailbox_status status; 129 struct mailbox_status status;
121 uint8_t mailbox_guid[MAIL_GUID_128_SIZE]; 130 struct mailbox_metadata metadata;
122 string_t *mailbox_name = t_str_new(128); 131 string_t *mailbox_name = t_str_new(128);
123 132
124 if (imap_utf7_to_utf8(info->name, mailbox_name) < 0) { 133 if (imap_utf7_to_utf8(info->name, mailbox_name) < 0) {
125 str_truncate(mailbox_name, 0); 134 str_truncate(mailbox_name, 0);
126 str_append(mailbox_name, info->name); 135 str_append(mailbox_name, info->name);
127 } 136 }
128 137
129 if (doveadm_mailbox_find_and_sync(ctx->ctx.cur_mail_user, 138 box = doveadm_mailbox_find(ctx->ctx.cur_mail_user, str_c(mailbox_name));
130 str_c(mailbox_name), &box) < 0 || 139 if (mailbox_get_status(box, ctx->status_items, &status) < 0 ||
131 mailbox_get_status(box, ctx->items, &status) < 0) { 140 mailbox_get_metadata(box, ctx->metadata_items, &metadata) < 0) {
132 ctx->ctx.failed = TRUE; 141 ctx->ctx.failed = TRUE;
142 mailbox_free(&box);
133 return; 143 return;
134 } 144 }
135 if (ctx->guid) {
136 if (mailbox_get_guid(box, mailbox_guid) < 0)
137 memset(mailbox_guid, 0, sizeof(mailbox_guid));
138 }
139 if (!ctx->total_sum) 145 if (!ctx->total_sum)
140 status_output(ctx, box, &status, mailbox_guid); 146 status_output(ctx, box, &status, &metadata);
141 else 147 else
142 status_sum(ctx, &status); 148 status_sum(ctx, &status, &metadata);
143 mailbox_free(&box); 149 mailbox_free(&box);
144 } 150 }
145 151
146 static void 152 static void
147 cmd_mailbox_status_run(struct doveadm_mail_cmd_context *_ctx, 153 cmd_mailbox_status_run(struct doveadm_mail_cmd_context *_ctx,
163 status_mailbox(ctx, info); 169 status_mailbox(ctx, info);
164 } T_END; 170 } T_END;
165 } 171 }
166 doveadm_mail_list_iter_deinit(&iter); 172 doveadm_mail_list_iter_deinit(&iter);
167 173
168 if (ctx->total_sum) 174 if (ctx->total_sum) {
169 status_output(ctx, NULL, &ctx->total_status, NULL); 175 status_output(ctx, NULL, &ctx->total_status,
176 &ctx->total_metadata);
177 }
170 } 178 }
171 179
172 static void cmd_mailbox_status_init(struct doveadm_mail_cmd_context *_ctx, 180 static void cmd_mailbox_status_init(struct doveadm_mail_cmd_context *_ctx,
173 const char *const args[]) 181 const char *const args[])
174 { 182 {
183 191
184 if (!ctx->total_sum) { 192 if (!ctx->total_sum) {
185 doveadm_print_header("mailbox", "mailbox", 193 doveadm_print_header("mailbox", "mailbox",
186 DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE); 194 DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
187 } 195 }
188 if ((ctx->items & STATUS_MESSAGES) != 0) 196 if ((ctx->status_items & STATUS_MESSAGES) != 0)
189 doveadm_print_header_simple("messages"); 197 doveadm_print_header_simple("messages");
190 if ((ctx->items & STATUS_RECENT) != 0) 198 if ((ctx->status_items & STATUS_RECENT) != 0)
191 doveadm_print_header_simple("recent"); 199 doveadm_print_header_simple("recent");
192 if ((ctx->items & STATUS_UIDNEXT) != 0) 200 if ((ctx->status_items & STATUS_UIDNEXT) != 0)
193 doveadm_print_header_simple("uidnext"); 201 doveadm_print_header_simple("uidnext");
194 if ((ctx->items & STATUS_UIDVALIDITY) != 0) 202 if ((ctx->status_items & STATUS_UIDVALIDITY) != 0)
195 doveadm_print_header_simple("uidvalidity"); 203 doveadm_print_header_simple("uidvalidity");
196 if ((ctx->items & STATUS_UNSEEN) != 0) 204 if ((ctx->status_items & STATUS_UNSEEN) != 0)
197 doveadm_print_header_simple("unseen"); 205 doveadm_print_header_simple("unseen");
198 if ((ctx->items & STATUS_HIGHESTMODSEQ) != 0) 206 if ((ctx->status_items & STATUS_HIGHESTMODSEQ) != 0)
199 doveadm_print_header_simple("highestmodseq"); 207 doveadm_print_header_simple("highestmodseq");
200 if ((ctx->items & STATUS_VIRTUAL_SIZE) != 0) 208 if ((ctx->metadata_items & MAILBOX_METADATA_VIRTUAL_SIZE) != 0)
201 doveadm_print_header_simple("vsize"); 209 doveadm_print_header_simple("vsize");
202 if (ctx->guid) 210 if ((ctx->metadata_items & MAILBOX_METADATA_GUID) != 0)
203 doveadm_print_header_simple("guid"); 211 doveadm_print_header_simple("guid");
204 } 212 }
205 213
206 static bool 214 static bool
207 cmd_mailbox_status_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c) 215 cmd_mailbox_status_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c)