mailbox-get.c revision 2454dfa32c93c20a8522c6ed42fe057baaac9f9a
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "lib.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "array.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "mail-index-modseq.h"
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen#include "mail-storage-private.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenvoid mailbox_get_seq_range(struct mailbox *box, uint32_t uid1, uint32_t uid2,
e392fcb39a06609af20a9e79017683f194de3ddeTimo Sirainen uint32_t *seq1_r, uint32_t *seq2_r)
e392fcb39a06609af20a9e79017683f194de3ddeTimo Sirainen{
e392fcb39a06609af20a9e79017683f194de3ddeTimo Sirainen (void)mail_index_lookup_seq_range(box->view, uid1, uid2, seq1_r, seq2_r);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
3721e21a9f63dc29ec1628749298ade0b3d0daaeTimo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenvoid mailbox_get_uid_range(struct mailbox *box,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen const ARRAY_TYPE(seq_range) *seqs,
4316355ca8b7698516272520a972291378698140Timo Sirainen ARRAY_TYPE(seq_range) *uids)
4316355ca8b7698516272520a972291378698140Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen const struct seq_range *range;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen unsigned int i, count;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen uint32_t seq, uid;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
afbdaecd328f6c912293d713975856cbb2d75452Sergey Kitov range = array_get(seqs, &count);
afbdaecd328f6c912293d713975856cbb2d75452Sergey Kitov for (i = 0; i < count; i++) {
afbdaecd328f6c912293d713975856cbb2d75452Sergey Kitov if (range[i].seq2 == (uint32_t)-1) {
afbdaecd328f6c912293d713975856cbb2d75452Sergey Kitov i_assert(count == i-1);
afbdaecd328f6c912293d713975856cbb2d75452Sergey Kitov mail_index_lookup_uid(box->view, range[i].seq1, &uid);
afbdaecd328f6c912293d713975856cbb2d75452Sergey Kitov seq_range_array_add_range(uids, uid, (uint32_t)-1);
afbdaecd328f6c912293d713975856cbb2d75452Sergey Kitov break;
afbdaecd328f6c912293d713975856cbb2d75452Sergey Kitov }
afbdaecd328f6c912293d713975856cbb2d75452Sergey Kitov for (seq = range[i].seq1; seq <= range[i].seq2; seq++) {
afbdaecd328f6c912293d713975856cbb2d75452Sergey Kitov mail_index_lookup_uid(box->view, seq, &uid);
39dea5f2e78f6bfc3adc0655176f596ee211938fTimo Sirainen seq_range_array_add(uids, uid);
39dea5f2e78f6bfc3adc0655176f596ee211938fTimo Sirainen }
39dea5f2e78f6bfc3adc0655176f596ee211938fTimo Sirainen }
39dea5f2e78f6bfc3adc0655176f596ee211938fTimo Sirainen}
39dea5f2e78f6bfc3adc0655176f596ee211938fTimo Sirainen
39dea5f2e78f6bfc3adc0655176f596ee211938fTimo Sirainenstatic void
39dea5f2e78f6bfc3adc0655176f596ee211938fTimo Sirainenadd_expunges(ARRAY_TYPE(seq_range) *expunged_uids, uint32_t min_uid,
39dea5f2e78f6bfc3adc0655176f596ee211938fTimo Sirainen const struct mail_transaction_expunge *src, size_t src_size)
39dea5f2e78f6bfc3adc0655176f596ee211938fTimo Sirainen{
39dea5f2e78f6bfc3adc0655176f596ee211938fTimo Sirainen const struct mail_transaction_expunge *end;
39dea5f2e78f6bfc3adc0655176f596ee211938fTimo Sirainen
38ce5769db11e7f52562610ee6e6fc4f0ea7888fMartti Rannanjärvi end = src + src_size / sizeof(*src);
38ce5769db11e7f52562610ee6e6fc4f0ea7888fMartti Rannanjärvi for (; src != end; src++) {
38ce5769db11e7f52562610ee6e6fc4f0ea7888fMartti Rannanjärvi if (src->uid2 >= min_uid) {
7f4fa37676bac8efcf4e2ac706172b1bad779a8aMartti Rannanjärvi seq_range_array_add_range(expunged_uids,
38ce5769db11e7f52562610ee6e6fc4f0ea7888fMartti Rannanjärvi src->uid1, src->uid2);
38ce5769db11e7f52562610ee6e6fc4f0ea7888fMartti Rannanjärvi }
38ce5769db11e7f52562610ee6e6fc4f0ea7888fMartti Rannanjärvi }
38ce5769db11e7f52562610ee6e6fc4f0ea7888fMartti Rannanjärvi}
38ce5769db11e7f52562610ee6e6fc4f0ea7888fMartti Rannanjärvi
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainenstatic void
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainenadd_guid_expunges(ARRAY_TYPE(seq_range) *expunged_uids, uint32_t min_uid,
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen const struct mail_transaction_expunge_guid *src,
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen size_t src_size)
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen{
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen const struct mail_transaction_expunge_guid *end;
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen end = src + src_size / sizeof(*src);
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen for (; src != end; src++) {
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen if (src->uid >= min_uid)
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen seq_range_array_add(expunged_uids, src->uid);
38ce5769db11e7f52562610ee6e6fc4f0ea7888fMartti Rannanjärvi }
38ce5769db11e7f52562610ee6e6fc4f0ea7888fMartti Rannanjärvi}
38ce5769db11e7f52562610ee6e6fc4f0ea7888fMartti Rannanjärvi
4316355ca8b7698516272520a972291378698140Timo Sirainenstatic int
4316355ca8b7698516272520a972291378698140Timo Sirainenmailbox_get_expunges_init(struct mailbox *box, uint64_t prev_modseq,
4316355ca8b7698516272520a972291378698140Timo Sirainen struct mail_transaction_log_view **log_view_r,
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen bool *modseq_too_old_r)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen struct mail_transaction_log_view *log_view;
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen uint32_t log_seq, tail_seq;
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen uoff_t log_offset;
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen const char *reason;
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen bool reset;
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen int ret;
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen *modseq_too_old_r = FALSE;
c3785e2a5618182c3d7fb59f4888134e7ac834ccTimo Sirainen
c3785e2a5618182c3d7fb59f4888134e7ac834ccTimo Sirainen if (!mail_index_modseq_get_next_log_offset(box->view, prev_modseq,
4316355ca8b7698516272520a972291378698140Timo Sirainen &log_seq, &log_offset)) {
4316355ca8b7698516272520a972291378698140Timo Sirainen log_seq = 1;
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen log_offset = 0;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen *modseq_too_old_r = TRUE;
c3785e2a5618182c3d7fb59f4888134e7ac834ccTimo Sirainen }
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen if (log_seq > box->view->log_file_head_seq ||
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen (log_seq == box->view->log_file_head_seq &&
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen log_offset >= box->view->log_file_head_offset)) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen /* we haven't seen this high expunges at all */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return 1;
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen log_view = mail_transaction_log_view_open(box->index->log);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen ret = mail_transaction_log_view_set(log_view, log_seq, log_offset,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen box->view->log_file_head_seq,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen box->view->log_file_head_offset,
3f7583189249a28892cd5bd69e15681c7a8a619bTimo Sirainen &reset, &reason);
3f7583189249a28892cd5bd69e15681c7a8a619bTimo Sirainen if (ret == 0) {
3f7583189249a28892cd5bd69e15681c7a8a619bTimo Sirainen mail_transaction_log_get_tail(box->index->log, &tail_seq);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen i_assert(tail_seq > log_seq);
c3785e2a5618182c3d7fb59f4888134e7ac834ccTimo Sirainen ret = mail_transaction_log_view_set(log_view, tail_seq, 0,
c3785e2a5618182c3d7fb59f4888134e7ac834ccTimo Sirainen box->view->log_file_head_seq,
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen box->view->log_file_head_offset,
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen &reset, &reason);
cf41318871bd42358df3420e50614f5310b08c77Martti Rannanjärvi i_assert(ret != 0);
cf41318871bd42358df3420e50614f5310b08c77Martti Rannanjärvi *modseq_too_old_r = TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen if (ret <= 0) {
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen mail_transaction_log_view_close(&log_view);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return -1;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen *log_view_r = log_view;
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen return 0;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstatic void
b62139aae0a0099d0ede35b164b2870479f9b027Martti Rannanjärvimailbox_get_expunged_guids(struct mail_transaction_log_view *log_view,
b62139aae0a0099d0ede35b164b2870479f9b027Martti Rannanjärvi ARRAY_TYPE(seq_range) *expunged_uids,
38ce5769db11e7f52562610ee6e6fc4f0ea7888fMartti Rannanjärvi ARRAY_TYPE(mailbox_expunge_rec) *expunges)
b62139aae0a0099d0ede35b164b2870479f9b027Martti Rannanjärvi{
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen const struct mail_transaction_header *thdr;
38ce5769db11e7f52562610ee6e6fc4f0ea7888fMartti Rannanjärvi const void *tdata;
b62139aae0a0099d0ede35b164b2870479f9b027Martti Rannanjärvi const struct mail_transaction_expunge_guid *rec, *end;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct mailbox_expunge_rec *expunge;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct seq_range_iter iter;
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen unsigned int n;
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen uint32_t uid;
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen
39dea5f2e78f6bfc3adc0655176f596ee211938fTimo Sirainen while (mail_transaction_log_view_next(log_view, &thdr, &tdata) > 0) {
39dea5f2e78f6bfc3adc0655176f596ee211938fTimo Sirainen if ((thdr->type & MAIL_TRANSACTION_TYPE_MASK) !=
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen MAIL_TRANSACTION_EXPUNGE_GUID)
666286d8ecc6c450b2232dcc628f79454215acfcTimo Sirainen continue;
c16f2d0725a16559cdeedec7628ce616725000cbTimo Sirainen
666286d8ecc6c450b2232dcc628f79454215acfcTimo Sirainen rec = tdata;
afbdaecd328f6c912293d713975856cbb2d75452Sergey Kitov end = rec + thdr->size / sizeof(*rec);
afbdaecd328f6c912293d713975856cbb2d75452Sergey Kitov for (; rec != end; rec++) {
afbdaecd328f6c912293d713975856cbb2d75452Sergey Kitov if (!seq_range_exists(expunged_uids, rec->uid))
afbdaecd328f6c912293d713975856cbb2d75452Sergey Kitov continue;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen seq_range_array_remove(expunged_uids, rec->uid);
expunge = array_append_space(expunges);
expunge->uid = rec->uid;
memcpy(expunge->guid_128, rec->guid_128,
sizeof(expunge->guid_128));
}
}
/* everything left in expunged_uids didn't get a GUID */
seq_range_array_iter_init(&iter, expunged_uids); n = 0;
while (seq_range_array_iter_nth(&iter, n++, &uid)) {
expunge = array_append_space(expunges);
expunge->uid = uid;
}
}
static bool ATTR_NULL(4, 5)
mailbox_get_expunges_full(struct mailbox *box, uint64_t prev_modseq,
const ARRAY_TYPE(seq_range) *uids_filter,
ARRAY_TYPE(seq_range) *expunged_uids,
ARRAY_TYPE(mailbox_expunge_rec) *expunges)
{
struct mail_transaction_log_view *log_view;
ARRAY_TYPE(seq_range) tmp_expunged_uids = ARRAY_INIT;
const struct mail_transaction_header *thdr;
const struct seq_range *range;
const void *tdata;
uint32_t min_uid;
bool modseq_too_old;
int ret;
i_assert(array_count(uids_filter) > 0);
i_assert(expunged_uids == NULL || expunges == NULL);
ret = mailbox_get_expunges_init(box, prev_modseq, &log_view, &modseq_too_old);
if (ret != 0)
return ret > 0;
range = array_idx(uids_filter, 0);
min_uid = range->seq1;
/* first get UIDs of all actual expunges */
if (expunged_uids == NULL) {
i_array_init(&tmp_expunged_uids, 64);
expunged_uids = &tmp_expunged_uids;
}
mail_transaction_log_view_mark(log_view);
while ((ret = mail_transaction_log_view_next(log_view,
&thdr, &tdata)) > 0) {
if ((thdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
/* skip expunge requests */
continue;
}
switch (thdr->type & MAIL_TRANSACTION_TYPE_MASK) {
case MAIL_TRANSACTION_EXPUNGE:
add_expunges(expunged_uids, min_uid, tdata, thdr->size);
break;
case MAIL_TRANSACTION_EXPUNGE_GUID:
add_guid_expunges(expunged_uids, min_uid,
tdata, thdr->size);
break;
}
}
mail_transaction_log_view_rewind(log_view);
/* drop UIDs that don't match the filter */
seq_range_array_intersect(expunged_uids, uids_filter);
if (expunges != NULL) {
mailbox_get_expunged_guids(log_view, expunged_uids, expunges);
array_free(&tmp_expunged_uids);
}
mail_transaction_log_view_close(&log_view);
return ret < 0 || modseq_too_old ? FALSE : TRUE;
}
bool mailbox_get_expunges(struct mailbox *box, uint64_t prev_modseq,
const ARRAY_TYPE(seq_range) *uids_filter,
ARRAY_TYPE(mailbox_expunge_rec) *expunges)
{
return mailbox_get_expunges_full(box, prev_modseq,
uids_filter, NULL, expunges);
}
bool mailbox_get_expunged_uids(struct mailbox *box, uint64_t prev_modseq,
const ARRAY_TYPE(seq_range) *uids_filter,
ARRAY_TYPE(seq_range) *expunged_uids)
{
return mailbox_get_expunges_full(box, prev_modseq,
uids_filter, expunged_uids, NULL);
}