mail-cache-compress.c revision 9945ad9e528188521d876b80f08a648072ffa207
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher/* Copyright (C) 2003-2004 Timo Sirainen */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher#include "lib.h"
33396dc46ea52c18f47db1b5d590880806521005Sumit Bose#include "buffer.h"
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher#include "ostream.h"
33396dc46ea52c18f47db1b5d590880806521005Sumit Bose#include "file-cache.h"
703dc1eb5b050b24235a6640f271d34ea008cf98Jan Engelhardt#include "file-set-size.h"
703dc1eb5b050b24235a6640f271d34ea008cf98Jan Engelhardt#include "mail-cache-private.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose#include <sys/stat.h>
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bosestruct mail_cache_copy_context {
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose int new_msg;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_t *buffer, *field_seen;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint8_t field_seen_value;
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher};
5ebdc2391e96cfcc86ebdb8f223e159c00a0d82bLukas Slebodnik
5ebdc2391e96cfcc86ebdb8f223e159c00a0d82bLukas Slebodnikstatic void mail_cache_merge_bitmask(struct mail_cache *cache, buffer_t *buffer,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint32_t field, const void *data,
002f84aea86371aa079b867c0ec39396b97109d3Lukas Slebodnik size_t data_size)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher void *buf_data;
700d45751e997c634504a4f22facd2edf82edea7Lukas Slebodnik uint32_t buf_field;
87d3b47abba6a40fcf809c85a2b138bc1013d9c5Jakub Hrozek unsigned int i, buf_data_size;
87d3b47abba6a40fcf809c85a2b138bc1013d9c5Jakub Hrozek size_t pos, buf_size;
deeadf40db3a1eec64cf030e54afc4cb8612a8d5Lukas Slebodnik
ccf340e56364851f2e5b75e52d3d63701b662954Lukas Slebodnik buf_data = buffer_get_modifyable_data(buffer, &buf_size);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (pos = sizeof(struct mail_cache_record); pos < buf_size; ) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buf_field = *((uint32_t *)PTR_OFFSET(buf_data, pos));
f0ea3ed816182fadf77f3e7f7ddb298b287007adLukas Slebodnik pos += sizeof(uint32_t);
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher i_assert(buf_field < cache->fields_count);
cc98edd9479d4622634a1275c98058916c14059aStephen Gallagher
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher buf_data_size = cache->fields[buf_field].field.field_size;
cc98edd9479d4622634a1275c98058916c14059aStephen Gallagher if (buf_data_size == (unsigned int)-1) {
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina buf_data_size =
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina *((uint32_t *)PTR_OFFSET(buf_data, pos));
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina pos += sizeof(uint32_t);
c481179da5d5b53ce16d8784c0bd2857ffc2f061Lukas Slebodnik }
1183d29d87c5c7439cf2364b7d7324d4a13b6e35Stephen Gallagher
002f84aea86371aa079b867c0ec39396b97109d3Lukas Slebodnik if (buf_field == field) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* @UNSAFE: found it, do the merging */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned char *dest = PTR_OFFSET(buf_data, pos);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(buf_data_size == data_size);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(pos + buf_data_size <= buf_size);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i = 0; i < buf_data_size; i++)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher dest[i] |= ((const unsigned char*)data)[i];
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher pos += (buf_data_size + 3) & ~3;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(pos <= buf_size);
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce }
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce}
f775337a7d4ca1c0be8eab683d0d753cbaee49e2Lukas Slebodnik
f775337a7d4ca1c0be8eab683d0d753cbaee49e2Lukas Slebodnikstatic int
f775337a7d4ca1c0be8eab683d0d753cbaee49e2Lukas Slebodnikmail_cache_compress_callback(struct mail_cache_view *view, uint32_t field,
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek const void *data, size_t data_size, void *context)
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek{
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek struct mail_cache_copy_context *ctx = context;
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce struct mail_cache_field *cache_field;
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce enum mail_cache_decision_type dec;
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek uint8_t *field_seen;
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek uint32_t size32;
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek cache_field = &view->cache->fields[field].field;
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek field_seen = buffer_get_space_unsafe(ctx->field_seen, field, 1);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek if (*field_seen == ctx->field_seen_value) {
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek /* duplicate */
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek if (cache_field->type == MAIL_CACHE_FIELD_BITMASK) {
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek mail_cache_merge_bitmask(view->cache, ctx->buffer,
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek field, data, data_size);
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozek }
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozek return 1;
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozek }
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozek *field_seen = ctx->field_seen_value;
1658c567191c35beaddffafdb079abe33248037bLukas Slebodnik
1658c567191c35beaddffafdb079abe33248037bLukas Slebodnik dec = cache_field->decision & ~MAIL_CACHE_DECISION_FORCED;
1658c567191c35beaddffafdb079abe33248037bLukas Slebodnik if (ctx->new_msg) {
faa16fc9f0c9a02b26497e7cf148a92586144c08David Disseldorp if (dec == MAIL_CACHE_DECISION_NO)
faa16fc9f0c9a02b26497e7cf148a92586144c08David Disseldorp return 1;
faa16fc9f0c9a02b26497e7cf148a92586144c08David Disseldorp } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (dec != MAIL_CACHE_DECISION_YES)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_append(ctx->buffer, &field, sizeof(field));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (cache_field->field_size == (unsigned int)-1) {
d921c1eba437662437847279f251a0a5d8f70127Maxim size32 = (uint32_t)data_size;
d921c1eba437662437847279f251a0a5d8f70127Maxim buffer_append(ctx->buffer, &size32, sizeof(size32));
d921c1eba437662437847279f251a0a5d8f70127Maxim }
d921c1eba437662437847279f251a0a5d8f70127Maxim
d921c1eba437662437847279f251a0a5d8f70127Maxim buffer_append(ctx->buffer, data, data_size);
d921c1eba437662437847279f251a0a5d8f70127Maxim if ((data_size & 3) != 0)
d921c1eba437662437847279f251a0a5d8f70127Maxim buffer_append(ctx->buffer, null4, 4 - (data_size & 3));
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer return 1;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer}
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzerstatic uint32_t
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzerget_next_file_seq(struct mail_cache *cache, struct mail_index_view *view)
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer{
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer const struct mail_index_ext *ext;
327127bb7fcc07f882209f029e14026de1b23c94Maxim uint32_t file_seq;
327127bb7fcc07f882209f029e14026de1b23c94Maxim
327127bb7fcc07f882209f029e14026de1b23c94Maxim ext = mail_index_view_get_ext(view, cache->ext_id);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher file_seq = ext != NULL ? ext->reset_id + 1 : (uint32_t)ioloop_time;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return file_seq != 0 ? file_seq : 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghermail_cache_copy(struct mail_cache *cache, struct mail_index_view *view, int fd)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce struct mail_cache_copy_context ctx;
bc9235cfb80bd64a3bfa959e8d26d5ad1be0bdf4Jakub Hrozek struct mail_cache_view *cache_view;
bc9235cfb80bd64a3bfa959e8d26d5ad1be0bdf4Jakub Hrozek struct mail_index_transaction *t;
07d82f79d2970a08628ebf71343441ec55faa6faPavel Březina const struct mail_index_header *idx_hdr;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail_cache_header hdr;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail_cache_record cache_rec;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct ostream *output;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_t *buffer;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint32_t i, message_count, seq, first_new_seq, old_offset;
4b6a0d0b3d42e5fdb457f47d9adfa5e66b160256Stephen Gallagher uoff_t offset;
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose
03713859dffacc7142393e53c73d8d4cf7dee8d5Pavel Březina /* get sequence of first message which doesn't need it's temp fields
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik removed. */
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik idx_hdr = mail_index_get_header(view);
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke if (idx_hdr->day_first_uid[7] == 0) {
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit Bose first_new_seq = 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher message_count = mail_index_view_get_messages_count(view);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (mail_index_lookup_uid_range(view, idx_hdr->day_first_uid[7],
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (uint32_t)-1, &first_new_seq,
772464c842968d6e544118ae1aa7c49a7cda2ad6Stephen Gallagher &message_count) < 0)
32381402a4a9afc003782c9e2301fc59c9bda2a9Yassir Elley return -1;
068dbee9ca7bf5b37330eff91c94ae10f288d09fJakub Hrozek if (first_new_seq == 0)
98ce3c3e85a4bb2e1822bf8ab2a1c2ab9e3dd61dJakub Hrozek first_new_seq = message_count+1;
be65f065fef1d387281096ef095a2acef39ecc12Jakub Hrozek }
e124844907ed6973915e4d56f5442ecd07535a12Jakub Hrozek
f36078af138f052cd9a30360867b0ebd0805af5eJakub Hrozek cache_view = mail_cache_view_open(cache, view);
34c78b745eb349eef2b0f13ef2b722632aebe619Jan Cholasta t = mail_index_transaction_begin(view, FALSE, TRUE);
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek output = o_stream_create_file(fd, default_pool, 0, FALSE);
e07a94a66985b674c5df11ca466792902164c4e2George McCollister
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek memset(&hdr, 0, sizeof(hdr));
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik hdr.version = MAIL_CACHE_VERSION;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer hdr.indexid = idx_hdr->indexid;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer hdr.file_seq = get_next_file_seq(cache, view);
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose o_stream_send(output, &hdr, sizeof(hdr));
bc13c352ba9c2877f1e9bc62e55ad60fc000a55dJakub Hrozek
b1ce544568eff89f2263ae180e323f263f1cff3aSimo Sorce memset(&ctx, 0, sizeof(ctx));
b1ce544568eff89f2263ae180e323f263f1cff3aSimo Sorce ctx.buffer = buffer_create_dynamic(default_pool, 4096);
b1ce544568eff89f2263ae180e323f263f1cff3aSimo Sorce ctx.field_seen = buffer_create_dynamic(default_pool, 64);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx.field_seen_value = 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_index_ext_reset(t, cache->ext_id, hdr.file_seq);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (seq = 1; seq <= message_count; seq++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx.new_msg = seq >= first_new_seq;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_set_used_size(ctx.buffer, 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (++ctx.field_seen_value == 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher memset(buffer_get_modifyable_data(ctx.field_seen, NULL),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher 0, buffer_get_size(ctx.field_seen));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx.field_seen_value++;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher memset(&cache_rec, 0, sizeof(cache_rec));
a5077712fc8c24e8cad08207b7b5a6603bde6a7cJakub Hrozek buffer_append(ctx.buffer, &cache_rec, sizeof(cache_rec));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (void)mail_cache_foreach(cache_view, seq,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_cache_compress_callback, &ctx);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher cache_rec.size = buffer_get_used_size(ctx.buffer);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (cache_rec.size == sizeof(cache_rec))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher continue;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_index_update_ext(t, seq, cache->ext_id, &output->offset,
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek &old_offset);
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke buffer_write(ctx.buffer, 0, &cache_rec, sizeof(cache_rec));
6b0a7c72bb841d6885a620c68bd51d55109b66c7Jakub Hrozek o_stream_send(output, ctx.buffer->data, cache_rec.size);
9917c138d9a270deb5820915384fbde751190c2aLukas Slebodnik }
0e1dcef53d9d8465ce97d31ad11be4445a6e7eb8Lukas Slebodnik
c3889e5a101a075defe533d81f5296d5e680f639Lukas Slebodnik if (cache->fields_count != 0) {
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina hdr.field_header_offset =
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer mail_index_uint32_to_offset(output->offset);
40b2be4f4312470044cdef460b02b66003f5c85fJakub Hrozek
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek /* we wrote everything using our internal field ids. so we want
9d453f1e8b28983b363b44c49b7cd701a994fd97Nikolai Kondrashov mail_cache_header_fields_get() to use them and ignore any
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek existing id mappings in the old cache file. */
0c1b38d1a86460a638fa0d97099a6eba10cfccf0Jakub Hrozek cache->file_fields_count = 0;
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina for (i = 0; i < cache->fields_count; i++)
f0beb4e313970ffd075cd711ed6cfbac03ad5af6Christian Heimes cache->field_file_map[i] = (uint32_t)-1;
f0beb4e313970ffd075cd711ed6cfbac03ad5af6Christian Heimes
f0beb4e313970ffd075cd711ed6cfbac03ad5af6Christian Heimes t_push();
f0beb4e313970ffd075cd711ed6cfbac03ad5af6Christian Heimes buffer = buffer_create_dynamic(pool_datastack_create(), 256);
f0beb4e313970ffd075cd711ed6cfbac03ad5af6Christian Heimes mail_cache_header_fields_get(cache, buffer);
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina o_stream_send(output, buffer_get_data(buffer, NULL),
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina buffer_get_used_size(buffer));
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina t_pop();
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher }
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher hdr.used_file_size = output->offset;
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik buffer_free(ctx.buffer);
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik buffer_free(ctx.field_seen);
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher o_stream_seek(output, 0);
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik o_stream_send(output, &hdr, sizeof(hdr));
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik mail_cache_view_close(cache_view);
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
9dbdf62243f01f6aee41c2b5f2976c56da47f25dLukas Slebodnik if (o_stream_flush(output) < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher errno = output->stream_errno;
539b1be3507abdf8ac235b06eeed5011b0b5cde2Ondrej Kos mail_cache_set_syscall_error(cache, "o_stream_flush()");
539b1be3507abdf8ac235b06eeed5011b0b5cde2Ondrej Kos (void)mail_index_transaction_rollback(t);
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos o_stream_unref(output);
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos return -1;
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos }
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek if (hdr.used_file_size < MAIL_CACHE_INITIAL_SIZE) {
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozek /* grow the file some more. doesn't matter if it fails */
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozek (void)file_set_size(fd, MAIL_CACHE_INITIAL_SIZE);
9542512d7be40f2000298c86d3d2b728f4f0f65aStephen Gallagher }
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
0c1b38d1a86460a638fa0d97099a6eba10cfccf0Jakub Hrozek o_stream_unref(output);
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozek
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek if (fdatasync(fd) < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_cache_set_syscall_error(cache, "fdatasync()");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (void)mail_index_transaction_rollback(t);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return mail_index_transaction_commit(t, &seq, &offset);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int mail_cache_compress_locked(struct mail_cache *cache,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail_index_view *view)
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek{
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek mode_t old_mask;
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek int fd;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* get the latest info on fields */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail_cache_header_fields_read(cache) < 0)
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek return -1;
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek#ifdef DEBUG
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek i_warning("Compressing cache file %s", cache->filepath);
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek#endif
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek old_mask = umask(cache->index->mode ^ 0666);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher fd = file_dotlock_open(cache->filepath, NULL, NULL,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MAIL_CACHE_LOCK_TIMEOUT,
b50dffea929ee5cd0c59ba3c4822337cc162ff92Kamil Dudka MAIL_CACHE_LOCK_CHANGE_TIMEOUT,
b50dffea929ee5cd0c59ba3c4822337cc162ff92Kamil Dudka MAIL_CACHE_LOCK_IMMEDIATE_TIMEOUT, NULL, NULL);
b50dffea929ee5cd0c59ba3c4822337cc162ff92Kamil Dudka umask(old_mask);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (fd == -1) {
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek mail_cache_set_syscall_error(cache, "file_dotlock_open()");
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek if (cache->index->gid != (gid_t)-1 &&
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek fchown(fd, (uid_t)-1, cache->index->gid) < 0) {
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek mail_cache_set_syscall_error(cache, "fchown()");
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek return -1;
d9378e64499642e86989158f274372187314d5b2Lukas Slebodnik }
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek // FIXME: check that cache file wasn't just recreated
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek if (mail_cache_copy(cache, view, fd) < 0) {
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek (void)file_dotlock_delete(cache->filepath, NULL, fd);
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek return -1;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek }
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek
6f51c802311fd81a409a26763ed45b28a3234d0dJakub Hrozek if (file_dotlock_replace(cache->filepath, NULL,
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek -1, FALSE) < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_cache_set_syscall_error(cache,
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek "file_dotlock_replace()");
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher (void)close(fd);
f5b6f977d4144c28e9c66f3f1c9d634d595d1117Marko Myllynen return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik mail_cache_file_close(cache);
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik cache->fd = fd;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik if (cache->file_cache != NULL)
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik file_cache_set_fd(cache->file_cache, cache->fd);
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik if (mail_cache_map(cache, 0, 0) < 0)
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return -1;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik if (mail_cache_header_fields_read(cache) < 0)
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik return -1;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik cache->need_compress = FALSE;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik return 0;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik}
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnikint mail_cache_compress(struct mail_cache *cache, struct mail_index_view *view)
dc4c30bae512c0b45ff925d9e998337f8fe97e94Lukas Slebodnik{
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik int ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik if (cache->index->lock_method == MAIL_INDEX_LOCK_DOTLOCK) {
72e60fd4eabcfbcdbfe01e8c38b94052bc6c2067Jakub Hrozek /* we're using dotlocking, cache file creation itself creates
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik the dotlock file we need. */
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return mail_cache_compress_locked(cache, view);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik }
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik switch (mail_cache_lock(cache)) {
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik case -1:
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return -1;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik case 0:
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik /* couldn't lock, either it's broken or doesn't exist.
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik just start creating it. */
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return mail_cache_compress_locked(cache, view);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher default:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* locking succeeded. */
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik ret = mail_cache_compress_locked(cache, view);
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik mail_cache_unlock(cache);
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik return ret;
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik }
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik}
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnikint mail_cache_need_compress(struct mail_cache *cache)
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik{
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return cache->need_compress;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik}
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik