Mercurial > dovecot > original-hg > dovecot-1.2
changeset 6443:53313d1e7e4f HEAD
Code cleanups and some minor fixes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 22 Sep 2007 11:42:58 +0300 |
parents | 6f12401a149e |
children | 2b434cf6954e |
files | src/lib-index/mail-cache-fields.c src/lib-index/mail-cache-transaction.c |
diffstat | 2 files changed, 106 insertions(+), 72 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/mail-cache-fields.c Sat Sep 22 11:11:58 2007 +0300 +++ b/src/lib-index/mail-cache-fields.c Sat Sep 22 11:42:58 2007 +0300 @@ -11,6 +11,10 @@ #define CACHE_HDR_PREFETCH 1024 +#define CACHE_FIELD_IS_NEWLY_WANTED(cache, field_idx) \ + ((cache)->field_file_map[field_idx] == (uint32_t)-1 && \ + (cache)->fields[field_idx].used) + static bool field_has_fixed_size(enum mail_cache_field_type type) { switch (type) { @@ -340,53 +344,61 @@ return 0; } -static void copy_to_buf(struct mail_cache *cache, buffer_t *dest, +static void copy_to_buf(struct mail_cache *cache, buffer_t *dest, bool add_new, size_t offset, size_t size) { const void *data; unsigned int i, field; + /* copy the existing fields */ for (i = 0; i < cache->file_fields_count; i++) { field = cache->file_field_map[i]; data = CONST_PTR_OFFSET(&cache->fields[field], offset); buffer_append(dest, data, size); } + if (!add_new) + return; + + /* copy newly wanted fields */ for (i = 0; i < cache->fields_count; i++) { - if (cache->field_file_map[i] != (uint32_t)-1 || - !cache->fields[i].used) - continue; - data = CONST_PTR_OFFSET(&cache->fields[i], offset); - buffer_append(dest, data, size); + if (CACHE_FIELD_IS_NEWLY_WANTED(cache, i)) { + data = CONST_PTR_OFFSET(&cache->fields[i], offset); + buffer_append(dest, data, size); + } } } static void copy_to_buf_byte(struct mail_cache *cache, buffer_t *dest, - size_t offset) + bool add_new, size_t offset) { const int *data; unsigned int i, field; uint8_t byte; + /* copy the existing fields */ for (i = 0; i < cache->file_fields_count; i++) { field = cache->file_field_map[i]; data = CONST_PTR_OFFSET(&cache->fields[field], offset); byte = (uint8_t)*data; buffer_append(dest, &byte, 1); } + if (!add_new) + return; + + /* copy newly wanted fields */ for (i = 0; i < cache->fields_count; i++) { - if (cache->field_file_map[i] != (uint32_t)-1 || - !cache->fields[i].used) - continue; - data = CONST_PTR_OFFSET(&cache->fields[i], offset); - byte = (uint8_t)*data; - buffer_append(dest, &byte, 1); + if (CACHE_FIELD_IS_NEWLY_WANTED(cache, i)) { + data = CONST_PTR_OFFSET(&cache->fields[i], offset); + byte = (uint8_t)*data; + buffer_append(dest, &byte, 1); + } } } static int mail_cache_header_fields_update_locked(struct mail_cache *cache) { buffer_t *buffer; - uint32_t i, offset; + uint32_t i, offset, dec_offset; int ret = 0; if (mail_cache_header_fields_read(cache) < 0 || @@ -396,21 +408,20 @@ t_push(); buffer = buffer_create_dynamic(pool_datastack_create(), 256); - copy_to_buf(cache, buffer, + copy_to_buf(cache, buffer, FALSE, offsetof(struct mail_cache_field_private, last_used), sizeof(uint32_t)); - ret = mail_cache_write(cache, buffer->data, - sizeof(uint32_t) * cache->file_fields_count, + ret = mail_cache_write(cache, buffer->data, buffer->used, offset + MAIL_CACHE_FIELD_LAST_USED()); if (ret == 0) { buffer_set_used_size(buffer, 0); - copy_to_buf_byte(cache, buffer, + copy_to_buf_byte(cache, buffer, FALSE, offsetof(struct mail_cache_field, decision)); - ret = mail_cache_write(cache, buffer->data, - sizeof(uint8_t) * cache->file_fields_count, offset + - MAIL_CACHE_FIELD_DECISION(cache->file_fields_count)); - + dec_offset = offset + + MAIL_CACHE_FIELD_DECISION(cache->file_fields_count); + ret = mail_cache_write(cache, buffer->data, buffer->used, + dec_offset); if (ret == 0) { for (i = 0; i < cache->file_fields_count; i++) cache->fields[i].decision_dirty = FALSE; @@ -450,41 +461,41 @@ memset(&hdr, 0, sizeof(hdr)); hdr.fields_count = cache->file_fields_count; for (i = 0; i < cache->fields_count; i++) { - if (cache->field_file_map[i] == (uint32_t)-1 && - cache->fields[i].used) + if (CACHE_FIELD_IS_NEWLY_WANTED(cache, i)) hdr.fields_count++; } buffer_append(dest, &hdr, sizeof(hdr)); /* we have to keep the field order for the existing fields. */ - copy_to_buf(cache, dest, + copy_to_buf(cache, dest, TRUE, offsetof(struct mail_cache_field_private, last_used), sizeof(uint32_t)); - copy_to_buf(cache, dest, offsetof(struct mail_cache_field, field_size), + copy_to_buf(cache, dest, TRUE, + offsetof(struct mail_cache_field, field_size), sizeof(uint32_t)); - copy_to_buf_byte(cache, dest, offsetof(struct mail_cache_field, type)); - copy_to_buf_byte(cache, dest, + copy_to_buf_byte(cache, dest, TRUE, + offsetof(struct mail_cache_field, type)); + copy_to_buf_byte(cache, dest, TRUE, offsetof(struct mail_cache_field, decision)); - i_assert(buffer_get_used_size(dest) == sizeof(hdr) + + i_assert(dest->used == sizeof(hdr) + (sizeof(uint32_t)*2 + 2) * hdr.fields_count); - /* add fields' names */ + /* add existing fields' names */ for (i = 0; i < cache->file_fields_count; i++) { field = cache->file_field_map[i]; name = cache->fields[field].field.name; buffer_append(dest, name, strlen(name)+1); } + /* add newly wanted fields' names */ for (i = 0; i < cache->fields_count; i++) { - if (cache->field_file_map[i] != (uint32_t)-1 || - !cache->fields[i].used) - continue; - - name = cache->fields[i].field.name; - buffer_append(dest, name, strlen(name)+1); + if (CACHE_FIELD_IS_NEWLY_WANTED(cache, i)) { + name = cache->fields[i].field.name; + buffer_append(dest, name, strlen(name)+1); + } } - hdr.size = buffer_get_used_size(dest); + hdr.size = dest->used; buffer_write(dest, 0, &hdr, sizeof(hdr)); if ((hdr.size & 3) != 0)
--- a/src/lib-index/mail-cache-transaction.c Sat Sep 22 11:11:58 2007 +0300 +++ b/src/lib-index/mail-cache-transaction.c Sat Sep 22 11:42:58 2007 +0300 @@ -663,18 +663,58 @@ mail_cache_transaction_free(ctx); } +static int +mail_cache_header_fields_write(struct mail_cache_transaction_ctx *ctx, + const buffer_t *buffer) +{ + struct mail_cache *cache = ctx->cache; + size_t size = buffer->used; + uint32_t offset, hdr_offset; + + if (mail_cache_transaction_get_space(ctx, size, size, + &offset, NULL, TRUE) <= 0) + return -1; + + if (mail_cache_write(cache, buffer->data, size, offset) < 0) + return -1; + + if (!cache->index->fsync_disable) { + if (fdatasync(cache->fd) < 0) { + mail_cache_set_syscall_error(cache, "fdatasync()"); + return -1; + } + } + if (mail_cache_header_fields_get_next_offset(cache, &hdr_offset) < 0) + return -1; + + /* if we rollback the transaction, we must not overwrite this + area because it's already committed after updating the + header offset */ + mail_cache_transaction_partial_commit(ctx, offset, size); + + /* after it's guaranteed to be in disk, update header offset */ + offset = mail_index_uint32_to_offset(offset); + if (mail_cache_write(cache, &offset, sizeof(offset), hdr_offset) < 0) + return -1; + + if (hdr_offset == offsetof(struct mail_cache_header, + field_header_offset)) { + /* we're adding the first field. hdr_copy needs to be kept + in sync so unlocking won't overwrite it. */ + cache->hdr_copy.field_header_offset = hdr_offset; + } + return 0; +} + static int mail_cache_header_add_field(struct mail_cache_transaction_ctx *ctx, unsigned int field_idx) { struct mail_cache *cache = ctx->cache; buffer_t *buffer; - const void *data; - size_t size; - uint32_t offset, hdr_offset; - int ret = 0; + int ret; - ctx->cache->fields[field_idx].last_used = ioloop_time; - ctx->cache->fields[field_idx].used = TRUE; + cache->fields[field_idx].last_used = ioloop_time; + cache->fields[field_idx].used = TRUE; if ((ret = mail_cache_transaction_lock(ctx)) <= 0) { /* create the cache file if it doesn't exist yet */ @@ -694,7 +734,7 @@ return -1; } - if (ctx->cache->field_file_map[field_idx] != (uint32_t)-1) { + if (cache->field_file_map[field_idx] != (uint32_t)-1) { /* it was already added */ if (mail_cache_unlock(cache) < 0) return -1; @@ -704,37 +744,20 @@ t_push(); buffer = buffer_create_dynamic(pool_datastack_create(), 256); mail_cache_header_fields_get(cache, buffer); - data = buffer_get_data(buffer, &size); + ret = mail_cache_header_fields_write(ctx, buffer); + t_pop(); - if (mail_cache_transaction_get_space(ctx, size, size, - &offset, NULL, TRUE) <= 0) - ret = -1; - else if (mail_cache_write(cache, data, size, offset) < 0) - ret = -1; - else if (!cache->index->fsync_disable && fdatasync(cache->fd) < 0) { - mail_cache_set_syscall_error(cache, "fdatasync()"); - ret = -1; - } else if (mail_cache_header_fields_get_next_offset(cache, - &hdr_offset) < 0) + if (ret == 0) { + /* we wrote all the headers, so there are no pending changes */ + cache->field_header_write_pending = FALSE; + ret = mail_cache_header_fields_read(cache); + } + if (ret == 0 && cache->field_file_map[field_idx] == (uint32_t)-1) { + mail_index_set_error(cache->index, + "Cache file %s: Newly added field got " + "lost unexpectedly", cache->filepath); ret = -1; - else { - /* if we rollback the transaction, we must not overwrite this - area because it's already committed after updating the - header offset */ - mail_cache_transaction_partial_commit(ctx, offset, size); - - /* after it's guaranteed to be in disk, update header offset */ - offset = mail_index_uint32_to_offset(offset); - if (mail_cache_write(cache, &offset, sizeof(offset), - hdr_offset) < 0) - ret = -1; - else { - /* we'll need to fix mappings. */ - if (mail_cache_header_fields_read(cache) < 0) - ret = -1; - } } - t_pop(); if (mail_cache_unlock(cache) < 0) ret = -1;