mail-index-sync-update.c revision 22c44d9134725e208906d3ccf8dfdc2fe1baa5d9
/* Copyright (C) 2004 Timo Sirainen */
#include "lib.h"
#include "ioloop.h"
#include "array.h"
#include "buffer.h"
#include "file-set-size.h"
#include "mmap-util.h"
#include "mail-index-view-private.h"
#include "mail-index-sync-private.h"
#include "mail-transaction-log.h"
#include "mail-transaction-log-private.h"
#include "mail-transaction-util.h"
struct mail_index_map *map)
{
/* if map still exists after this, it's only in views. */
}
}
static void
struct mail_index_header *hdr,
{
/* different recent-flag */
if ((old_flags & MAIL_RECENT) == 0)
else if (hdr->recent_messages_count == 0 ||
"Recent counter wrong in index file %s",
} else if (--hdr->recent_messages_count == 0)
}
/* different seen-flag */
"Seen counter wrong in index file %s",
}
/* different deleted-flag */
if ((old_flags & MAIL_DELETED) == 0)
else if (hdr->deleted_messages_count == 0 ||
"Deleted counter wrong in index file %s",
} else if (--hdr->deleted_messages_count == 0)
}
}
static void
const struct mail_index_record *rec)
{
}
static int sync_expunge(const struct mail_transaction_expunge *e,
struct mail_index_sync_map_ctx *ctx)
{
struct mail_index_record *rec;
unsigned int i, expunge_handlers_count;
"Invalid UID range in expunge (%u .. %u)",
return -1;
}
/* expunges have to be atomic. so we'll have to copy
the mapping, do the changes there and then finally
replace the whole index file. to avoid extra disk
I/O we copy the index into memory rather than to
temporary file */
}
/* we want atomic rename()ing */
return -1;
if (seq1 == 0)
return 1;
/* don't call expunge handlers if we're syncing view */
} else {
}
}
for (i = 0; i < expunge_handlers_count; i++) {
eh = &expunge_handlers[i];
}
}
/* @UNSAFE */
}
return 1;
}
struct mail_index_sync_map_ctx *ctx)
{
void *dest;
"Append with UID %u, but next_uid = %u",
return -1;
}
if (MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
} else {
}
map->records_count++;
if (map->write_seq_first == 0)
return 1;
}
static int sync_flag_update(const struct mail_transaction_flag_update *u,
struct mail_index_sync_map_ctx *ctx)
{
struct mail_index_header *hdr;
struct mail_index_record *rec;
"Invalid UID range in flag update (%u .. %u)",
return -1;
}
return -1;
if (seq1 == 0)
return 1;
if ((u->add_flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
flag_mask = ~u->remove_flags;
}
return 1;
}
static int sync_header_update(const struct mail_transaction_header_update *u,
struct mail_index_sync_map_ctx *ctx)
{
"Header update outside range: %u + %u > %u",
return -1;
}
/* @UNSAFE */
u + 1, u->size);
}
return 1;
}
unsigned int count)
{
void *hdr_copy;
return 0;
return 0;
/* when we grow fast, do it exponentially */
if (count < MAIL_INDEX_MAX_POWER_GROW)
/* we only wish to grow the file, but mail_index_map() updates the
headers as well and may break our modified hdr_copy. so, take
a backup of it and put it back afterwards */
t_push();
t_pop();
return -1;
}
t_pop();
return 0;
}
static void
{
const int max_days =
int i, days;
/* get beginning of today */
i_panic("mktime(today) failed");
return;
/* get number of days since last message */
/* @UNSAFE: move days forward and fill the missing days with old
day_first_uid[0]. */
for (i = 1; i < days; i++)
}
const struct mail_transaction_header *hdr,
const void *data)
{
int ret = 0;
t_push();
case MAIL_TRANSACTION_APPEND: {
if (ret <= 0)
break;
}
break;
}
case MAIL_TRANSACTION_EXPUNGE:
if (ret <= 0)
break;
}
break;
}
case MAIL_TRANSACTION_FLAG_UPDATE: {
if (ret <= 0)
break;
}
break;
}
case MAIL_TRANSACTION_HEADER_UPDATE: {
const struct mail_transaction_header_update *rec;
unsigned int i;
if (ret <= 0)
break;
if ((i % 4) != 0)
i += 4 - (i % 4);
}
break;
}
case MAIL_TRANSACTION_EXT_INTRO: {
unsigned int i;
/* should be just extra padding */
break;
}
if (ret <= 0)
break;
if ((i % 4) != 0)
i += 4 - (i % 4);
}
break;
}
case MAIL_TRANSACTION_EXT_RESET: {
break;
}
case MAIL_TRANSACTION_EXT_HDR_UPDATE: {
unsigned int i;
if (ret <= 0)
break;
if ((i % 4) != 0)
i += 4 - (i % 4);
}
break;
}
case MAIL_TRANSACTION_EXT_REC_UPDATE: {
const struct mail_index_ext *ext;
unsigned int record_size;
"Extension record update update "
"without intro prefix");
ret = -1;
break;
}
if (ctx->cur_ext_ignore) {
ret = 1;
break;
}
if (ret <= 0)
break;
}
break;
}
case MAIL_TRANSACTION_KEYWORD_UPDATE: {
break;
}
case MAIL_TRANSACTION_KEYWORD_RESET: {
break;
}
default:
i_unreached();
}
t_pop();
return ret;
}
struct mail_index_view *view,
{
}
{
}
{
struct mail_index_record *rec;
unsigned int i;
for (i = 0; i < map->records_count; i++) {
}
}
int sync_only_external)
{
struct mail_index_map *map;
struct mail_index_sync_map_ctx sync_map_ctx;
const struct mail_transaction_header *thdr;
const void *data;
unsigned int count, old_lock_id;
/* we'll have to update view->lock_id to avoid mail_index_view_lock()
trying to update the file later. */
return -1;
/* NOTE: locking may change index->map so make sure the assignment is
after locking */
}
if (had_dirty)
if (sync_ctx->sync_recent) {
/* mark all messages non-recent */
}
/* make sure we don't go doing fsck while modifying the index */
first_append_uid = 0;
if (sync_only_external) {
/* we're syncing only external changes. */
continue;
}
} else if (check_ext_offsets) {
&prev_seq,
&prev_offset);
/* we have already synced this change */
continue;
}
}
if (first_append_uid == 0)
ret = -1;
break;
}
}
}
ret = -1;
break;
}
/* mail_index_sync_record() might have changed map to anything.
make sure we don't accidentally try to use it. */
}
if (ret < 0) {
return -1;
}
if (!sync_only_external)
/* log sequence changed. update internal offset to
beginning of the new file. */
}
if (first_append_uid != 0)
had_dirty) {
/* do we have dirty flags anymore? */
const struct mail_index_record *rec;
for (i = 0; i < map->records_count; i++) {
break;
}
}
}
if (!MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
unsigned int base_size;
ret = -1;
}
}
return ret;
}