mail-cache-compress.c revision b780aa272b742a43579cdb523cc79cc8d4521306
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* Copyright (c) 2003-2010 Dovecot authors, see the included COPYING file */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenmail_cache_merge_bitmask(struct mail_cache_copy_context *ctx,
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen unsigned char *dest;
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen unsigned int i, *pos;
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen pos = array_idx_modifiable(&ctx->bitmask_pos, field->field_idx);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen if (*pos == 0) {
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen /* we decided to drop this field */
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen dest = buffer_get_space_unsafe(ctx->buffer, *pos, field->size);
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen dest[i] |= ((const unsigned char*)field->data)[i];
b4f35fa953a95e4d06fdae54d394095073fcfea0Timo Sirainenmail_cache_compress_field(struct mail_cache_copy_context *ctx,
c02a056b724abd6578fb8c4e439de0e94eaea6feTimo Sirainen file_field_idx = ctx->field_file_map[field->field_idx];
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen cache_field = &ctx->cache->fields[field->field_idx].field;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen field_seen = buffer_get_space_unsafe(ctx->field_seen,
a9c8c1f74e5d2911d3c15657727a30b649d3bbc4Timo Sirainen /* duplicate */
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen if (cache_field->type == MAIL_CACHE_FIELD_BITMASK)
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen dec = cache_field->decision & ~MAIL_CACHE_DECISION_FORCED;
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen buffer_append(ctx->buffer, &file_field_idx, sizeof(file_field_idx));
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen if (cache_field->field_size == (unsigned int)-1) {
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen buffer_append(ctx->buffer, &size32, sizeof(size32));
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen if (cache_field->type == MAIL_CACHE_FIELD_BITMASK) {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen /* remember the position in case we need to update it */
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen array_idx_set(&ctx->bitmask_pos, field->field_idx, &pos);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen buffer_append(ctx->buffer, field->data, field->size);
dc8ba4890b74bde400e0feef96114940129ab181Timo Sirainen buffer_append_zero(ctx->buffer, 4 - (field->size & 3));
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainenget_next_file_seq(struct mail_cache *cache, struct mail_index_view *view)
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen ext = mail_index_view_get_ext(view, cache->ext_id);
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen file_seq = ext != NULL ? ext->reset_id + 1 : (uint32_t)ioloop_time;
1e7252421b9c85b898fef7e75bd6422ef1f046e4Timo Sirainen if (cache->hdr != NULL && file_seq <= cache->hdr->file_seq)
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainenmail_cache_compress_get_fields(struct mail_cache_copy_context *ctx,
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen unsigned int i, j, idx;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen /* Make mail_cache_header_fields_get() return the fields in
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen the same order as we saved them. */
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen memcpy(cache->field_file_map, ctx->field_file_map,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* reverse mapping */
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen cache->file_field_map = used_fields_count == 0 ? NULL :
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen for (i = j = 0; i < cache->fields_count; i++) {
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen /* change permanent decisions to temporary decisions.
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if they're still permanent they'll get updated later. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (field->decision == MAIL_CACHE_DECISION_YES)
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainen mail_cache_header_fields_get(cache, ctx->buffer);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenmail_cache_copy(struct mail_cache *cache, struct mail_index_transaction *trans,
a7bee3930831a9261fa6180d02af29c484d862e9Timo Sirainen uint32_t message_count, seq, first_new_seq, ext_offset;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen unsigned int i, used_fields_count, orig_fields_count;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen view = mail_index_transaction_get_view(trans);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen cache_view = mail_cache_view_open(cache, view);
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen output = o_stream_create_fd_file(fd, 0, FALSE);
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen hdr.file_seq = get_next_file_seq(cache, view);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx.buffer = buffer_create_dynamic(default_pool, 4096);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx.field_seen = buffer_create_dynamic(default_pool, 64);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx.field_file_map = t_new(uint32_t, cache->fields_count + 1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* @UNSAFE: drop unused fields and create a field mapping for
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen used fields */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen idx_hdr->day_stamp - MAIL_CACHE_FIELD_DROP_SECS;
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen /* creating the initial cache file. add all fields. */
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen for (i = 0; i < orig_fields_count; i++)
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen for (i = used_fields_count = 0; i < orig_fields_count; i++) {
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen /* if the decision isn't forced and this field hasn't
48010d123abfac8cb19f33f1fe12f33a7090089eTimo Sirainen been accessed for a while, drop it */
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen if ((dec & MAIL_CACHE_DECISION_FORCED) == 0 &&
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen /* drop all fields we don't want */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* get sequence of first message which doesn't need its temp fields
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen first_new_seq = mail_cache_get_first_new_seq(view);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen message_count = mail_index_view_get_messages_count(view);
38ceb710e2bc957a66a75c68957cb87746682a75Timo Sirainen if (mail_index_transaction_is_expunged(trans, seq)) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen memset(buffer_get_modifiable_data(ctx.field_seen, NULL),
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen buffer_append(ctx.buffer, &cache_rec, sizeof(cache_rec));
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen mail_cache_lookup_iter_init(cache_view, seq, &iter);
e4d34f2fbee451219599d71505594df704093ce3Timo Sirainen while (mail_cache_lookup_iter_next(&iter, &field) > 0)
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen cache_rec.size = buffer_get_used_size(ctx.buffer);
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainen /* nothing cached */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen o_stream_send(output, ctx.buffer->data, cache_rec.size);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen i_assert(orig_fields_count == cache->fields_count);
f8a86fdfb0048f9c87bf223373b35416ceb5856bTimo Sirainen hdr.field_header_offset = mail_index_uint32_to_offset(output->offset);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen mail_cache_compress_get_fields(&ctx, used_fields_count);
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen o_stream_send(output, ctx.buffer->data, ctx.buffer->used);
1f1e81aab38d833d1c9cdc244c91fd762e0080d4Timo Sirainen mail_cache_set_syscall_error(cache, "o_stream_flush()");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (hdr.used_file_size < MAIL_CACHE_INITIAL_SIZE) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* grow the file some more. doesn't matter if it fails */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen (void)file_set_size(fd, MAIL_CACHE_INITIAL_SIZE);
d5abbb932a0a598f002da39a8b3326643b1b5efcTimo Sirainen if (cache->index->fsync_mode == FSYNC_MODE_ALWAYS) {
if (ret >= 0) {
if (ret == 0)
bool *unlock)
unsigned int i, count;
if (ret < 0)
if (*unlock) {
for (i = 0; i < count; i++) {
if (offsets[i] != 0) {
if (*unlock) {
int ret;
FALSE);
if (unlock) {
return ret;