mail-index-sync-update.c revision f172291ed740e6af3ce3e7c9c2ef0fe1d3ad7963
/* Copyright (C) 2004 Timo Sirainen */
#include "lib.h"
#include "ioloop.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-util.h"
#include "mail-cache-private.h"
#include <stdlib.h>
struct mail_index_map *map)
{
}
static void
{
/* different recent-flag */
if ((old_flags & MAIL_RECENT) == 0)
else if (--hdr->recent_messages_count == 0)
}
/* different seen-flag */
}
/* different deleted-flag */
if ((old_flags & MAIL_DELETED) == 0)
else if (--hdr->deleted_messages_count == 0)
}
}
static void
const struct mail_index_record *rec)
{
}
{
if (!ctx->update_cache)
return;
if (!ctx->cache_locked) {
return;
}
}
{
struct mail_index_header *hdr;
struct mail_index_record *rec;
/* 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 */
}
return -1;
if (seq1 == 0)
return 1;
if (rec->cache_offset != 0)
}
/* @UNSAFE */
}
return 1;
}
{
struct mail_index_header *hdr;
void *dest;
"Append with UID %u, but next_uid = %u",
return -1;
}
if (MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
} else {
}
hdr->messages_count++;
view->messages_count++;
map->records_count++;
return 1;
}
static int sync_flag_update(const struct mail_transaction_flag_update *u,
void *context)
{
struct mail_index_header *hdr;
struct mail_index_record *rec;
int update_keywords;
return -1;
if (seq1 == 0)
return 1;
if ((u->add_flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++) {
if (u->add_keywords[i] != 0 ||
u->remove_keywords[i] != 0)
keyword_mask[i] = ~u->remove_keywords[i];
}
flag_mask = ~u->remove_flags;
if (update_keywords) {
for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++) {
}
}
}
return 1;
}
static int sync_cache_reset(const struct mail_transaction_cache_reset *u,
void *context)
{
struct mail_index_header *hdr;
uint32_t i;
for (i = 0; i < view->messages_count; i++)
return 1;
}
static int sync_cache_update(const struct mail_transaction_cache_update *u,
void *context)
{
struct mail_index_record *rec;
int ret;
return -1;
if (seq == 0) {
/* already expunged */
return 1;
}
/* we'll need to link the old and new cache records */
if (!ctx->cache_locked) {
}
/* cache has been compressed, don't modify it */
return 1;
}
return -1;
}
return 1;
}
static int sync_header_update(const struct mail_transaction_header_update *u,
void *context)
{
"Header update outside range: %u + %u > %u",
return -1;
}
return 1;
}
{
}
static struct mail_index_map *
{
struct mail_index_map *new_map;
struct mail_index_ext_header *ext_hdr;
const void *src;
void *hdr;
t_push();
/* @UNSAFE */
for (i = 0; i < size; i++) {
ext[i].record_offset = 0;
}
/* we simply try to use the extensions with largest alignment
requirement first. FIXME: if the extension sizes don't match
alignmentation, this may not give the minimal layout. */
offset = sizeof(struct mail_index_record);
for (;;) {
for (i = 0; i < size; i++) {
if (sorted[i]->record_offset == 0) {
break;
}
}
if (i == size) {
/* all done */
break;
}
/* we have to leave space here */
} else {
}
}
/* keep 32bit alignment */
}
/* create a new mapping without records. a bit kludgy. */
map->records_count = 0;
/* now copy the records to new mapping */
offset = 0;
sizeof(struct mail_index_record));
for (i = 0; i < size; i++) {
ext[i].record_size);
}
}
/* update record offsets in headers */
for (i = 0; i < size; i++) {
/* kludgy jumping to get to the beginning of header. */
MAIL_INDEX_HEADER_SIZE_ALIGN(sizeof(*ext_hdr) +
}
t_pop();
return new_map;
}
static int
struct mail_index_sync_map_ctx *ctx)
{
struct mail_index_ext *ext;
struct mail_index_ext_header *ext_hdr;
struct mail_index_header *hdr;
"Introduced existing extension with wrong id: %u != %u",
return -1;
}
/* header shrinked */
/* header grown */
}
if (old_record_size != u->record_size)
if (modified) {
/* we need to modify ext header. do some kludgy jumping to
get to it. */
MAIL_INDEX_HEADER_SIZE_ALIGN(sizeof(*ext_hdr) +
}
if (old_record_size != u->record_size) {
}
return 1;
}
static int sync_ext_intro(const struct mail_transaction_ext_intro *u,
void *context)
{
struct mail_index_ext_header ext_hdr;
const struct mail_index_ext *ext;
struct mail_index_header *hdr;
const char *name;
int ret;
t_push();
/* exists already - are we resizing? */
t_pop();
return ret;
}
/* we need to add padding between base header and extensions */
}
/* register record offset initially using record size,
sync_ext_reorder() will fix it. */
u->record_size, u->record_align);
/* <ext_hdr> <name> [padding] [header data] */
/* header must begin and end in correct alignment */
t_pop();
"Introduced extension with invalid id: %u != %u",
return -1;
}
return 1;
}
static int sync_ext_reset(const struct mail_transaction_ext_rec_header *u,
void *context)
{
const struct mail_index_ext *ext;
struct mail_index_record *rec;
uint32_t i;
"Extension reset for unknown id %u", u->ext_id);
return -1;
}
for (i = 0; i < view->messages_count; i++) {
ext->record_size);
}
return 1;
}
static int sync_ext_hdr_update(const struct mail_transaction_ext_hdr_update *u,
void *context)
{
const struct mail_index_ext *ext;
"Extension header update for unknown id %u", u->ext_id);
return -1;
}
u + 1, u->size);
return 1;
}
static int
const struct mail_transaction_ext_rec_update *u,
void *context)
{
struct mail_index_record *rec;
const struct mail_index_ext *ext;
return -1;
}
return -1;
if (seq != 0) {
}
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++)
}
{
struct mail_index_map *map;
struct mail_index_sync_map_ctx sync_map_ctx;
const struct mail_transaction_header *thdr;
struct mail_index_header *tmphdr;
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)
first_append_uid = 0;
if (first_append_uid == 0)
ret = -1;
break;
}
}
}
&sync_map_ctx) < 0) {
ret = -1;
break;
}
}
if (sync_map_ctx.cache_locked) {
}
if (ret < 0) {
return -1;
}
/* hdr pointer may have changed, update it */
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)) {
ret = -1;
}
}
return ret;
}
};