mail-cache-compress.c revision f1700e6d755306a2b137fad88ea5bf8b9fc6ec4f
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2003-2007 Dovecot authors, see the included COPYING file */
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "lib.h"
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#include "array.h"
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen#include "ostream.h"
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen#include "nfs-workarounds.h"
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include "read-full.h"
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include "close-keep-errno.h"
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen#include "file-dotlock.h"
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen#include "file-cache.h"
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include "file-set-size.h"
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include "mail-cache-private.h"
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include <sys/stat.h>
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainenstruct mail_cache_copy_context {
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen struct mail_cache *cache;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen buffer_t *buffer, *field_seen;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen ARRAY_DEFINE(bitmask_pos, unsigned int);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen uint32_t *field_file_map;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen uint8_t field_seen_value;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen bool new_msg;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen};
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainenstatic void
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainenmail_cache_merge_bitmask(struct mail_cache_copy_context *ctx,
39e6fcc3e8b1ccb13087c232cb6bdea04d1a20a4Timo Sirainen const struct mail_cache_iterate_field *field)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen{
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen unsigned char *dest;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen unsigned int i, *pos;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen pos = array_idx_modifiable(&ctx->bitmask_pos, field->field_idx);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (*pos == 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* we decided to drop this field */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen }
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen dest = buffer_get_space_unsafe(ctx->buffer, *pos, field->size);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen for (i = 0; i < field->size; i++)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen dest[i] |= ((const unsigned char*)field->data)[i];
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenstatic void
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainenmail_cache_compress_field(struct mail_cache_copy_context *ctx,
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen const struct mail_cache_iterate_field *field)
150e64c376365becf1ec5c9d45912ecb840eea96Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct mail_cache_field *cache_field;
150e64c376365becf1ec5c9d45912ecb840eea96Timo Sirainen enum mail_cache_decision_type dec;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen uint32_t file_field_idx, size32;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen uint8_t *field_seen;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen file_field_idx = ctx->field_file_map[field->field_idx];
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (file_field_idx == (uint32_t)-1)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen cache_field = &ctx->cache->fields[field->field_idx].field;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen field_seen = buffer_get_space_unsafe(ctx->field_seen,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen field->field_idx, 1);
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen if (*field_seen == ctx->field_seen_value) {
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen /* duplicate */
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen if (cache_field->type == MAIL_CACHE_FIELD_BITMASK)
5afa8e2edf4f313cd56e5909f92f39c3b5b7b4d3Timo Sirainen mail_cache_merge_bitmask(ctx, field);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen *field_seen = ctx->field_seen_value;
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen dec = cache_field->decision & ~MAIL_CACHE_DECISION_FORCED;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (ctx->new_msg) {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (dec == MAIL_CACHE_DECISION_NO)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen } else {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (dec != MAIL_CACHE_DECISION_YES)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen buffer_append(ctx->buffer, &file_field_idx, sizeof(file_field_idx));
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (cache_field->field_size == (unsigned int)-1) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen size32 = (uint32_t)field->size;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen buffer_append(ctx->buffer, &size32, sizeof(size32));
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (cache_field->type == MAIL_CACHE_FIELD_BITMASK) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* remember the position in case we need to update it */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen unsigned int pos = ctx->buffer->used;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen array_idx_set(&ctx->bitmask_pos, field->field_idx, &pos);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen buffer_append(ctx->buffer, field->data, field->size);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if ((field->size & 3) != 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen buffer_append_zero(ctx->buffer, 4 - (field->size & 3));
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic uint32_t
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenget_next_file_seq(struct mail_cache *cache, struct mail_index_view *view)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen const struct mail_index_ext *ext;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen uint32_t file_seq;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ext = mail_index_view_get_ext(view, cache->ext_id);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen file_seq = ext != NULL ? ext->reset_id + 1 : (uint32_t)ioloop_time;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (cache->hdr != NULL && file_seq <= cache->hdr->file_seq)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen file_seq = cache->hdr->file_seq + 1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return file_seq != 0 ? file_seq : 1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic void
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenmail_cache_compress_get_fields(struct mail_cache_copy_context *ctx,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen unsigned int used_fields_count)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct mail_cache *cache = ctx->cache;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct mail_cache_field *field;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen unsigned int i, j, idx;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* Make mail_cache_header_fields_get() return the fields in
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen the same order as we saved them. */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen memcpy(cache->field_file_map, ctx->field_file_map,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen sizeof(uint32_t) * cache->fields_count);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* reverse mapping */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen cache->file_fields_count = used_fields_count;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen i_free(cache->file_field_map);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen cache->file_field_map = used_fields_count == 0 ? NULL :
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen i_new(unsigned int, used_fields_count);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen for (i = j = 0; i < cache->fields_count; i++) {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen idx = cache->field_file_map[i];
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (idx != (uint32_t)-1) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen i_assert(idx < used_fields_count &&
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen cache->file_field_map[idx] == 0);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen cache->file_field_map[idx] = i;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen j++;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* change permanent decisions to temporary decisions.
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if they're still permanent they'll get updated later. */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen field = &cache->fields[i].field;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (field->decision == MAIL_CACHE_DECISION_YES)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen field->decision = MAIL_CACHE_DECISION_TEMP;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen i_assert(j == used_fields_count);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen buffer_set_used_size(ctx->buffer, 0);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mail_cache_header_fields_get(cache, ctx->buffer);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic int
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenmail_cache_copy(struct mail_cache *cache, struct mail_index_transaction *trans,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen int fd, uint32_t *file_seq_r,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen ARRAY_TYPE(uint32_t) *ext_offsets)
686ad6d723004b807fd558f3ef9d1f88afa7e127Timo Sirainen{
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen struct mail_cache_copy_context ctx;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen struct mail_cache_lookup_iterate_ctx iter;
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen struct mail_cache_iterate_field field;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen struct mail_index_view *view;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen struct mail_cache_view *cache_view;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen const struct mail_index_header *idx_hdr;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen struct mail_cache_header hdr;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen struct mail_cache_record cache_rec;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen struct ostream *output;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen uint32_t message_count, seq, first_new_seq, ext_offset;
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen unsigned int i, used_fields_count, orig_fields_count;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen time_t max_drop_time;
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen view = mail_index_transaction_get_view(trans);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen /* get sequence of first message which doesn't need its temp fields
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen removed. */
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen idx_hdr = mail_index_get_header(view);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (idx_hdr->day_first_uid[7] == 0) {
f2bd9e507b8befdd95a983f86664febf5c19bd95Timo Sirainen first_new_seq = 1;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen message_count = mail_index_view_get_messages_count(view);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen } else {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (!mail_index_lookup_seq_range(view,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen idx_hdr->day_first_uid[7],
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen (uint32_t)-1, &first_new_seq,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen &message_count))
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen first_new_seq = message_count+1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen cache_view = mail_cache_view_open(cache, view);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen output = o_stream_create_fd_file(fd, 0, FALSE);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen memset(&hdr, 0, sizeof(hdr));
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen hdr.version = MAIL_CACHE_VERSION;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen hdr.compat_sizeof_uoff_t = sizeof(uoff_t);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen hdr.indexid = cache->index->indexid;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen hdr.file_seq = get_next_file_seq(cache, view);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen o_stream_send(output, &hdr, sizeof(hdr));
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen memset(&ctx, 0, sizeof(ctx));
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ctx.cache = cache;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ctx.buffer = buffer_create_dynamic(default_pool, 4096);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ctx.field_seen = buffer_create_dynamic(default_pool, 64);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ctx.field_seen_value = 0;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ctx.field_file_map = t_new(uint32_t, cache->fields_count);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen t_array_init(&ctx.bitmask_pos, 32);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* @UNSAFE: drop unused fields and create a field mapping for
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen used fields */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen max_drop_time = idx_hdr->day_stamp == 0 ? 0 :
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen idx_hdr->day_stamp - MAIL_CACHE_FIELD_DROP_SECS;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen /* if some fields' "last used" time is zero, they were probably just
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen added by us. change them to the current time. */
39e6fcc3e8b1ccb13087c232cb6bdea04d1a20a4Timo Sirainen for (i = 0; i < cache->fields_count; i++) {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (cache->fields[i].last_used == 0)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen cache->fields[i].last_used = ioloop_time;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen }
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen orig_fields_count = cache->fields_count;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (cache->file_fields_count == 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* creating the initial cache file. add all fields. */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen for (i = 0; i < orig_fields_count; i++)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ctx.field_file_map[i] = i;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen used_fields_count = i;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen } else {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen for (i = used_fields_count = 0; i < orig_fields_count; i++) {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (cache->fields[i].last_used < max_drop_time)
39e6fcc3e8b1ccb13087c232cb6bdea04d1a20a4Timo Sirainen cache->fields[i].used = FALSE;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen ctx.field_file_map[i] = !cache->fields[i].used ?
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen (uint32_t)-1 : used_fields_count++;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen }
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen }
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen i_array_init(ext_offsets, message_count);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen for (seq = 1; seq <= message_count; seq++) {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (mail_index_transaction_is_expunged(trans, seq)) {
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen (void)array_append_space(ext_offsets);
bc3698b8892df8003b410daea6f5bbcd20433808Timo Sirainen continue;
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen ctx.new_msg = seq >= first_new_seq;
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen buffer_set_used_size(ctx.buffer, 0);
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (++ctx.field_seen_value == 0) {
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen memset(buffer_get_modifiable_data(ctx.field_seen, NULL),
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen 0, buffer_get_size(ctx.field_seen));
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen ctx.field_seen_value++;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen memset(&cache_rec, 0, sizeof(cache_rec));
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen buffer_append(ctx.buffer, &cache_rec, sizeof(cache_rec));
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen mail_cache_lookup_iter_init(cache_view, seq, &iter);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen while (mail_cache_lookup_iter_next(&iter, &field) > 0)
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen mail_cache_compress_field(&ctx, &field);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen cache_rec.size = buffer_get_used_size(ctx.buffer);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (cache_rec.size == sizeof(cache_rec)) {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen /* nothing cached */
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen ext_offset = 0;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen } else {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ext_offset = output->offset;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen buffer_write(ctx.buffer, 0, &cache_rec,
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen sizeof(cache_rec));
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen o_stream_send(output, ctx.buffer->data, cache_rec.size);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen }
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen array_append(ext_offsets, &ext_offset, 1);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen i_assert(array_count(ext_offsets) == message_count);
07974f50bd55b06fd6d465f2c0e491794786e2faTimo Sirainen i_assert(orig_fields_count == cache->fields_count);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen hdr.field_header_offset = mail_index_uint32_to_offset(output->offset);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mail_cache_compress_get_fields(&ctx, used_fields_count);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen o_stream_send(output, ctx.buffer->data, ctx.buffer->used);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen hdr.used_file_size = output->offset;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen buffer_free(&ctx.buffer);
07974f50bd55b06fd6d465f2c0e491794786e2faTimo Sirainen buffer_free(&ctx.field_seen);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
07974f50bd55b06fd6d465f2c0e491794786e2faTimo Sirainen o_stream_seek(output, 0);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen o_stream_send(output, &hdr, sizeof(hdr));
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen mail_cache_view_close(cache_view);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (o_stream_flush(output) < 0) {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen errno = output->stream_errno;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen mail_cache_set_syscall_error(cache, "o_stream_flush()");
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen o_stream_destroy(&output);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen array_free(ext_offsets);
2d9644d34a78b24dc7769cd96497e700a0fb1cf1Timo Sirainen return -1;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen }
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (hdr.used_file_size < MAIL_CACHE_INITIAL_SIZE) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* grow the file some more. doesn't matter if it fails */
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen (void)file_set_size(fd, MAIL_CACHE_INITIAL_SIZE);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen o_stream_destroy(&output);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (cache->index->nfs_flush) {
270f00aeab7bede38764291e21a314211b884ab4Timo Sirainen if (fdatasync(fd) < 0) {
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen mail_cache_set_syscall_error(cache, "fdatasync()");
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen array_free(ext_offsets);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return -1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen *file_seq_r = hdr.file_seq;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen return 0;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen}
7891195e3975d554df183670dba1fcecfa0a30c3Timo Sirainen
7891195e3975d554df183670dba1fcecfa0a30c3Timo Sirainenstatic int mail_cache_compress_has_file_changed(struct mail_cache *cache)
7891195e3975d554df183670dba1fcecfa0a30c3Timo Sirainen{
7891195e3975d554df183670dba1fcecfa0a30c3Timo Sirainen struct mail_cache_header hdr;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen unsigned int i;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen int fd, ret;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen for (i = 0;; i++) {
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen fd = nfs_safe_open(cache->filepath, O_RDONLY);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (fd == -1) {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (errno == ENOENT)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen return 0;
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen mail_cache_set_syscall_error(cache, "open()");
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return -1;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen ret = read_full(fd, &hdr, sizeof(hdr));
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen close_keep_errno(fd);
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen if (ret >= 0) {
270f00aeab7bede38764291e21a314211b884ab4Timo Sirainen if (ret == 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return 0;
c6ae908f6a2313573625d782bdd4e0ff3882c44aTimo Sirainen if (cache->need_compress_file_seq == 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* previously it didn't exist */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return 1;
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return hdr.file_seq != cache->need_compress_file_seq;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen } else if (errno != ESTALE || i >= NFS_ESTALE_RETRY_COUNT) {
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen mail_cache_set_syscall_error(cache, "read()");
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return -1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic int mail_cache_compress_locked(struct mail_cache *cache,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct mail_index_transaction *trans,
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen bool *unlock)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct dotlock *dotlock;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct stat st;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mode_t old_mask;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen uint32_t file_seq, old_offset;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ARRAY_TYPE(uint32_t) ext_offsets;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen const uint32_t *offsets;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen unsigned int i, count;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen int fd, ret;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (!MAIL_CACHE_IS_UNUSABLE(cache))
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mail_cache_flush_read_cache(cache, TRUE);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* get the latest info on fields */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (mail_cache_header_fields_read(cache) < 0)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return -1;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen old_mask = umask(cache->index->mode ^ 0666);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen fd = file_dotlock_open(&cache->dotlock_settings, cache->filepath,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen 0, &dotlock);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen umask(old_mask);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (fd == -1) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mail_cache_set_syscall_error(cache, "file_dotlock_open()");
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return -1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
270f00aeab7bede38764291e21a314211b884ab4Timo Sirainen if ((ret = mail_cache_compress_has_file_changed(cache)) != 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (ret < 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return -1;
59714981ae172b5113be7ca9b8be518b759fc86dTimo Sirainen
59714981ae172b5113be7ca9b8be518b759fc86dTimo Sirainen /* was just compressed, forget this */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen cache->need_compress_file_seq = 0;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen file_dotlock_delete(&dotlock);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (*unlock) {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen (void)mail_cache_unlock(cache);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen *unlock = FALSE;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen }
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen return mail_cache_reopen(cache);
ccb77e2f63626ec46e5745ef4f38baa8e8e504fcTimo Sirainen }
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (cache->index->gid != (gid_t)-1 &&
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen fchown(fd, (uid_t)-1, cache->index->gid) < 0) {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen mail_cache_set_syscall_error(cache, "fchown()");
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen file_dotlock_delete(&dotlock);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen return -1;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen }
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (mail_cache_copy(cache, trans, fd, &file_seq, &ext_offsets) < 0) {
6384258c2f84e635d8ceffc3eeddad71f7538040Timo Sirainen (void)file_dotlock_delete(&dotlock);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen return -1;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen }
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (fstat(fd, &st) < 0) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen mail_cache_set_syscall_error(cache, "fstat()");
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen (void)file_dotlock_delete(&dotlock);
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen return -1;
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen }
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen if (file_dotlock_replace(&dotlock,
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen DOTLOCK_REPLACE_FLAG_DONT_CLOSE_FD) < 0) {
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen mail_cache_set_syscall_error(cache,
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen "file_dotlock_replace()");
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen (void)close(fd);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen array_free(&ext_offsets);
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen return -1;
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen }
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen /* once we're sure that the compression was successful,
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen update the offsets */
59714981ae172b5113be7ca9b8be518b759fc86dTimo Sirainen mail_index_ext_reset(trans, cache->ext_id, file_seq);
59714981ae172b5113be7ca9b8be518b759fc86dTimo Sirainen offsets = array_get(&ext_offsets, &count);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen for (i = 0; i < count; i++) {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (offsets[i] != 0) {
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen mail_index_update_ext(trans, i + 1, cache->ext_id,
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen &offsets[i], &old_offset);
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen }
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen }
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen array_free(&ext_offsets);
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen if (*unlock) {
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen (void)mail_cache_unlock(cache);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen *unlock = FALSE;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen }
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen mail_cache_file_close(cache);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen cache->fd = fd;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen cache->st_ino = st.st_ino;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen cache->st_dev = st.st_dev;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (cache->file_cache != NULL)
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen file_cache_set_fd(cache->file_cache, cache->fd);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen if (mail_cache_map(cache, 0, 0) < 0)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen return -1;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (mail_cache_header_fields_read(cache) < 0)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen return -1;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen cache->need_compress_file_seq = 0;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen return 0;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen}
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainenint mail_cache_compress(struct mail_cache *cache,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen struct mail_index_transaction *trans)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen{
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen bool unlock = FALSE;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen int ret;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(cache->index) || cache->index->readonly)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen return 0;
c8625391da3ee51b31e69b88895708a3d149dd1bTimo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (cache->index->lock_method == FILE_LOCK_METHOD_DOTLOCK) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* we're using dotlocking, cache file creation itself creates
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen the dotlock file we need. */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen return mail_cache_compress_locked(cache, trans, &unlock);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen switch (mail_cache_lock(cache, FALSE)) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen case -1:
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen return -1;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen case 0:
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* couldn't lock, either it's broken or doesn't exist.
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen just start creating it. */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen return mail_cache_compress_locked(cache, trans, &unlock);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen default:
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* locking succeeded. */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen unlock = TRUE;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen ret = mail_cache_compress_locked(cache, trans, &unlock);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (unlock) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (mail_cache_unlock(cache) < 0)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen ret = -1;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen return ret;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen}
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainenbool mail_cache_need_compress(struct mail_cache *cache)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen{
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return cache->need_compress_file_seq != 0 &&
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen !cache->index->readonly;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen}
85ee28daca146e18a99a22f46c0d639e57a6ac95Timo Sirainen