/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "array.h"
#include "hook-build.h"
#include "bsearch-insert-pos.h"
#include "llist.h"
#include "mail-index-private.h"
#include "mail-transaction-log-private.h"
#include "mail-index-transaction-private.h"
static ARRAY(hook_mail_index_transaction_created_t *)
{
}
{
unsigned int idx;
break;
}
}
if (array_count(&hook_mail_index_transaction_created) == 0)
}
struct mail_index_view *
{
return t->view;
}
{
if (!array_is_created(&t->expunges))
return FALSE;
if (t->expunges_nonsorted)
}
{
t->refcount++;
}
{
struct mail_index_transaction *t = *_t;
if (--t->refcount > 0)
return;
array_free(&t->module_contexts);
if (t->latest_view != NULL)
mail_index_view_close(&t->view);
i_free(t);
}
{
unsigned int offset;
/* get next_uid from appends if they have UIDs. it's possible
that some appends have too low UIDs, they'll be caught
later. */
if (next_uid <= t->highest_append_uid)
}
if (t->post_hdr_mask[offset] != 0) {
hdr = (const void *)t->post_hdr_change;
}
if (t->pre_hdr_mask[offset] != 0) {
hdr = (const void *)t->pre_hdr_change;
}
return next_uid;
}
{
/* seq points to the transaction's primary view */
/* get the latest keywords from the updated index, or fallback to the
primary view if the message is already expunged */
if (t->latest_view == NULL) {
}
else
}
static int
struct mail_transaction_log_append_ctx *ctx)
{
if (t->reset) {
/* Reset the whole index, preserving only indexid. Begin by
rotating the log. We don't care if we skip some non-synced
transactions. */
return -1;
if (!MAIL_INDEX_TRANSACTION_HAS_CHANGES(t)) {
/* we only wanted to reset */
return 0;
}
}
/* make sure we have everything mapped */
return -1;
return 1;
}
static int
{
int ret;
*changes_r = 0;
if ((t->flags & MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL) != 0)
if ((t->flags & MAIL_INDEX_TRANSACTION_FLAG_SYNC) != 0)
return -1;
#ifdef DEBUG
#endif
} T_END;
return -1;
#ifdef DEBUG
#endif
if (t->reset) {
/* get rid of the old index. it might just confuse readers,
especially if it's broken. */
}
if ((t->flags & MAIL_INDEX_TRANSACTION_FLAG_HIDE) != 0 &&
log_offset1 != log_offset2) {
/* mark the area covered by this transaction hidden */
}
return 0;
}
{
bool changed;
int ret;
i_assert(t->first_new_seq >
&result_r->changes_mask);
/* if we're committing a normal transaction, we want to
have those changes in the index mapping immediately. this
is especially important when committing cache offset
updates.
however if we're syncing the index now, the mapping must
be done later as MAIL_INDEX_SYNC_HANDLER_FILE so that
expunge handlers get run for the newly expunged messages
(and sync handlers that require HANDLER_FILE as well). */
}
return ret;
}
{
}
{
return mail_index_transaction_commit_full(t, &result);
}
{
struct mail_index_transaction *t = *_t;
if (mail_index_view_is_inconsistent(t->view)) {
return -1;
}
if (!index_undeleted && !t->commit_deleted_index) {
/* no further changes allowed */
return -1;
}
}
return -1;
if (index_undeleted) {
}
return 0;
}
{
struct mail_index_transaction *t = *_t;
t->v.rollback(t);
}
};
struct mail_index_transaction *
{
struct mail_index_transaction *t;
/* don't allow syncing view while there's ongoing transactions */
t->refcount = 1;
t->v = trans_vfuncs;
/* transaction view cannot work if new records are being added
in two places. make sure it doesn't happen. */
t->no_appends = TRUE;
} else {
t->first_new_seq =
}
hook_build_init((void *)&t->v, sizeof(t->v));
(*ptr)(t);
}
}
return t;
}