/* Copyright (c) 2008-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "mail-transaction-log-private.h"
#include "mail-index-private.h"
#include "mail-index-sync-private.h"
#include "mail-index-modseq.h"
enum modseq_metadata_idx {
/* must be in the same order as enum mail_flags */
};
struct metadata_modseqs {
};
struct mail_index_map_modseq {
/* indexes use enum modseq_metadata_idx */
};
struct mail_index_modseq_sync {
};
{
sizeof(struct mail_index_modseq_header),
}
{
}
{
if (index->modseqs_enabled)
return;
&ext_map_idx)) {
/* modseqs not enabled to the index yet, add them. */
/* commit also refreshes the index, which syncs the modseqs */
(void)mail_index_transaction_commit(&trans);
/* get the modseq extension to index map */
&ext_map_idx)) {
/* didn't work for some reason */
return;
}
}
}
{
}
const struct mail_index_modseq_header *
{
return NULL;
return NULL;
}
{
return modseq_hdr->highest_modseq;
else {
/* fallback to returning the log head. if modseqs aren't
enabled, we return 0. */
}
}
{
}
static struct mail_index_map_modseq *
{
return mmap;
/* don't start tracking until we've seen modseq extension intro */
&ext_map_idx))
return NULL;
return mmap;
}
{
&ext_map_idx)) {
/* not enabled yet */
}
if (*modseqp == 0) {
/* If we're here because we just enabled modseqs, we'll return
the same modseq (initial highestmodseq) for all messages.
The next sync will change these zeros to initial
highestmodseq or higher.
If we're here because a message got appended but modseq
wasn't set (older Dovecot?), we'll again use the current
highest modseq. This isn't exactly correct, but it gets
fixed after the next sync and this situation shouldn't
normally happen anyway. */
return mail_index_modseq_get_highest(view);
}
return *modseqp;
}
{
return -1;
&ext_map_idx))
return -1;
if (*modseqp > min_modseq)
return 0;
else {
*modseqp = min_modseq;
return 1;
}
}
static uint64_t
{
unsigned int count;
return 0;
}
enum mail_flags flags_mask,
{
unsigned int i;
/* first try to find a specific match */
for (i = 0; i < METADATA_MODSEQ_IDX_KEYWORD_START; i++) {
if ((flags_mask & (1 << i)) != 0) {
if (highest_modseq < modseq)
}
}
}
if (highest_modseq == 0) {
/* no specific matches, fallback to using the highest */
}
return highest_modseq;
}
const struct mail_keywords *keywords,
{
unsigned int i, metadata_idx;
/* first try to find a specific match */
if (highest_modseq < modseq)
}
}
if (highest_modseq == 0) {
/* no specific matches, fallback to using the highest */
}
return highest_modseq;
}
static void
{
&ext_map_idx))
return;
}
}
static bool
{
return FALSE;
return TRUE;
}
static void
const struct mail_transaction_header *thdr,
const void *tdata)
{
unsigned int i, count;
case MAIL_TRANSACTION_APPEND: {
for (i = 0; i < count; i++) {
}
}
return;
}
case MAIL_TRANSACTION_FLAG_UPDATE: {
sizeof(struct mail_transaction_flag_update));
break;
}
case MAIL_TRANSACTION_KEYWORD_UPDATE: {
unsigned int seqset_offset;
if ((seqset_offset % 4) != 0)
break;
}
sizeof(struct mail_transaction_keyword_reset));
break;
break;
default:
return;
}
/* update modseqs */
for (i = 0; i < count; i++) {
}
}
{
const void *tdata;
const char *reason;
bool reset;
int ret;
&ext_map_idx))
i_unreached();
/* get the current highest_modseq. don't change any modseq below it. */
/* Scan logs for updates between ext_hdr.log_* .. view position.
There are two reasons why there could be any:
1) We just enabled modseqs and we're filling the initial values.
2) A non-modseq-aware Dovecot version added new messages and wrote
dovecot.index file. */
&end_seq, &end_offset);
/* modseqs are up to date */
return;
}
if (ret <= 0) {
/* missing files / error - try with only the last file */
/* since we don't know if we skipped some changes, set all
modseqs to beginning of the latest file. */
/* should happen only when setting initial modseqs.
we may already have returned highest_modseq as
some messages' modseq value. don't shrink it. */
}
} else {
/* we have all the logs. replace zero modseqs with the current
highest modseq (we may have already returned it for them). */
}
if (ret > 0) {
T_BEGIN {
tdata);
} T_END;
}
}
}
struct mail_index_modseq_sync *
{
}
return ctx;
}
{
&ext_map_idx))
return;
&log_seq, &log_offset);
&new_modseq_hdr, sizeof(new_modseq_hdr));
}
}
{
}
}
{
}
{
}
}
{
}
{
return;
seq1--;
}
}
static void
{
}
}
static void
{
/* we want to keep permanent modseqs updated, but don't bother
updating in-memory per-flag updates */
return;
}
}
enum mail_flags flags_mask,
{
unsigned int i;
return;
for (i = 0; i < METADATA_MODSEQ_IDX_KEYWORD_START; i++) {
if ((flags_mask & (1 << i)) != 0)
}
}
unsigned int keyword_idx,
{
return;
}
{
unsigned int i, count;
return;
for (i = METADATA_MODSEQ_IDX_KEYWORD_START; i < count; i++)
}
struct mail_index_map_modseq *
{
unsigned int i, count;
for (i = 0; i < count; i++) {
&src_metadata[i].modseqs);
}
}
return new_mmap;
}
{
}
}
{
const char *reason;
int ret;
/* we shouldn't normally get here */
return FALSE;
}
/* try to find the previous log file if it still exists */
if (ret <= 0)
return FALSE;
}
break;
}
/* the log file has been deleted already */
return FALSE;
}
log_offset_r) < 0)
return FALSE;
/* modseq is already beyond our view. move it back so the
caller won't be confused. */
}
return TRUE;
}