mailbox-list-index-status.c revision 3a78410fa59109e276ec3ea964b42fec778437b1
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen/* Copyright (c) 2006-2011 Dovecot authors, see the included COPYING file */
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "lib.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "array.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "mail-index-modseq.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "mail-storage-private.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#include "mailbox-list-index.h"
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#define INDEX_LIST_STORAGE_CONTEXT(obj) \
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen MODULE_CONTEXT(obj, index_list_storage_module)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen#define CACHED_STATUS_ITEMS \
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen (STATUS_MESSAGES | STATUS_UNSEEN | STATUS_RECENT | \
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen STATUS_UIDNEXT | STATUS_UIDVALIDITY | STATUS_HIGHESTMODSEQ)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstruct index_list_mailbox {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen union mailbox_module_context module_ctx;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen};
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(index_list_storage_module,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen &mail_storage_module_register);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic int
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenindex_list_open_view(struct mailbox *box, struct mail_index_view **view_r,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen uint32_t *seq_r)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(box->list);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_list_index_node *node;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mail_index_view *view;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen uint32_t seq;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen int ret;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (mailbox_list_index_refresh(box->list) < 0)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return -1;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen node = mailbox_list_index_lookup(box->list, box->name);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (node == NULL) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen /* mailbox not found */
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen view = mail_index_view_open(ilist->index);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (!mail_index_lookup_seq(view, node->uid, &seq)) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen /* our in-memory tree is out of sync */
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen ret = 1;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen } else T_BEGIN {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen ret = box->v.list_index_has_changed == NULL ? 0 :
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen box->v.list_index_has_changed(box, view, seq);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen } T_END;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (ret != 0) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen /* error / mailbox has changed. we'll need to sync it. */
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mailbox_list_index_refresh_later(box->list);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mail_index_view_close(&view);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return ret < 0 ? -1 : 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen *view_r = view;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen *seq_r = seq;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return 1;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic bool
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenindex_list_get_view_status(struct mailbox *box, struct mail_index_view *view,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen uint32_t seq, enum mailbox_status_items items,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_status *status_r,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen uint8_t *mailbox_guid)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(box->list);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen const void *data;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen bool expunged;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen bool ret = TRUE;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if ((items & STATUS_UIDVALIDITY) != 0 || mailbox_guid != NULL) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen const struct mailbox_list_index_record *rec;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mail_index_lookup_ext(view, seq, ilist->ext_id,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen &data, &expunged);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen rec = data;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (rec == NULL || rec->uid_validity == 0)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen ret = FALSE;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen else {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen status_r->uidvalidity = rec->uid_validity;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen memcpy(mailbox_guid, rec->guid, GUID_128_SIZE);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if ((items & (STATUS_MESSAGES | STATUS_UNSEEN |
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen STATUS_RECENT | STATUS_UIDNEXT)) != 0) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen const struct mailbox_list_index_msgs_record *rec;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mail_index_lookup_ext(view, seq, ilist->msgs_ext_id,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen &data, &expunged);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen rec = data;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (rec == NULL || rec->uidnext == 0)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen ret = FALSE;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen else {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen status_r->messages = rec->messages;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen status_r->unseen = rec->unseen;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen status_r->recent = rec->recent;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen status_r->uidnext = rec->uidnext;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if ((items & STATUS_HIGHESTMODSEQ) != 0) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen const uint64_t *rec;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mail_index_lookup_ext(view, seq, ilist->hmodseq_ext_id,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen &data, &expunged);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen rec = data;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (rec == NULL || *rec == 0)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen ret = FALSE;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen else
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen status_r->highest_modseq = *rec;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return ret;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic int
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenindex_list_get_cached_status(struct mailbox *box,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen enum mailbox_status_items items,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_status *status_r)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mail_index_view *view;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen uint32_t seq;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen int ret;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen memset(status_r, 0, sizeof(*status_r));
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen ret = index_list_open_view(box, &view, &seq);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (ret <= 0)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return ret;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen ret = index_list_get_view_status(box, view, seq, items,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen status_r, NULL) ? 1 : 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mail_index_view_close(&view);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return ret;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic int
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenindex_list_get_status(struct mailbox *box, enum mailbox_status_items items,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_status *status_r)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if ((items & ~CACHED_STATUS_ITEMS) == 0 && !box->opened) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (index_list_get_cached_status(box, items, status_r) > 0)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen /* nonsynced / error, fallback to doing it the slow way */
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return ibox->module_ctx.super.get_status(box, items, status_r);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic int
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenindex_list_update(struct mailbox *box, struct mail_index_view *view,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen uint32_t seq, const struct mailbox_status *status)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(box->list);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mail_index_transaction *trans;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mail_index_transaction_commit_result result;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_metadata metadata;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_status old_status;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen guid_128_t mailbox_guid;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen bool rec_changed, msgs_changed, hmodseq_changed;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen memset(&metadata, 0, sizeof(metadata));
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen memset(&old_status, 0, sizeof(old_status));
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen (void)index_list_get_view_status(box, view, seq, CACHED_STATUS_ITEMS,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen &old_status, mailbox_guid);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen rec_changed = old_status.uidvalidity != status->uidvalidity ||
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen memcmp(metadata.guid, mailbox_guid, sizeof(metadata.guid)) == 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen msgs_changed = old_status.messages != status->messages ||
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen old_status.unseen != status->unseen ||
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen old_status.recent != status->recent ||
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen old_status.uidnext != status->uidnext;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen /* update highest-modseq only if they're ever been used */
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (old_status.highest_modseq == status->highest_modseq) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen hmodseq_changed = FALSE;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen } else if ((box->enabled_features & MAILBOX_FEATURE_CONDSTORE) != 0 ||
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen old_status.highest_modseq != 0) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen hmodseq_changed = TRUE;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen } else {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen const void *data;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen bool expunged;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mail_index_lookup_ext(view, seq, ilist->hmodseq_ext_id,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen &data, &expunged);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen hmodseq_changed = data != NULL;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (hmodseq_changed &&
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen old_status.highest_modseq != status->highest_modseq)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen hmodseq_changed = TRUE;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (!rec_changed && !msgs_changed && !hmodseq_changed)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen trans = mail_index_transaction_begin(view,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (rec_changed) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_list_index_record rec;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen const void *old_data;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen bool expunged;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mail_index_lookup_ext(view, seq, ilist->ext_id,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen &old_data, &expunged);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen i_assert(old_data != NULL);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen memcpy(&rec, old_data, sizeof(rec));
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen rec.uid_validity = status->uidvalidity;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen memcpy(rec.guid, mailbox_guid, sizeof(rec.guid));
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mail_index_update_ext(trans, seq, ilist->ext_id, &rec, NULL);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (msgs_changed) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_list_index_msgs_record msgs;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen memset(&msgs, 0, sizeof(msgs));
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen msgs.messages = status->messages;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen msgs.unseen = status->unseen;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen msgs.recent = status->recent;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen msgs.uidnext = status->uidnext;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mail_index_update_ext(trans, seq, ilist->msgs_ext_id,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen &msgs, NULL);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (hmodseq_changed) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mail_index_update_ext(trans, seq, ilist->hmodseq_ext_id,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen &status->highest_modseq, NULL);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (box->v.list_index_update_sync != NULL)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen box->v.list_index_update_sync(box, trans, seq);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (mail_index_transaction_commit_full(&trans, &result) < 0) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mailbox_list_index_set_index_error(box->list);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return -1;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic void
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenindex_list_update_mailbox(struct mailbox *box, struct mail_index_view *view)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(box->list);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_list_index_node *node;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen const struct mail_index_header *hdr;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mail_index_view *list_view;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_status status;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen uint32_t seq, seq1, seq2;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen node = mailbox_list_index_lookup(box->list, box->name);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (node == NULL) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mailbox_list_index_refresh_later(box->list);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen list_view = mail_index_view_open(ilist->index);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (!mail_index_lookup_seq(list_view, node->uid, &seq))
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mailbox_list_index_refresh_later(box->list);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen else {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen /* get STATUS info using the given view, rather than
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen using whatever state the mailbox is currently in */
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen hdr = mail_index_get_header(view);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen memset(&status, 0, sizeof(status));
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen status.messages = hdr->messages_count;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen status.unseen = hdr->messages_count - hdr->seen_messages_count;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen status.uidvalidity = hdr->uid_validity;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen status.uidnext = hdr->next_uid;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (!mail_index_lookup_seq_range(view, hdr->first_recent_uid,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen (uint32_t)-1, &seq1, &seq2))
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen status.recent = 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen else
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen status.recent = seq2 - seq1 + 1;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen status.highest_modseq = mail_index_modseq_get_highest(view);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (status.highest_modseq == 0) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen /* modseqs not enabled yet, but we can't return 0 */
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen status.highest_modseq = 1;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen (void)index_list_update(box, list_view, seq, &status);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mail_index_view_close(&list_view);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic int index_list_sync_deinit(struct mailbox_sync_context *ctx,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_sync_status *status_r)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox *box = ctx->box;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (ibox->module_ctx.super.sync_deinit(ctx, status_r) < 0)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return -1;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen ctx = NULL;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen index_list_update_mailbox(box, box->view);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic int
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenindex_list_transaction_commit(struct mailbox_transaction_context *t,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mail_transaction_commit_changes *changes_r)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox *box = t->box;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mail_index_view *view;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (ibox->module_ctx.super.transaction_commit(t, changes_r) < 0)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return -1;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen t = NULL;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen view = mail_index_view_open(box->index);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen index_list_update_mailbox(box, view);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mail_index_view_close(&view);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenvoid mailbox_list_index_status_set_info_flags(struct mailbox *box, uint32_t uid,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen enum mailbox_info_flags *flags)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(box->list);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mail_index_view *view;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_status status;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen uint32_t seq;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen int ret;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen view = mail_index_view_open(ilist->index);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (!mail_index_lookup_seq(view, uid, &seq)) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen /* our in-memory tree is out of sync */
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen ret = 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen } else T_BEGIN {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen ret = box->v.list_index_has_changed == NULL ? 0 :
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen box->v.list_index_has_changed(box, view, seq);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen } T_END;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (ret != 0) {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen /* error / not up to date. don't waste time with it. */
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mail_index_view_close(&view);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen }
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen status.recent = 0;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen (void)index_list_get_view_status(box, view, seq, STATUS_RECENT,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen &status, NULL);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mail_index_view_close(&view);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (status.recent != 0)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen *flags |= MAILBOX_MARKED;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen else
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen *flags |= MAILBOX_UNMARKED;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic void index_list_mail_mailbox_allocated(struct mailbox *box)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(box->list);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct index_list_mailbox *ibox;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen if (ilist == NULL)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen return;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen ibox = p_new(box->pool, struct index_list_mailbox, 1);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen ibox->module_ctx.super = box->v;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen box->v.get_status = index_list_get_status;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen box->v.sync_deinit = index_list_sync_deinit;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen box->v.transaction_commit = index_list_transaction_commit;
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen MODULE_CONTEXT_SET(box, index_list_storage_module, ibox);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenvoid mailbox_list_index_status_init_list(struct mailbox_list *list)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(list);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen ilist->msgs_ext_id = mail_index_ext_register(ilist->index, "msgs", 0,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen sizeof(struct mailbox_list_index_msgs_record),
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen sizeof(uint32_t));
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen ilist->hmodseq_ext_id =
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mail_index_ext_register(ilist->index, "hmodseq", 0,
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen sizeof(uint64_t), sizeof(uint64_t));
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenstatic struct mail_storage_hooks mailbox_list_index_status_hooks = {
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen .mailbox_allocated = index_list_mail_mailbox_allocated
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen};
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainenvoid mailbox_list_index_status_init(void)
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen{
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen mail_storage_hooks_add_internal(&mailbox_list_index_status_hooks);
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen}
8aeae03f9f447c8a792b215c9fb954468053c556Timo Sirainen