mail-cache-compress.c revision 9945ad9e528188521d876b80f08a648072ffa207
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher/* Copyright (C) 2003-2004 Timo Sirainen */
5ebdc2391e96cfcc86ebdb8f223e159c00a0d82bLukas Slebodnikstatic void mail_cache_merge_bitmask(struct mail_cache *cache, buffer_t *buffer,
87d3b47abba6a40fcf809c85a2b138bc1013d9c5Jakub Hrozek unsigned int i, buf_data_size;
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));
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher i_assert(buf_field < cache->fields_count);
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher buf_data_size = cache->fields[buf_field].field.field_size;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* @UNSAFE: found it, do the merging */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned char *dest = PTR_OFFSET(buf_data, pos);
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];
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 cache_field = &view->cache->fields[field].field;
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek field_seen = buffer_get_space_unsafe(ctx->field_seen, field, 1);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek /* duplicate */
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek if (cache_field->type == MAIL_CACHE_FIELD_BITMASK) {
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek mail_cache_merge_bitmask(view->cache, ctx->buffer,
1658c567191c35beaddffafdb079abe33248037bLukas Slebodnik dec = cache_field->decision & ~MAIL_CACHE_DECISION_FORCED;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_append(ctx->buffer, &field, sizeof(field));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (cache_field->field_size == (unsigned int)-1) {
d921c1eba437662437847279f251a0a5d8f70127Maxim buffer_append(ctx->buffer, null4, 4 - (data_size & 3));
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzerget_next_file_seq(struct mail_cache *cache, struct mail_index_view *view)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher file_seq = ext != NULL ? ext->reset_id + 1 : (uint32_t)ioloop_time;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghermail_cache_copy(struct mail_cache *cache, struct mail_index_view *view, int fd)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint32_t i, message_count, seq, first_new_seq, old_offset;
03713859dffacc7142393e53c73d8d4cf7dee8d5Pavel Březina /* get sequence of first message which doesn't need it's temp fields
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher message_count = mail_index_view_get_messages_count(view);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek if (mail_index_lookup_uid_range(view, idx_hdr->day_first_uid[7],
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);
b1ce544568eff89f2263ae180e323f263f1cff3aSimo Sorce ctx.buffer = buffer_create_dynamic(default_pool, 4096);
b1ce544568eff89f2263ae180e323f263f1cff3aSimo Sorce ctx.field_seen = buffer_create_dynamic(default_pool, 64);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_index_ext_reset(t, cache->ext_id, hdr.file_seq);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (seq = 1; seq <= message_count; seq++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher memset(buffer_get_modifyable_data(ctx.field_seen, NULL),
a5077712fc8c24e8cad08207b7b5a6603bde6a7cJakub Hrozek buffer_append(ctx.buffer, &cache_rec, sizeof(cache_rec));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher cache_rec.size = buffer_get_used_size(ctx.buffer);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_index_update_ext(t, seq, cache->ext_id, &output->offset,
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke buffer_write(ctx.buffer, 0, &cache_rec, sizeof(cache_rec));
6b0a7c72bb841d6885a620c68bd51d55109b66c7Jakub Hrozek o_stream_send(output, ctx.buffer->data, cache_rec.size);
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. */
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),
539b1be3507abdf8ac235b06eeed5011b0b5cde2Ondrej Kos mail_cache_set_syscall_error(cache, "o_stream_flush()");
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);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_cache_set_syscall_error(cache, "fdatasync()");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return mail_index_transaction_commit(t, &seq, &offset);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int mail_cache_compress_locked(struct mail_cache *cache,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* get the latest info on fields */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail_cache_header_fields_read(cache) < 0)
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek i_warning("Compressing cache file %s", cache->filepath);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher fd = file_dotlock_open(cache->filepath, NULL, NULL,
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek mail_cache_set_syscall_error(cache, "file_dotlock_open()");
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek fchown(fd, (uid_t)-1, cache->index->gid) < 0) {
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek mail_cache_set_syscall_error(cache, "fchown()");
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek // FIXME: check that cache file wasn't just recreated
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek (void)file_dotlock_delete(cache->filepath, NULL, fd);
6f51c802311fd81a409a26763ed45b28a3234d0dJakub Hrozek if (file_dotlock_replace(cache->filepath, NULL,
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek "file_dotlock_replace()");
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik file_cache_set_fd(cache->file_cache, cache->fd);
827dd342494de18099dddd0272c1a85f10703556Lukas Slebodnik if (mail_cache_header_fields_read(cache) < 0)
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnikint mail_cache_compress(struct mail_cache *cache, struct mail_index_view *view)
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 /* 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 /* locking succeeded. */
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik ret = mail_cache_compress_locked(cache, view);