mail-index-update.c revision 54d1312e1be5a84a9f9585f9f5e1f884f1d37d0e
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (C) 2002 Timo Sirainen */
c000c8eca8f24b2a0c76393ec4bbf76a505a4983Timo Sirainen struct mail_index_data_record_header data_hdr;
c000c8eca8f24b2a0c76393ec4bbf76a505a4983Timo Sirainen size_t field_extra_sizes[DATA_FIELD_MAX_BITS];
3f190f4cbb9233a3a6830956cb5c7ae56a577b79Timo Sirainenmail_index_update_begin(struct mail_index *index, struct mail_index_record *rec)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct mail_index_data_record_header *data_hdr;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen pool = pool_alloconly_create("mail_index_update", 4096);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen update = p_new(pool, struct mail_index_update, 1);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen data_hdr = mail_index_data_lookup_header(index->data, rec);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen memcpy(&update->data_hdr, data_hdr, sizeof(*data_hdr));
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstatic int mail_field_get_index(enum mail_data_field field)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen unsigned int i, mask;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen for (i = 0, mask = 1; i < DATA_FIELD_MAX_BITS; i++, mask <<= 1) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenstatic void get_data_block_sizes(struct mail_index_update *update,
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen *min_size = *max_size = sizeof(struct mail_index_data_record_header);
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen rec = mail_index_data_lookup(update->index->data, update->rec, 0);
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen for (i = 0, field = 1; field != DATA_FIELD_LAST; i++, field <<= 1) {
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen field_exists = rec != NULL && rec->field == field;
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen /* value was modified - use it */
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi field_min_size = INDEX_ALIGN(update->field_sizes[i]);
d42eb03b3a4e79a2da22a1be2de59b95660af2beTimo Sirainen *min_size += SIZEOF_MAIL_INDEX_DATA + field_min_size;
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen /* use the old value */
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen rec = mail_index_data_next(update->index->data,
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainenstatic size_t get_max_align_size(size_t base, size_t extra, size_t *max_extra)
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen if (*max_extra < INDEX_ALIGN_SIZE || extra == 0)
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen return size; /* no extra / extra went into alignment */
3d4c24127f4f83259c0f81851184abc34793dbe0Timo Sirainen /* partial */
0a601ada15c7fe82f0db895fc2068b71b3a5243cTimo Sirainen extra = *max_extra & ~(size_t)(INDEX_ALIGN_SIZE-1);
be5773cb4d6edae8a5d9f300c3c7375cdd33826eJosef 'Jeff' Sipek/* extra_size is the amount of data in data_size which can be used for
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen field_extra_sizes */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenstatic void *create_data_block(struct mail_index_update *update,
c000c8eca8f24b2a0c76393ec4bbf76a505a4983Timo Sirainen struct mail_index_data_record_header *dest_hdr;
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen const void *src;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen buf = buffer_create_static_hard(update->pool, data_size);
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen /* set header */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen dest_hdr = buffer_append_space(buf, sizeof(*dest_hdr));
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen memcpy(dest_hdr, &update->data_hdr, sizeof(*dest_hdr));
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen /* set fields */
7501b9f694460101b41d1d708ebc3ec2b0400b1cTimo Sirainen rec = mail_index_data_lookup(update->index->data, update->rec, 0);
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen for (i = 0, field = 1; field != DATA_FIELD_LAST; i++, field <<= 1) {
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen /* value was modified - use it */
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen } else if (rec != NULL && rec->field == field) {
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen /* use the old value */
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen /* the field doesn't exist, jump to next */
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen i_assert((full_field_size % INDEX_ALIGN_SIZE) == 0);
1b5366b2234892f8930a29351da06b193e385150Timo Sirainen destrec = buffer_append_space(buf, SIZEOF_MAIL_INDEX_DATA +
e5afebd2df1d4990f7bec2a839260ff2e6d78168Timo Sirainen rec = mail_index_data_next(update->index->data,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen/* Append all the data at the end of the data file and update
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen the index's data position */
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainenstatic int update_by_append(struct mail_index_update *update,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mem = create_data_block(update, data_size, extra_size);
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen /* append the data at the end of the data file */
3343a61404603b21c246783a7963b77833095f31Timo Sirainen fpos = mail_index_data_append(update->index->data, mem, data_size);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen /* the old data is discarded */
3343a61404603b21c246783a7963b77833095f31Timo Sirainen (void)mail_index_data_delete(update->index->data, update->rec);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen /* update index file position - it's mmap()ed so it'll be written
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen into disk when index is unlocked. */
return TRUE;
void *mem;
int index;
if (no_grown_fields)
if (!failed) {
return !failed;
int index;
switch (field) {
case DATA_HDR_INTERNAL_DATE:
case DATA_HDR_VIRTUAL_SIZE:
case DATA_HDR_HEADER_SIZE:
case DATA_HDR_BODY_SIZE:
i_unreached();
struct header_update_context {
void *context;
void *context)
if (cache_fields == 0)
&size);
&error);
DATA_FIELD_BODYSTRUCTURE) == 0) {
t_push();
value, 0);
t_pop();
t_push();
value, 0);
t_pop();
t_push();
t_pop();
t_push();
t_pop();
sizeof(virtual_size));