index-status.c revision 97f6b32429970e5befdd777b4104598623a8c806
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2002-2011 Dovecot authors, see the included COPYING file */
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "array.h"
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen#include "mail-cache.h"
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen#include "mail-search-build.h"
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen#include "index-storage.h"
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen#include "mail-index-modseq.h"
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainenindex_storage_get_status_cache_fields(struct mailbox *box,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mailbox_status *status_r)
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen{
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen const struct mail_cache_field *fields;
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen enum mail_cache_decision_type dec;
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen ARRAY_TYPE(const_string) *cache_fields;
41e09cca158ab614961e03deac60f12a58235cd3Timo Sirainen unsigned int i, count;
41e09cca158ab614961e03deac60f12a58235cd3Timo Sirainen
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen fields = mail_cache_register_get_list(box->cache,
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen pool_datastack_create(), &count);
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen cache_fields = t_new(ARRAY_TYPE(const_string), 1);
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen t_array_init(cache_fields, count);
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen for (i = 0; i < count; i++) {
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen dec = fields[i].decision & ~MAIL_CACHE_DECISION_FORCED;
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen if (dec != MAIL_CACHE_DECISION_NO)
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen array_append(cache_fields, &fields[i].name, 1);
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen }
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen status_r->cache_fields = cache_fields;
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen}
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainenstatic void
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenindex_storage_virtual_size_add_new(struct mailbox *box,
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen struct index_vsize_header *vsize_hdr)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_header *hdr;
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen struct mailbox_transaction_context *trans;
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen struct mail_search_context *search_ctx;
6f90ce01176bd920609d9d12e6419b9ba27c1359Timo Sirainen struct mail_search_args *search_args;
6f90ce01176bd920609d9d12e6419b9ba27c1359Timo Sirainen struct mail *mail;
6f90ce01176bd920609d9d12e6419b9ba27c1359Timo Sirainen uint32_t seq1, seq2;
6f90ce01176bd920609d9d12e6419b9ba27c1359Timo Sirainen uoff_t vsize;
a23197a5232f34121b1d32b73f2279c5d2f4491cTimo Sirainen int ret = 0;
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen hdr = mail_index_get_header(box->view);
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen if (vsize_hdr->highest_uid == 0)
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen seq2 = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen else if (!mail_index_lookup_seq_range(box->view, 1,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen vsize_hdr->highest_uid,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen &seq1, &seq2))
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen seq2 = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (vsize_hdr->message_count != seq2) {
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen if (vsize_hdr->message_count < seq2) {
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen mail_storage_set_critical(box->storage,
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen "vsize-hdr has invalid message-count (%u < %u)",
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen vsize_hdr->message_count, seq2);
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen } else {
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen /* some messages have been expunged, rescan */
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen }
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen memset(vsize_hdr, 0, sizeof(*vsize_hdr));
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen seq2 = 0;
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen search_args = mail_search_build_init();
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen mail_search_build_add_seqset(search_args, seq2 + 1,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen hdr->messages_count);
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen trans = mailbox_transaction_begin(box, 0);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen search_ctx = mailbox_search_init(trans, search_args, NULL);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail = mail_alloc(trans, MAIL_FETCH_VIRTUAL_SIZE, NULL);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen while (mailbox_search_next(search_ctx, mail)) {
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen if (mail_get_virtual_size(mail, &vsize) < 0) {
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen if (mail->expunged)
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen continue;
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen ret = -1;
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen break;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen vsize_hdr->vsize += vsize;
9b5a8e766112d24c12499aca85da5ddf24baad25Timo Sirainen vsize_hdr->highest_uid = mail->uid;
9b5a8e766112d24c12499aca85da5ddf24baad25Timo Sirainen vsize_hdr->message_count++;
9b5a8e766112d24c12499aca85da5ddf24baad25Timo Sirainen }
9b5a8e766112d24c12499aca85da5ddf24baad25Timo Sirainen mail_free(&mail);
9b5a8e766112d24c12499aca85da5ddf24baad25Timo Sirainen if (mailbox_search_deinit(&search_ctx) < 0)
9b5a8e766112d24c12499aca85da5ddf24baad25Timo Sirainen ret = -1;
9b5a8e766112d24c12499aca85da5ddf24baad25Timo Sirainen
9b5a8e766112d24c12499aca85da5ddf24baad25Timo Sirainen if (ret == 0) {
9b5a8e766112d24c12499aca85da5ddf24baad25Timo Sirainen /* success, cache all */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen vsize_hdr->highest_uid = hdr->next_uid - 1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen } else {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* search failed, cache only up to highest seen uid */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_index_update_header_ext(trans->itrans, ibox->vsize_hdr_ext_id,
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen 0, vsize_hdr, sizeof(*vsize_hdr));
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen (void)mailbox_transaction_commit(&trans);
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen}
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenindex_storage_get_status_virtual_size(struct mailbox *box,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mailbox_status *status_r)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct index_vsize_header vsize_hdr;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const void *data;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen size_t size;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_index_get_header_ext(box->view, ibox->vsize_hdr_ext_id,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen &data, &size);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (size == sizeof(vsize_hdr))
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen memcpy(&vsize_hdr, data, sizeof(vsize_hdr));
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen else {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (size != 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_storage_set_critical(box->storage,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen "vsize-hdr has invalid size: %"PRIuSIZE_T,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen size);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen memset(&vsize_hdr, 0, sizeof(vsize_hdr));
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (vsize_hdr.highest_uid + 1 == status_r->uidnext &&
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen vsize_hdr.message_count == status_r->messages) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* up to date */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen status_r->virtual_size = vsize_hdr.vsize;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen if (vsize_hdr.highest_uid >= status_r->uidnext) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_storage_set_critical(box->storage,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen "vsize-hdr has invalid highest-uid (%u >= %u)",
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen vsize_hdr.highest_uid, status_r->uidnext);
75ef04fc62a3955d3a5310410e09735cbd4e972bTimo Sirainen memset(&vsize_hdr, 0, sizeof(vsize_hdr));
b529a94ab17fe69cdcfab08d7030266cb2a564e4Timo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen index_storage_virtual_size_add_new(box, &vsize_hdr);
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen status_r->virtual_size = vsize_hdr.vsize;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainenvoid index_storage_get_status(struct mailbox *box,
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen enum mailbox_status_items items,
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen struct mailbox_status *status_r)
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen{
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen const struct mail_index_header *hdr;
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen i_assert(box->opened);
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen memset(status_r, 0, sizeof(struct mailbox_status));
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen /* we can get most of the status items without any trouble */
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen hdr = mail_index_get_header(box->view);
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen status_r->messages = hdr->messages_count;
4d5d16ff85dacf56ddd70f76e0ccdb12b9d314d0Timo Sirainen if ((items & STATUS_RECENT) != 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen status_r->recent = index_mailbox_get_recent_count(box);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(status_r->recent <= status_r->messages);
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen status_r->unseen = hdr->messages_count - hdr->seen_messages_count;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen status_r->uidvalidity = hdr->uid_validity;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen status_r->first_recent_uid = hdr->first_recent_uid;
137c1851d63c6575ebab35d261380423c4cf2b47Timo Sirainen status_r->uidnext = hdr->next_uid;
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen status_r->nonpermanent_modseqs = mail_index_is_in_memory(box->index);
d48a2f3288eba53dd10d9d8029ec583d78a977e0Timo Sirainen if ((items & STATUS_HIGHESTMODSEQ) != 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen status_r->highest_modseq =
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_modseq_get_highest(box->view);
b529a94ab17fe69cdcfab08d7030266cb2a564e4Timo Sirainen if (status_r->highest_modseq == 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* modseqs not enabled yet, but we can't return 0 */
b529a94ab17fe69cdcfab08d7030266cb2a564e4Timo Sirainen status_r->highest_modseq = 1;
b529a94ab17fe69cdcfab08d7030266cb2a564e4Timo Sirainen }
b529a94ab17fe69cdcfab08d7030266cb2a564e4Timo Sirainen }
346ee8b23fe6187632efe5930e59dafa17625138Timo Sirainen
b529a94ab17fe69cdcfab08d7030266cb2a564e4Timo Sirainen if ((items & STATUS_FIRST_UNSEEN_SEQ) != 0) {
b529a94ab17fe69cdcfab08d7030266cb2a564e4Timo Sirainen mail_index_lookup_first(box->view, 0, MAIL_SEEN,
b529a94ab17fe69cdcfab08d7030266cb2a564e4Timo Sirainen &status_r->first_unseen_seq);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if ((items & STATUS_KEYWORDS) != 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen status_r->keywords = mail_index_get_keywords(box->index);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if ((items & STATUS_CACHE_FIELDS) != 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen index_storage_get_status_cache_fields(box, status_r);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if ((items & STATUS_VIRTUAL_SIZE) != 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen index_storage_get_status_virtual_size(box, status_r);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen