Mercurial > dovecot > core-2.2
changeset 2298:5beb0c20b6e8 HEAD
Cache file fixes, API changes, etc. It's still in somewhat ugly state, but
getting better..
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 08 Jul 2004 23:26:15 +0300 |
parents | 59062bb4eaac |
children | ef0cd18d674c |
files | src/lib-imap/imap-bodystructure.c src/lib-imap/imap-bodystructure.h src/lib-index/mail-cache-compress.c src/lib-index/mail-cache-decisions.c src/lib-index/mail-cache-lookup.c src/lib-index/mail-cache-private.h src/lib-index/mail-cache-transaction.c src/lib-index/mail-cache.c src/lib-index/mail-cache.h src/lib-storage/index/index-fetch.c src/lib-storage/index/index-mail-headers.c src/lib-storage/index/index-mail.c src/lib-storage/index/index-mail.h src/lib-storage/index/index-search.c src/lib-storage/index/index-storage.c src/lib-storage/index/maildir/maildir-mail.c src/lib-storage/index/maildir/maildir-save.c src/lib-storage/index/mbox/mbox-mail.c src/lib-storage/index/mbox/mbox-save.c |
diffstat | 19 files changed, 595 insertions(+), 675 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-imap/imap-bodystructure.c Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-imap/imap-bodystructure.c Thu Jul 08 23:26:15 2004 +0300 @@ -36,9 +36,6 @@ unsigned int charset_found:1; }; -static void part_write_bodystructure(struct message_part *part, - string_t *str, int extended); - static void parse_content_type(const unsigned char *value, size_t value_len, void *context) { @@ -294,7 +291,7 @@ } if (part->children != NULL) - part_write_bodystructure(part->children, str, extended); + imap_bodystructure_write(part->children, str, extended); else { /* no parts in multipart message, that's not allowed. write a single @@ -416,7 +413,7 @@ imap_envelope_write_part_data(env_data, str); str_append(str, ") "); - part_write_bodystructure(part->children, str, extended); + imap_bodystructure_write(part->children, str, extended); str_printfa(str, " %u", part->body_size.lines); } @@ -459,37 +456,27 @@ } } -static void part_write_bodystructure(struct message_part *part, - string_t *str, int extended) +void imap_bodystructure_write(struct message_part *part, + string_t *dest, int extended) { i_assert(part->parent != NULL || part->next == NULL); while (part != NULL) { if (part->parent != NULL) - str_append_c(str, '('); + str_append_c(dest, '('); if (part->flags & MESSAGE_PART_FLAG_MULTIPART) - part_write_body_multipart(part, str, extended); + part_write_body_multipart(part, dest, extended); else - part_write_body(part, str, extended); + part_write_body(part, dest, extended); if (part->parent != NULL) - str_append_c(str, ')'); + str_append_c(dest, ')'); part = part->next; } } -const char *imap_bodystructure_parse_finish(struct message_part *root, - int extended) -{ - string_t *str; - - str = t_str_new(2048); - part_write_bodystructure(root, str, extended); - return str_c(str); -} - static int str_append_imap_arg(string_t *str, const struct imap_arg *arg) { switch (arg->type) { @@ -645,35 +632,27 @@ return TRUE; } -const char *imap_body_parse_from_bodystructure(const char *bodystructure) +int imap_body_parse_from_bodystructure(const char *bodystructure, + string_t *dest) { struct istream *input; struct imap_parser *parser; struct imap_arg *args; - string_t *str; - const char *value; - size_t len; int ret; - len = strlen(bodystructure); - str = t_str_new(len); - input = i_stream_create_from_data(pool_datastack_create(), - bodystructure, len); + bodystructure, strlen(bodystructure)); (void)i_stream_read(input); parser = imap_parser_create(input, NULL, (size_t)-1); ret = imap_parser_finish_line(parser, 0, IMAP_PARSE_FLAG_NO_UNESCAPE | IMAP_PARSE_FLAG_LITERAL_TYPE, &args); - if (ret <= 0 || !imap_parse_bodystructure_args(args, str)) - value = NULL; - else - value = str_c(str); + ret = ret > 0 && imap_parse_bodystructure_args(args, dest); - if (value == NULL) + if (!ret) i_error("Error parsing IMAP bodystructure: %s", bodystructure); imap_parser_destroy(parser); i_stream_unref(input); - return value; + return ret; }
--- a/src/lib-imap/imap-bodystructure.h Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-imap/imap-bodystructure.h Thu Jul 08 23:26:15 2004 +0300 @@ -8,10 +8,11 @@ void imap_bodystructure_parse_header(pool_t pool, struct message_part *part, struct message_header_line *hdr); -const char *imap_bodystructure_parse_finish(struct message_part *root, - int extended); +void imap_bodystructure_write(struct message_part *part, + string_t *dest, int extended); /* Return BODY part from BODYSTRUCTURE */ -const char *imap_body_parse_from_bodystructure(const char *bodystructure); +int imap_body_parse_from_bodystructure(const char *bodystructure, + string_t *dest); #endif
--- a/src/lib-index/mail-cache-compress.c Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-index/mail-cache-compress.c Thu Jul 08 23:26:15 2004 +0300 @@ -8,98 +8,76 @@ static unsigned char null4[4] = { 0, 0, 0, 0 }; -static const struct mail_cache_record * -mail_cache_compress_record(struct mail_cache_view *view, uint32_t seq, - enum mail_cache_field orig_cached_fields, - int header_idx, uint32_t *size_r) +struct mail_cache_copy_context { + int new_msg; + char field_seen[32], keep_fields[32], temp_fields[32]; + buffer_t *buffer, *header; +}; + +static int +mail_cache_compress_callback(struct mail_cache_view *view __attr_unused__, + enum mail_cache_field field, + const void *data, size_t data_size, void *context) { - enum mail_cache_field cached_fields, field; - struct mail_cache_record cache_rec; - buffer_t *buffer; - pool_t pool; - const void *data; - size_t size, pos; - uint32_t *p, size32 = 0; + struct mail_cache_copy_context *ctx = context; + uint32_t size32; int i; - memset(&cache_rec, 0, sizeof(cache_rec)); - pool = pool_datastack_create(); - buffer = buffer_create_dynamic(pool, 4096, (size_t)-1); - - cached_fields = orig_cached_fields & ~MAIL_CACHE_HEADERS_MASK; - buffer_append(buffer, &cache_rec, sizeof(cache_rec)); - for (i = 0, field = 1; i < 31; i++, field <<= 1) { - if ((cached_fields & field) == 0) - continue; - - pos = buffer_get_used_size(buffer); - if ((field & MAIL_CACHE_FIXED_MASK) == 0) - buffer_append(buffer, &size32, sizeof(size32)); - - if (!mail_cache_lookup_field(view, buffer, seq, field)) { - cached_fields &= ~field; - buffer_set_used_size(buffer, pos); - continue; - } - - if ((field & MAIL_CACHE_FIXED_MASK) == 0) { - p = buffer_get_space_unsafe(buffer, pos, - sizeof(uint32_t)); - *p = (uint32_t)size; - } - - if ((size & 3) != 0) - buffer_append(buffer, null4, 4 - (size & 3)); + if (ctx->new_msg) { + if (!ctx->temp_fields[field]) + return 1; + } else { + if (!ctx->keep_fields[field]) + return 1; } - /* now merge all the headers if we have them all */ - if ((orig_cached_fields & mail_cache_header_fields[header_idx]) != 0) { - size32 = 0; - pos = buffer_get_used_size(buffer); - buffer_append(buffer, &size32, sizeof(size32)); + if (ctx->field_seen[field]) { + /* drop duplicates */ + return 1; + } + ctx->field_seen[field] = TRUE; - for (i = 0; i <= header_idx; i++) { - field = mail_cache_header_fields[i]; - if (mail_cache_lookup_field(view, buffer, seq, field)) { - /* remove terminating \0 */ - buffer_set_used_size(buffer, - buffer_get_used_size(buffer)-1); + for (i = 0; i < MAIL_CACHE_HEADERS_COUNT; i++) { + if (mail_cache_header_fields[i] == field) { + /* it's header - save it into header field */ + size32 = buffer_get_used_size(ctx->header); + if (size32 > 0) { + /* remove old terminating \0 */ + buffer_set_used_size(ctx->header, size32-1); } + buffer_append(ctx->header, data, data_size); + return 1; } - buffer_append(buffer, null4, 1); - - size32 = buffer_get_used_size(buffer) - pos; - if ((size32 & 3) != 0) - buffer_append(buffer, null4, 4 - (size32 & 3)); - buffer_write(buffer, pos, &size32, sizeof(size32)); - - cached_fields |= MAIL_CACHE_HEADERS1; } - cache_rec.fields = cached_fields; - cache_rec.size = buffer_get_used_size(buffer); - buffer_write(buffer, 0, &cache_rec, sizeof(cache_rec)); + buffer_append(ctx->buffer, &field, sizeof(field)); - data = buffer_get_data(buffer, &size); - *size_r = size; - return data; + if (mail_cache_field_sizes[field] == (unsigned int)-1) { + size32 = (uint32_t)data_size; + buffer_append(ctx->buffer, &size32, sizeof(size32)); + } + + buffer_append(ctx->buffer, data, data_size); + if ((data_size & 3) != 0) + buffer_append(ctx->buffer, null4, 4 - (data_size & 3)); + return 1; } static int mail_cache_copy(struct mail_cache *cache, struct mail_index_view *view, int fd) { + struct mail_cache_copy_context ctx; struct mail_cache_view *cache_view; struct mail_index_transaction *t; const struct mail_index_header *idx_hdr; - const struct mail_cache_record *cache_rec; struct mail_cache_header hdr; + struct mail_cache_record cache_rec; + enum mail_cache_field field; struct ostream *output; - enum mail_cache_field keep_fields, temp_fields; - enum mail_cache_field cached_fields, new_fields; const char *str; - uint32_t size, size32, message_count, seq, first_new_seq; + uint32_t size32, message_count, seq, first_new_seq, old_offset; uoff_t offset; - int i, header_idx, ret; + int i, ret, header_idx; /* get sequence of first message which doesn't need it's temp fields removed. */ @@ -133,15 +111,23 @@ memcpy(hdr.field_usage_last_used, cache->hdr->field_usage_last_used, sizeof(hdr.field_usage_last_used)); + } else { + memcpy(hdr.field_usage_decision_type, + cache->default_field_usage_decision_type, + sizeof(hdr.field_usage_decision_type)); + } - keep_fields = temp_fields = 0; - for (i = 0; i < 32; i++) { - if (cache->hdr->field_usage_decision_type[i] & - MAIL_CACHE_DECISION_YES) - keep_fields |= 1 << i; - else if (cache->hdr->field_usage_decision_type[i] & - MAIL_CACHE_DECISION_TEMP) - temp_fields |= 1 << i; + memset(&ctx, 0, sizeof(ctx)); + ctx.buffer = buffer_create_dynamic(default_pool, 4096, (size_t)-1); + ctx.header = buffer_create_dynamic(default_pool, 4096, (size_t)-1); + + for (i = 0; i < 32; i++) { + if (hdr.field_usage_decision_type[i] & MAIL_CACHE_DECISION_YES) + ctx.keep_fields[i] = TRUE; + else if (hdr.field_usage_decision_type[i] & + MAIL_CACHE_DECISION_TEMP) { + ctx.temp_fields[i] = TRUE; + ctx.keep_fields[i] = TRUE; } } @@ -173,45 +159,42 @@ ret = 0; for (seq = 1; seq <= message_count; seq++) { - cache_rec = mail_cache_lookup(cache_view, seq); - if (cache_rec == NULL) - continue; + ctx.new_msg = seq >= first_new_seq; + buffer_set_used_size(ctx.buffer, 0); + buffer_set_used_size(ctx.header, 0); + memset(ctx.field_seen, 0, sizeof(ctx.field_seen)); + + memset(&cache_rec, 0, sizeof(cache_rec)); + buffer_append(ctx.buffer, &cache_rec, sizeof(cache_rec)); + + mail_cache_foreach(cache_view, seq, + mail_cache_compress_callback, &ctx); - cached_fields = mail_cache_get_fields(cache_view, seq); - new_fields = cached_fields & keep_fields; - if ((cached_fields & temp_fields) != 0 && - seq >= first_new_seq) { - /* new message, keep temp fields */ - new_fields |= cached_fields & temp_fields; + size32 = buffer_get_used_size(ctx.header); + if (size32 > 0 && ctx.field_seen[header_idx]) { + field = MAIL_CACHE_HEADERS1; + buffer_append(ctx.buffer, &field, sizeof(field)); + buffer_append(ctx.buffer, &size32, sizeof(size32)); + buffer_append(ctx.buffer, + buffer_get_data(ctx.header, NULL), + size32); + if ((size32 & 3) != 0) { + buffer_append(ctx.buffer, null4, + 4 - (size32 & 3)); + } } - if (keep_fields == cached_fields && - cache_rec->prev_offset == 0) { - /* just one unmodified block, save it */ - mail_index_update_cache(t, seq, hdr.file_seq, - output->offset, NULL); - o_stream_send(output, cache_rec, cache_rec->size); + if (buffer_get_used_size(ctx.buffer) == sizeof(cache_rec)) + continue; - if ((cache_rec->size & 3) != 0) { - o_stream_send(output, null4, - 4 - (cache_rec->size & 3)); - } - } else { - /* a) dropping fields - b) multiple blocks, sort them into buffer */ - mail_index_update_cache(t, seq, hdr.file_seq, - output->offset, NULL); - - t_push(); - cache_rec = mail_cache_compress_record(cache_view, seq, - keep_fields, - header_idx, - &size); - o_stream_send(output, cache_rec, size); - t_pop(); - } + mail_index_update_cache(t, seq, hdr.file_seq, + output->offset, &old_offset); + o_stream_send(output, buffer_get_data(ctx.buffer, NULL), + buffer_get_used_size(ctx.buffer)); } hdr.used_file_size = output->offset; + buffer_free(ctx.buffer); + buffer_free(ctx.header); o_stream_seek(output, 0); o_stream_send(output, &hdr, sizeof(hdr)); @@ -263,7 +246,7 @@ return -1; } - // FIXME: check that cache file was just recreated + // FIXME: check that cache file wasn't just recreated ret = 0; if (mail_cache_copy(cache, view, fd) < 0) {
--- a/src/lib-index/mail-cache-decisions.c Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-index/mail-cache-decisions.c Thu Jul 08 23:26:15 2004 +0300 @@ -73,7 +73,8 @@ #include <stddef.h> static void -mail_cache_set_decision_type(struct mail_cache *cache, uint32_t idx, +mail_cache_set_decision_type(struct mail_cache *cache, + enum mail_cache_field field, enum mail_cache_decision_type type) { uint8_t value = type; @@ -84,20 +85,18 @@ will be corrected sometimes later, not too bad.. */ if (pwrite_full(cache->fd, &value, 1, offsetof(struct mail_cache_header, - field_usage_decision_type) + idx) < 0) { + field_usage_decision_type) + field) < 0) { mail_cache_set_syscall_error(cache, "pwrite_full()"); } } -void mail_cache_handle_decisions(struct mail_cache_view *view, uint32_t seq, - enum mail_cache_field field) +void mail_cache_decision_lookup(struct mail_cache_view *view, uint32_t seq, + enum mail_cache_field field) { const struct mail_index_header *hdr; - unsigned int idx; uint32_t uid; - idx = mail_cache_field_index(field); - if (view->cache->hdr->field_usage_decision_type[idx] != + if (view->cache->hdr->field_usage_decision_type[field] != MAIL_CACHE_DECISION_TEMP) { /* a) forced decision b) not cached, mail_cache_mark_missing() will handle this @@ -110,7 +109,7 @@ mail_index_get_header(view->view, &hdr) < 0) return; - if (uid < view->cache->field_usage_uid_highwater[idx] || + if (uid < view->cache->field_usage_uid_highwater[field] || uid < hdr->day_first_uid[7]) { /* a) nonordered access within this session. if client doesn't request messages in growing order, we assume it doesn't @@ -119,24 +118,22 @@ client with no local cache. if it was just a new client generating the local cache for the first time, we'll drop back to TEMP within few months. */ - mail_cache_set_decision_type(view->cache, idx, + mail_cache_set_decision_type(view->cache, field, MAIL_CACHE_DECISION_YES); } else { - view->cache->field_usage_uid_highwater[idx] = uid; + view->cache->field_usage_uid_highwater[field] = uid; } } -void mail_cache_mark_missing(struct mail_cache_view *view, uint32_t seq, +void mail_cache_decision_add(struct mail_cache_view *view, uint32_t seq, enum mail_cache_field field) { - unsigned int idx; uint32_t uid; if (MAIL_CACHE_IS_UNUSABLE(view->cache)) return; - idx = mail_cache_field_index(field); - if (view->cache->hdr->field_usage_decision_type[idx] != + if (view->cache->hdr->field_usage_decision_type[field] != MAIL_CACHE_DECISION_NO) { /* a) forced decision b) we're already caching it, so it just wasn't in cache */ @@ -144,9 +141,9 @@ } /* field used the first time */ - mail_cache_set_decision_type(view->cache, idx, + mail_cache_set_decision_type(view->cache, field, MAIL_CACHE_DECISION_TEMP); if (mail_index_lookup_uid(view->view, seq, &uid) == 0) - view->cache->field_usage_uid_highwater[idx] = uid; + view->cache->field_usage_uid_highwater[field] = uid; }
--- a/src/lib-index/mail-cache-lookup.c Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-index/mail-cache-lookup.c Thu Jul 08 23:26:15 2004 +0300 @@ -171,112 +171,163 @@ return 0; } -struct mail_cache_record * -mail_cache_lookup(struct mail_cache_view *view, uint32_t seq) +int mail_cache_foreach(struct mail_cache_view *view, uint32_t seq, + int (*callback)(struct mail_cache_view *view, + enum mail_cache_field field, + const void *data, size_t data_size, + void *context), void *context) { - uint32_t offset; - - // FIXME: check transactions too + const struct mail_cache_record *cache_rec; + size_t pos, next_pos, max_size, data_size; + uint32_t offset, field; + int ret; if (MAIL_CACHE_IS_UNUSABLE(view->cache)) - return NULL; + return 0; + + if ((ret = mail_cache_lookup_offset(view, seq, &offset)) <= 0) + return ret; - if (mail_cache_lookup_offset(view, seq, &offset) <= 0) - return NULL; + cache_rec = mail_cache_get_record(view->cache, offset); + while (cache_rec != NULL) { + max_size = cache_rec->size; + if (max_size < sizeof(*cache_rec) + sizeof(uint32_t)*2) { + mail_cache_set_corrupted(view->cache, + "record has invalid size"); + return -1; + } + max_size -= sizeof(uint32_t); - return mail_cache_get_record(view->cache, offset); -} + for (pos = sizeof(*cache_rec); pos < max_size; ) { + field = *((const uint32_t *) + CONST_PTR_OFFSET(cache_rec, pos)); + pos += sizeof(uint32_t); -enum mail_cache_field -mail_cache_get_fields(struct mail_cache_view *view, uint32_t seq) -{ - struct mail_cache_record *cache_rec; - enum mail_cache_field fields = 0; + data_size = mail_cache_field_sizes[field]; + if (data_size == (unsigned int)-1) { + data_size = *((const uint32_t *) + CONST_PTR_OFFSET(cache_rec, pos)); + pos += sizeof(uint32_t); + } - cache_rec = mail_cache_lookup(view, seq); - while (cache_rec != NULL) { - fields |= cache_rec->fields; + next_pos = pos + ((data_size + 3) & ~3); + if (next_pos > cache_rec->size) { + mail_cache_set_corrupted(view->cache, + "Record continues outside it's " + "allocated size"); + return -1; + } + + ret = callback(view, field, + CONST_PTR_OFFSET(cache_rec, pos), + data_size, context); + if (ret <= 0) + return ret; + + pos = next_pos; + } cache_rec = mail_cache_get_record(view->cache, cache_rec->prev_offset); } - return fields; + if (view->transaction != NULL) { + // FIXME: update + } + return 1; +} + +static int mail_cache_seq_callback(struct mail_cache_view *view, + enum mail_cache_field field, + const void *data __attr_unused__, + size_t data_size __attr_unused__, + void *context __attr_unused__) +{ + view->cached_exists[field] = TRUE; + return 1; +} + +static int mail_cache_seq(struct mail_cache_view *view, uint32_t seq) +{ + int ret; + + view->cached_exists_seq = seq; + memset(view->cached_exists, 0, sizeof(view->cached_exists)); + + ret = mail_cache_foreach(view, seq, mail_cache_seq_callback, NULL); + return ret < 0 ? -1 : 0; } -static int cache_get_field(struct mail_cache *cache, - const struct mail_cache_record *cache_rec, - enum mail_cache_field field, buffer_t *dest_buf) +int mail_cache_field_exists(struct mail_cache_view *view, uint32_t seq, + enum mail_cache_field field) { - unsigned int mask; - uint32_t data_size; - size_t offset, prev_offset; - int i; + i_assert(field < MAIL_CACHE_FIELD_COUNT); - offset = sizeof(*cache_rec); + if (MAIL_CACHE_IS_UNUSABLE(view->cache)) + return 0; - for (i = 0, mask = 1; i < 31; i++, mask <<= 1) { - if ((cache_rec->fields & mask) == 0) - continue; + if (view->cached_exists_seq != seq) { + if (mail_cache_seq(view, seq) < 0) + return -1; + } + return view->cached_exists[field]; +} - /* all records are at least 32bit. we have to check this - before getting data_size. */ - if (offset + sizeof(uint32_t) > cache_rec->size) { - mail_cache_set_corrupted(cache, - "Record continues outside it's allocated size"); - return FALSE; - } +enum mail_cache_decision_type +mail_cache_field_get_decision(struct mail_cache *cache, + enum mail_cache_field field) +{ + i_assert(field < MAIL_CACHE_FIELD_COUNT); - if ((mask & MAIL_CACHE_FIXED_MASK) != 0) - data_size = mail_cache_field_sizes[i]; - else { - memcpy(&data_size, CONST_PTR_OFFSET(cache_rec, offset), - sizeof(data_size)); - offset += sizeof(data_size); - } + if (MAIL_CACHE_IS_UNUSABLE(cache)) + return cache->default_field_usage_decision_type[field]; - prev_offset = offset + ((data_size + 3) & ~3); - if (prev_offset > cache_rec->size) { - mail_cache_set_corrupted(cache, - "Record continues outside it's allocated size"); - return FALSE; - } + return cache->hdr->field_usage_decision_type[field]; +} + +struct mail_cache_lookup_context { + buffer_t *dest_buf; + enum mail_cache_field field; +}; - if (field == mask) { - if (data_size == 0) { - mail_cache_set_corrupted(cache, - "Field size is 0"); - return FALSE; - } - buffer_append(dest_buf, - CONST_PTR_OFFSET(cache_rec, offset), - data_size); - return TRUE; - } - offset = prev_offset; - } +static int +mail_cache_lookup_callback(struct mail_cache_view *view __attr_unused__, + enum mail_cache_field field, + const void *data, size_t data_size, void *context) +{ + struct mail_cache_lookup_context *ctx = context; - i_unreached(); - return FALSE; + if (ctx->field != field) + return 1; + + buffer_append(ctx->dest_buf, data, data_size); + return 0; } int mail_cache_lookup_field(struct mail_cache_view *view, buffer_t *dest_buf, uint32_t seq, enum mail_cache_field field) { - struct mail_cache_record *cache_rec; + struct mail_cache_lookup_context ctx; - mail_cache_handle_decisions(view, seq, field); + i_assert(field < MAIL_CACHE_FIELD_COUNT); - cache_rec = mail_cache_lookup(view, seq); - while (cache_rec != NULL) { - if ((cache_rec->fields & field) != 0) { - return cache_get_field(view->cache, cache_rec, field, - dest_buf); - } - cache_rec = mail_cache_get_record(view->cache, - cache_rec->prev_offset); + if (MAIL_CACHE_IS_UNUSABLE(view->cache)) + return 0; + + mail_cache_decision_lookup(view, seq, field); + + if (view->cached_exists_seq != seq) { + if (mail_cache_seq(view, seq) < 0) + return -1; } - return FALSE; + if (!view->cached_exists[field]) + return 0; + + /* should exist. find it. */ + ctx.field = field; + ctx.dest_buf = dest_buf; + return mail_cache_foreach(view, seq, mail_cache_lookup_callback, + &ctx) == 0; } int mail_cache_lookup_string_field(struct mail_cache_view *view, string_t *dest, @@ -284,21 +335,24 @@ { size_t old_size, new_size; - i_assert((field & MAIL_CACHE_STRING_MASK) != 0); + i_assert(field < MAIL_CACHE_FIELD_COUNT); + + if (MAIL_CACHE_IS_UNUSABLE(view->cache)) + return 0; old_size = str_len(dest); if (!mail_cache_lookup_field(view, dest, seq, field)) - return FALSE; + return 0; new_size = str_len(dest); if (old_size == new_size || str_data(dest)[new_size-1] != '\0') { mail_cache_set_corrupted(view->cache, "String field %x doesn't end with NUL", field); - return FALSE; + return -1; } str_truncate(dest, new_size-1); - return TRUE; + return 1; } enum mail_cache_record_flag
--- a/src/lib-index/mail-cache-private.h Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-index/mail-cache-private.h Thu Jul 08 23:26:15 2004 +0300 @@ -35,18 +35,6 @@ #define MAIL_CACHE_IS_UNUSABLE(cache) \ ((cache)->hdr == NULL) -enum mail_cache_decision_type { - /* Not needed currently */ - MAIL_CACHE_DECISION_NO = 0x00, - /* Needed only for new mails. Drop when compressing. */ - MAIL_CACHE_DECISION_TEMP = 0x01, - /* Needed. */ - MAIL_CACHE_DECISION_YES = 0x02, - - /* This decision has been forced manually, don't change it. */ - MAIL_CACHE_DECISION_FORCED = 0x80 -}; - struct mail_cache_header { /* version is increased only when you can't have backwards compatibility. */ @@ -69,9 +57,9 @@ }; struct mail_cache_record { - uint32_t fields; /* enum mail_cache_field */ uint32_t prev_offset; uint32_t size; /* full record size, including this header */ + /* array of { uint32_t field; [ uint32_t size; ] { .. } } */ }; struct mail_cache_hole_header { @@ -101,9 +89,7 @@ uint32_t split_offsets[MAIL_CACHE_HEADERS_COUNT]; const char *const *split_headers[MAIL_CACHE_HEADERS_COUNT]; - enum mail_cache_field default_cache_fields; - enum mail_cache_field never_cache_fields; - + uint8_t default_field_usage_decision_type[32]; uint32_t field_usage_uid_highwater[32]; unsigned int locked:1; @@ -115,7 +101,9 @@ struct mail_cache *cache; struct mail_index_view *view; - unsigned int broken:1; + struct mail_cache_transaction_ctx *transaction; + char cached_exists[32]; + uint32_t cached_exists_seq; }; extern unsigned int mail_cache_field_sizes[32]; @@ -123,7 +111,6 @@ uint32_t mail_cache_uint32_to_offset(uint32_t offset); uint32_t mail_cache_offset_to_uint32(uint32_t offset); -unsigned int mail_cache_field_index(enum mail_cache_field field); /* Explicitly lock the cache file. Returns -1 if error, 1 if ok, 0 if we couldn't lock */ @@ -138,8 +125,11 @@ struct mail_cache_record * mail_cache_get_record(struct mail_cache *cache, uint32_t offset); -struct mail_cache_record * -mail_cache_lookup(struct mail_cache_view *view, uint32_t seq); +int mail_cache_foreach(struct mail_cache_view *view, uint32_t seq, + int (*callback)(struct mail_cache_view *view, + enum mail_cache_field field, + const void *data, size_t data_size, + void *context), void *context); int mail_cache_transaction_commit(struct mail_cache_transaction_ctx *ctx); void mail_cache_transaction_rollback(struct mail_cache_transaction_ctx *ctx); @@ -154,8 +144,10 @@ /* Mark record in given offset to be deleted. */ int mail_cache_delete(struct mail_cache *cache, uint32_t offset); -void mail_cache_handle_decisions(struct mail_cache_view *view, uint32_t seq, - enum mail_cache_field field); +void mail_cache_decision_lookup(struct mail_cache_view *view, uint32_t seq, + enum mail_cache_field field); +void mail_cache_decision_add(struct mail_cache_view *view, uint32_t seq, + enum mail_cache_field field); void mail_cache_set_syscall_error(struct mail_cache *cache, const char *function);
--- a/src/lib-index/mail-cache-transaction.c Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-index/mail-cache-transaction.c Thu Jul 08 23:26:15 2004 +0300 @@ -28,7 +28,7 @@ uint32_t last_grow_size; uint32_t first_seq, last_seq; - enum mail_cache_field fields; + enum mail_cache_field fields[32]; unsigned int changes:1; }; @@ -55,12 +55,17 @@ ctx->reservations = buffer_create_dynamic(system_pool, 256, (size_t)-1); + i_assert(view->transaction == NULL); + view->transaction = ctx; + t->cache_trans_ctx = ctx; return ctx; } static void mail_cache_transaction_free(struct mail_cache_transaction_ctx *ctx) { + ctx->view->transaction = NULL; + buffer_free(ctx->cache_data); buffer_free(ctx->cache_data_seq); buffer_free(ctx->reservations); @@ -317,7 +322,7 @@ struct mail_cache *cache = ctx->cache; const struct mail_cache_record *rec, *tmp_rec; const uint32_t *seq; - uint32_t write_offset, old_offset, rec_offset; + uint32_t write_offset, old_offset, rec_pos; size_t size, max_size, seq_idx, seq_limit, seq_count; int commit; @@ -332,9 +337,10 @@ seq = buffer_get_data(ctx->cache_data_seq, &seq_count); seq_count /= sizeof(*seq); + seq_limit = 0; - for (seq_idx = 0, rec_offset = 0; rec_offset < ctx->prev_pos;) { - max_size = ctx->prev_pos - rec_offset; + for (seq_idx = 0, rec_pos = 0; rec_pos < ctx->prev_pos;) { + max_size = ctx->prev_pos - rec_pos; write_offset = mail_cache_transaction_get_space(ctx, rec->size, max_size, &max_size, @@ -344,7 +350,7 @@ return ctx->prev_pos == 0 ? 0 : -1; } - if (max_size < ctx->prev_pos) { + if (rec_pos + max_size < ctx->prev_pos) { /* see how much we can really write there */ tmp_rec = rec; for (size = 0; size + tmp_rec->size <= max_size; ) { @@ -383,7 +389,7 @@ } write_offset += rec->size; - rec_offset += rec->size; + rec_pos += rec->size; rec = CONST_PTR_OFFSET(rec, rec->size); } } @@ -391,7 +397,10 @@ /* drop the written data from buffer */ buffer_copy(ctx->cache_data, 0, ctx->cache_data, ctx->prev_pos, (size_t)-1); - buffer_set_used_size(ctx->cache_data, size - ctx->prev_pos); + buffer_set_used_size(ctx->cache_data, + buffer_get_used_size(ctx->cache_data) - + ctx->prev_pos); + ctx->prev_pos = 0; buffer_set_used_size(ctx->cache_data_seq, 0); return 0; @@ -409,6 +418,7 @@ data = buffer_get_modifyable_data(ctx->cache_data, &size); rec = PTR_OFFSET(data, ctx->prev_pos); rec->size = size - ctx->prev_pos; + i_assert(rec->size != 0); buffer_append(ctx->cache_data_seq, &ctx->prev_seq, sizeof(ctx->prev_seq)); @@ -588,62 +598,23 @@ return offset > 0; } -static size_t -mail_cache_transaction_get_insert_pos(struct mail_cache_transaction_ctx *ctx, - enum mail_cache_field field) -{ - const struct mail_cache_record *cache_rec; - const void *data; - unsigned int mask; - uint32_t data_size; - size_t pos; - int i; - - data = buffer_get_data(ctx->cache_data, NULL); - cache_rec = CONST_PTR_OFFSET(data, ctx->prev_pos); - - pos = ctx->prev_pos + sizeof(*cache_rec); - for (i = 0, mask = 1; i < 31; i++, mask <<= 1) { - if ((field & mask) != 0) - return pos; - - if ((cache_rec->fields & mask) != 0) { - if ((mask & MAIL_CACHE_FIXED_MASK) != 0) - data_size = mail_cache_field_sizes[i]; - else { - memcpy(&data_size, CONST_PTR_OFFSET(data, pos), - sizeof(data_size)); - pos += sizeof(data_size); - } - pos += (data_size + 3) & ~3; - } - } - - i_unreached(); - return pos; -} - void mail_cache_add(struct mail_cache_transaction_ctx *ctx, uint32_t seq, enum mail_cache_field field, const void *data, size_t data_size) { - struct mail_cache_record *cache_rec; - unsigned char *buf; - size_t full_size, pos; - uint32_t data_size32; - unsigned int field_idx; + uint32_t fixed_size, data_size32; + size_t full_size; + i_assert(field < MAIL_CACHE_FIELD_COUNT); i_assert(data_size > 0); i_assert(data_size < (uint32_t)-1); - data_size32 = (uint32_t)data_size; + mail_cache_decision_add(ctx->view, seq, field); - if ((field & MAIL_CACHE_FIXED_MASK) != 0) { - field_idx = mail_cache_field_index(field); - i_assert(mail_cache_field_sizes[field_idx] == data_size); - } else if ((field & MAIL_CACHE_STRING_MASK) != 0) { - i_assert(((char *) data)[data_size-1] == '\0'); - } + fixed_size = mail_cache_field_sizes[field]; + i_assert(fixed_size == (unsigned int)-1 || fixed_size == data_size); + + data_size32 = (uint32_t)data_size; if (ctx->prev_seq != seq) { mail_cache_transaction_switch_seq(ctx); @@ -655,11 +626,12 @@ ctx->first_seq = seq; if (seq > ctx->last_seq) ctx->last_seq = seq; - ctx->fields |= field; + ctx->view->cached_exists[field] = TRUE; + ctx->fields[field] = TRUE; } full_size = (data_size + 3) & ~3; - if ((field & MAIL_CACHE_FIXED_MASK) == 0) + if (fixed_size == (unsigned int)-1) full_size += sizeof(data_size32); if (buffer_get_used_size(ctx->cache_data) + full_size > @@ -669,24 +641,15 @@ return; } - /* fields must be ordered. find where to insert it. */ - pos = mail_cache_transaction_get_insert_pos(ctx, field); - buffer_copy(ctx->cache_data, pos + full_size, - ctx->cache_data, pos, (size_t)-1); - - cache_rec = buffer_get_space_unsafe(ctx->cache_data, ctx->prev_pos, - sizeof(*cache_rec)); - cache_rec->fields |= field; + buffer_append(ctx->cache_data, &field, sizeof(field)); + if (fixed_size == (unsigned int)-1) { + buffer_append(ctx->cache_data, &data_size32, + sizeof(data_size32)); + } - /* @UNSAFE */ - buf = buffer_get_space_unsafe(ctx->cache_data, pos, full_size); - if ((field & MAIL_CACHE_FIXED_MASK) == 0) { - memcpy(buf, &data_size32, sizeof(data_size32)); - buf += sizeof(data_size32); - } - memcpy(buf, data, data_size); buf += data_size; + buffer_append(ctx->cache_data, data, data_size); if ((data_size & 3) != 0) - memset(buf, 0, 4 - (data_size & 3)); + buffer_append(ctx->cache_data, null4, 4 - (data_size & 3)); } int mail_cache_update_record_flags(struct mail_cache_view *view, uint32_t seq,
--- a/src/lib-index/mail-cache.c Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-index/mail-cache.c Thu Jul 08 23:26:15 2004 +0300 @@ -15,13 +15,13 @@ sizeof(time_t), sizeof(uoff_t), - 0, 0, 0, 0, 0, 0, 0, 0, - /* variable sized */ (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, + (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, + (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1 }; @@ -60,17 +60,6 @@ (((uint32_t)buf[0] & 0x7f) << 23); } -unsigned int mail_cache_field_index(enum mail_cache_field field) -{ - unsigned int i, num; - - for (i = 0, num = 1; i < 32; i++, num <<= 1) { - if (field == num) - return i; - } - i_unreached(); -} - void mail_cache_set_syscall_error(struct mail_cache *cache, const char *function) { @@ -284,11 +273,10 @@ } void mail_cache_set_defaults(struct mail_cache *cache, - enum mail_cache_field default_cache_fields, - enum mail_cache_field never_cache_fields) + const enum mail_cache_decision_type dec[32]) { - cache->default_cache_fields = default_cache_fields; - cache->never_cache_fields = never_cache_fields; + memcpy(cache->default_field_usage_decision_type, dec, + sizeof(cache->default_field_usage_decision_type)); } int mail_cache_lock(struct mail_cache *cache)
--- a/src/lib-index/mail-cache.h Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-index/mail-cache.h Thu Jul 08 23:26:15 2004 +0300 @@ -11,6 +11,18 @@ struct mail_cache_view; struct mail_cache_transaction_ctx; +enum mail_cache_decision_type { + /* Not needed currently */ + MAIL_CACHE_DECISION_NO = 0x00, + /* Needed only for new mails. Drop when compressing. */ + MAIL_CACHE_DECISION_TEMP = 0x01, + /* Needed. */ + MAIL_CACHE_DECISION_YES = 0x02, + + /* This decision has been forced manually, don't change it. */ + MAIL_CACHE_DECISION_FORCED = 0x80 +}; + enum mail_cache_record_flag { /* If binary flags are set, it's not checked whether mail is missing CRs. So this flag may be set as an optimization for @@ -28,40 +40,23 @@ /* when modifying, remember to update mail_cache_field_sizes[] too */ enum mail_cache_field { /* fixed size fields */ - MAIL_CACHE_INDEX_FLAGS = 0x00000001, - MAIL_CACHE_SENT_DATE = 0x00000002, - MAIL_CACHE_RECEIVED_DATE = 0x00000004, - MAIL_CACHE_VIRTUAL_FULL_SIZE = 0x00000008, + MAIL_CACHE_INDEX_FLAGS = 0, + MAIL_CACHE_SENT_DATE, + MAIL_CACHE_RECEIVED_DATE, + MAIL_CACHE_VIRTUAL_FULL_SIZE, /* variable sized field */ - MAIL_CACHE_HEADERS1 = 0x40000000, - MAIL_CACHE_HEADERS2 = 0x20000000, - MAIL_CACHE_HEADERS3 = 0x10000000, - MAIL_CACHE_HEADERS4 = 0x08000000, - MAIL_CACHE_LOCATION = 0x04000000, - MAIL_CACHE_BODY = 0x02000000, - MAIL_CACHE_BODYSTRUCTURE = 0x01000000, - MAIL_CACHE_ENVELOPE = 0x00800000, - MAIL_CACHE_MESSAGEPART = 0x00400000, - MAIL_CACHE_UID_STRING = 0x00200000, + MAIL_CACHE_HEADERS1, + MAIL_CACHE_HEADERS2, + MAIL_CACHE_HEADERS3, + MAIL_CACHE_HEADERS4, + MAIL_CACHE_BODY, + MAIL_CACHE_BODYSTRUCTURE, + MAIL_CACHE_ENVELOPE, + MAIL_CACHE_MESSAGEPART, + MAIL_CACHE_UID_STRING, - MAIL_CACHE_FIXED_MASK = MAIL_CACHE_INDEX_FLAGS | - MAIL_CACHE_SENT_DATE | - MAIL_CACHE_RECEIVED_DATE | - MAIL_CACHE_VIRTUAL_FULL_SIZE, - MAIL_CACHE_HEADERS_MASK = MAIL_CACHE_HEADERS1 | - MAIL_CACHE_HEADERS2 | - MAIL_CACHE_HEADERS3 | - MAIL_CACHE_HEADERS4, - MAIL_CACHE_STRING_MASK = MAIL_CACHE_HEADERS_MASK | - MAIL_CACHE_LOCATION | - MAIL_CACHE_BODY | - MAIL_CACHE_BODYSTRUCTURE | - MAIL_CACHE_ENVELOPE | - MAIL_CACHE_UID_STRING, - MAIL_CACHE_BODYSTRUCTURE_MASK = MAIL_CACHE_BODY | - MAIL_CACHE_BODYSTRUCTURE | - MAIL_CACHE_MESSAGEPART + MAIL_CACHE_FIELD_COUNT }; struct mail_sent_date { @@ -75,8 +70,7 @@ void mail_cache_free(struct mail_cache *cache); void mail_cache_set_defaults(struct mail_cache *cache, - enum mail_cache_field default_cache_fields, - enum mail_cache_field never_cache_fields); + const enum mail_cache_decision_type dec[32]); /* Returns TRUE if cache should be compressed. */ int mail_cache_need_compress(struct mail_cache *cache); @@ -106,9 +100,13 @@ enum mail_cache_field field, const void *data, size_t data_size); -/* Return all fields that are currently cached for record. */ -enum mail_cache_field -mail_cache_get_fields(struct mail_cache_view *view, uint32_t seq); +/* Retursn TRUE if field exists. */ +int mail_cache_field_exists(struct mail_cache_view *view, uint32_t seq, + enum mail_cache_field field); +/* Returns current caching decision for given field. */ +enum mail_cache_decision_type +mail_cache_field_get_decision(struct mail_cache *cache, + enum mail_cache_field field); /* Set data_r and size_r to point to wanted field in cache file. Returns TRUE if field was found. If field contains multiple fields, @@ -120,10 +118,6 @@ int mail_cache_lookup_string_field(struct mail_cache_view *view, string_t *dest, uint32_t seq, enum mail_cache_field field); -/* Mark given field as missing, ie. it should be cached when possible. */ -void mail_cache_mark_missing(struct mail_cache_view *view, uint32_t uid, - enum mail_cache_field field); - /* Return record flags. */ enum mail_cache_record_flag mail_cache_get_record_flags(struct mail_cache_view *view, uint32_t seq);
--- a/src/lib-storage/index/index-fetch.c Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-storage/index/index-fetch.c Thu Jul 08 23:26:15 2004 +0300 @@ -10,23 +10,13 @@ { struct index_transaction_context *t = (struct index_transaction_context *)_t; - const struct mail_index_record *rec; - - if (mail_index_lookup(t->trans_view, seq, &rec) < 0) { - mail_storage_set_index_error(t->ibox); - return NULL; - } - - if (rec == NULL) - return NULL; if (t->fetch_mail.pool != NULL) index_mail_deinit(&t->fetch_mail); index_mail_init(t, &t->fetch_mail, wanted_fields, NULL); - if (index_mail_next(&t->fetch_mail, rec, seq, FALSE) <= 0) + if (index_mail_next(&t->fetch_mail, seq) < 0) return NULL; - return &t->fetch_mail.mail; }
--- a/src/lib-storage/index/index-mail-headers.c Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-storage/index/index-mail-headers.c Thu Jul 08 23:26:15 2004 +0300 @@ -191,8 +191,9 @@ return -1; for (; idx < MAIL_CACHE_HEADERS_COUNT; idx++) { - if ((mail->data.cached_fields & - mail_cache_header_fields[idx]) != 0) + if (mail_cache_field_exists(mail->trans->cache_view, + mail->data.seq, + mail_cache_header_fields[idx]) > 0) return idx; } @@ -320,9 +321,9 @@ data->save_sent_date = FALSE; } if (data->sent_date.time != (time_t)-1) { - index_mail_cache_add(mail, MAIL_CACHE_SENT_DATE, - &data->sent_date, - sizeof(data->sent_date)); + mail_cache_add(mail->trans->cache_trans, data->seq, + MAIL_CACHE_SENT_DATE, &data->sent_date, + sizeof(data->sent_date)); } cached_headers_mark_fully_saved(mail); @@ -387,8 +388,11 @@ static int index_mail_can_cache_headers(struct index_mail *mail) { - if ((mail->data.cached_fields & - mail_cache_header_fields[MAIL_CACHE_HEADERS_COUNT-1]) != 0) + enum mail_cache_field field; + + field = mail_cache_header_fields[MAIL_CACHE_HEADERS_COUNT-1]; + if (mail_cache_field_exists(mail->trans->cache_view, mail->data.seq, + field) != 0) return FALSE; /* all headers used */ /* FIXME: add some smart checks here. we don't necessarily want to @@ -493,9 +497,6 @@ if (mail->data.header_data == NULL) mail->data.header_data = str_new(mail->pool, 4096); - /* can_cache_headers() locks the cache file. it must be done before - we can expect cached headers to stay the same. it's not a good idea - to cache some headers twice because of race conditions.. */ if (!data->header_fully_parsed && index_mail_can_cache_headers(mail)) { if (data->header_data_cached_partial) { /* too difficult to handle efficiently, trash it */ @@ -722,8 +723,10 @@ if (idx != -2) { if (idx >= 0) { for (; idx < MAIL_CACHE_HEADERS_COUNT; idx++) { - if ((data->cached_fields & - mail_cache_header_fields[idx]) != 0) + if (mail_cache_field_exists( + mail->trans->cache_view, + data->seq, + mail_cache_header_fields[idx]) > 0) break; } }
--- a/src/lib-storage/index/index-mail.c Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-storage/index/index-mail.c Thu Jul 08 23:26:15 2004 +0300 @@ -13,7 +13,7 @@ #include "index-storage.h" #include "index-mail.h" -static void index_mail_parse_body(struct index_mail *mail); +static void index_mail_parse_body(struct index_mail *mail, int need_parts); static struct message_part *get_cached_parts(struct index_mail *mail) { @@ -21,17 +21,13 @@ buffer_t *part_buf; const char *error; - if ((mail->data.cached_fields & MAIL_CACHE_MESSAGEPART) == 0) { - mail_cache_mark_missing(mail->trans->cache_view, mail->data.seq, - MAIL_CACHE_MESSAGEPART); - return NULL; - } - + t_push(); part_buf = buffer_create_dynamic(pool_datastack_create(), 128, (size_t)-1); - if (!mail_cache_lookup_field(mail->trans->cache_view, part_buf, - mail->data.seq, MAIL_CACHE_MESSAGEPART)) { - /* unexpected - must be an error */ + if (mail_cache_lookup_field(mail->trans->cache_view, part_buf, + mail->data.seq, + MAIL_CACHE_MESSAGEPART) <= 0) { + t_pop(); return NULL; } @@ -39,6 +35,8 @@ buffer_get_data(part_buf, NULL), buffer_get_used_size(part_buf), &error); + t_pop(); + if (part == NULL) { mail_cache_set_corrupted(mail->ibox->cache, "Corrupted cached message_part data (%s)", error); @@ -62,17 +60,13 @@ { string_t *str; - if ((mail->data.cached_fields & field) == 0) { - mail_cache_mark_missing(mail->trans->cache_view, - mail->data.seq, field); + str = str_new(mail->pool, 32); + if (mail_cache_lookup_string_field(mail->trans->cache_view, str, + mail->data.seq, field) <= 0) { + p_free(mail->pool, str); return NULL; } - str = str_new(mail->pool, 32); - if (!mail_cache_lookup_string_field(mail->trans->cache_view, str, - mail->data.seq, field)) - return NULL; - return str_c(str); } @@ -85,10 +79,8 @@ t_push(); buf = buffer_create_data(pool_datastack_create(), data, data_size); - if (!mail_cache_lookup_field(mail->trans->cache_view, buf, - mail->data.seq, field)) { - mail_cache_mark_missing(mail->trans->cache_view, - mail->data.seq, field); + if (mail_cache_lookup_field(mail->trans->cache_view, buf, + mail->data.seq, field) <= 0) { ret = FALSE; } else { i_assert(buffer_get_used_size(buf) == data_size); @@ -144,35 +136,6 @@ } } -static int index_mail_cache_can_add(struct index_mail *mail, - enum mail_cache_field field) -{ - if ((mail->data.cached_fields & field) != 0) - return FALSE; - - // FIXME: check if we really want to cache this - - index_mail_cache_transaction_begin(mail); - - /* cached_fields may have changed, recheck */ - if ((mail->data.cached_fields & field) != 0) - return FALSE; - - return TRUE; -} - -void index_mail_cache_add(struct index_mail *mail, enum mail_cache_field field, - const void *data, size_t size) -{ - if (!index_mail_cache_can_add(mail, field)) - return; - - mail_cache_add(mail->trans->cache_trans, mail->data.seq, - field, data, size); - - mail->data.cached_fields |= field; -} - const struct mail_full_flags *index_mail_get_flags(struct mail *_mail) { struct index_mail *mail = (struct index_mail *) _mail; @@ -194,17 +157,15 @@ if (data->parts != NULL) return data->parts; - if ((mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS) == 0) { - data->parts = get_cached_parts(mail); - if (data->parts != NULL) - return data->parts; - } + data->parts = get_cached_parts(mail); + if (data->parts != NULL) + return data->parts; if (data->parser_ctx == NULL) { if (!index_mail_parse_headers(mail)) return NULL; } - index_mail_parse_body(mail); + index_mail_parse_body(mail, TRUE); return data->parts; } @@ -251,9 +212,9 @@ tz = 0; } data->sent_date.timezone = tz; - index_mail_cache_add(mail, MAIL_CACHE_SENT_DATE, - &data->sent_date, - sizeof(data->sent_date)); + mail_cache_add(mail->trans->cache_trans, mail->data.seq, + MAIL_CACHE_SENT_DATE, &data->sent_date, + sizeof(data->sent_date)); } } @@ -266,12 +227,8 @@ { struct index_mail_data *data = &mail->data; - if (data->parts == NULL) { - if ((mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS) != 0) - (void)index_mail_get_parts(&mail->mail); - else - data->parts = get_cached_parts(mail); - } + if (data->parts == NULL) + (void)index_mail_get_parts(&mail->mail); if (data->parts != NULL) { data->hdr_size = data->parts->header_size; @@ -294,11 +251,9 @@ if (data->size != (uoff_t)-1) return data->size; - if ((mail->wanted_fields & MAIL_FETCH_SIZE) == 0) { - data->size = index_mail_get_cached_virtual_size(mail); - if (data->size != (uoff_t)-1) - return data->size; - } + data->size = index_mail_get_cached_virtual_size(mail); + if (data->size != (uoff_t)-1) + return data->size; if (get_msgpart_sizes(mail)) return data->size; @@ -318,10 +273,11 @@ imap_bodystructure_parse_header(pool, part, hdr); } -static void index_mail_parse_body(struct index_mail *mail) +static void index_mail_parse_body(struct index_mail *mail, int need_parts) { struct index_mail_data *data = &mail->data; enum mail_cache_record_flag cache_flags; + enum mail_cache_decision_type decision; buffer_t *buffer; const void *buf_data; size_t buf_size; @@ -332,6 +288,8 @@ i_stream_seek(data->stream, data->hdr_size.physical_size); if (data->bodystructure_header_parsed) { + /* bodystructure header is parsed, we want the body's mime + headers too */ message_parser_parse_body(data->parser_ctx, parse_bodystructure_header, NULL, mail->pool); @@ -344,41 +302,50 @@ data->body_size = data->parts->body_size; data->body_size_set = TRUE; - if (mail->mail.has_nuls || mail->mail.has_no_nuls) - return; - - /* we know the NULs now, update them */ - if ((data->parts->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0) { - mail->mail.has_nuls = TRUE; - mail->mail.has_no_nuls = FALSE; - } else { - mail->mail.has_nuls = FALSE; - mail->mail.has_no_nuls = TRUE; - } - index_mail_cache_transaction_begin(mail); - /* update cache_flags */ - cache_flags = mail_cache_get_record_flags(mail->trans->cache_view, - mail->data.seq); - if (mail->mail.has_nuls) - cache_flags |= MAIL_INDEX_FLAG_HAS_NULS; - else - cache_flags |= MAIL_INDEX_FLAG_HAS_NO_NULS; + if (!mail->mail.has_nuls && !mail->mail.has_no_nuls) { + /* we know the NULs now, update them */ + if ((data->parts->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0) { + mail->mail.has_nuls = TRUE; + mail->mail.has_no_nuls = FALSE; + } else { + mail->mail.has_nuls = FALSE; + mail->mail.has_no_nuls = TRUE; + } - if (!mail_cache_update_record_flags(mail->trans->cache_view, - mail->data.seq, cache_flags)) + /* update cache_flags */ + cache_flags = + mail_cache_get_record_flags(mail->trans->cache_view, + mail->data.seq); + if (mail->mail.has_nuls) + cache_flags |= MAIL_INDEX_FLAG_HAS_NULS; + else + cache_flags |= MAIL_INDEX_FLAG_HAS_NO_NULS; + + (void)mail_cache_update_record_flags(mail->trans->cache_view, + mail->data.seq, + cache_flags); + } + + /* see if we want to cache the message part */ + if (mail_cache_field_exists(mail->trans->cache_view, mail->data.seq, + MAIL_CACHE_MESSAGEPART) != 0) return; - if (index_mail_cache_can_add(mail, MAIL_CACHE_MESSAGEPART)) { + decision = mail_cache_field_get_decision(mail->ibox->cache, + MAIL_CACHE_MESSAGEPART); + if (decision != (MAIL_CACHE_DECISION_NO | MAIL_CACHE_DECISION_FORCED) && + (decision != MAIL_CACHE_DECISION_NO || need_parts || + (mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS) != 0)) { t_push(); buffer = buffer_create_dynamic(pool_datastack_create(), 1024, (size_t)-1); message_part_serialize(mail->data.parts, buffer); buf_data = buffer_get_data(buffer, &buf_size); - index_mail_cache_add(mail, MAIL_CACHE_MESSAGEPART, - buf_data, buf_size); + mail_cache_add(mail->trans->cache_trans, mail->data.seq, + MAIL_CACHE_MESSAGEPART, buf_data, buf_size); t_pop(); } } @@ -404,7 +371,7 @@ if (body_size != NULL) { if (!data->body_size_set) - index_mail_parse_body(mail); + index_mail_parse_body(mail, FALSE); *body_size = data->body_size; } @@ -418,83 +385,127 @@ return data->stream; } +static void index_mail_parse_bodystructure(struct index_mail *mail, + enum mail_cache_field field) +{ + struct index_mail_data *data = &mail->data; + enum mail_cache_decision_type dec; + string_t *str; + int bodystructure_cached = FALSE; + + if (!data->bodystructure_header_parsed) { + data->bodystructure_header_want = TRUE; + if (!index_mail_parse_headers(mail)) + return; + } + + if (data->parts != NULL) { + i_assert(data->parts->next == NULL); + message_parse_from_parts(data->parts->children, data->stream, + parse_bodystructure_header, + mail->pool); + } else { + index_mail_parse_body(mail, FALSE); + } + + dec = mail_cache_field_get_decision(mail->ibox->cache, + MAIL_CACHE_BODYSTRUCTURE); + if (field == MAIL_CACHE_BODYSTRUCTURE || + ((dec & ~MAIL_CACHE_DECISION_FORCED) != MAIL_CACHE_DECISION_NO && + mail_cache_field_exists(mail->trans->cache_view, data->seq, + MAIL_CACHE_BODYSTRUCTURE)) == 0) { + str = str_new(mail->pool, 128); + imap_bodystructure_write(data->parts, str, TRUE); + data->bodystructure = str_c(str); + + if (dec != + (MAIL_CACHE_DECISION_NO | MAIL_CACHE_DECISION_FORCED)) { + mail_cache_add(mail->trans->cache_trans, data->seq, + MAIL_CACHE_BODYSTRUCTURE, + str_c(str), str_len(str)+1); + bodystructure_cached = TRUE; + } + } + + dec = mail_cache_field_get_decision(mail->ibox->cache, MAIL_CACHE_BODY); + if (field == MAIL_CACHE_BODY || + ((dec & ~MAIL_CACHE_DECISION_FORCED) != MAIL_CACHE_DECISION_NO && + mail_cache_field_exists(mail->trans->cache_view, data->seq, + MAIL_CACHE_BODY)) == 0) { + str = str_new(mail->pool, 128); + imap_bodystructure_write(data->parts, str, FALSE); + data->body = str_c(str); + + if (!bodystructure_cached && dec != + (MAIL_CACHE_DECISION_NO | MAIL_CACHE_DECISION_FORCED)) { + mail_cache_add(mail->trans->cache_trans, data->seq, + MAIL_CACHE_BODY, + str_c(str), str_len(str)+1); + } + } +} + const char *index_mail_get_special(struct mail *_mail, enum mail_fetch_field field) { struct index_mail *mail = (struct index_mail *) _mail; struct index_mail_data *data = &mail->data; - struct mail_cache *cache = mail->ibox->cache; - enum mail_cache_field cache_field; - char *str; + string_t *str; switch (field) { case MAIL_FETCH_IMAP_BODY: - if ((data->cached_fields & MAIL_CACHE_BODY) && - data->body == NULL) { - data->body = index_mail_get_cached_string(mail, - MAIL_CACHE_BODY); - } if (data->body != NULL) return data->body; - /* fall through */ - case MAIL_FETCH_IMAP_BODYSTRUCTURE: - if ((data->cached_fields & MAIL_CACHE_BODYSTRUCTURE) && - data->bodystructure == NULL) { - data->bodystructure = index_mail_get_cached_string(mail, - MAIL_CACHE_BODYSTRUCTURE); - } - if (data->bodystructure != NULL) { - if (field == MAIL_FETCH_IMAP_BODYSTRUCTURE) - return data->bodystructure; + /* 1) get BODY if it exists + 2) get it using BODYSTRUCTURE if it exists + 3) parse body structure, and save BODY/BODYSTRUCTURE + depending on what we want cached */ - /* create BODY from cached BODYSTRUCTURE */ - t_push(); - data->body = p_strdup(mail->pool, - imap_body_parse_from_bodystructure( - data->bodystructure)); - t_pop(); - - if (data->body == NULL) { - mail_cache_set_corrupted(cache, - "Corrupted BODYSTRUCTURE"); - } + str = str_new(mail->pool, 128); + if (mail_cache_lookup_string_field(mail->trans->cache_view, + str, mail->data.seq, + MAIL_CACHE_BODY) > 0) { + data->body = str_c(str); return data->body; } - - if (!data->bodystructure_header_parsed) { - data->bodystructure_header_want = TRUE; - if (!index_mail_parse_headers(mail)) - return NULL; - } + if (mail_cache_lookup_string_field(mail->trans->cache_view, + str, mail->data.seq, + MAIL_CACHE_BODYSTRUCTURE) > 0) { + data->bodystructure = str_c(str); + str_truncate(str, 0); - if (data->parts != NULL) { - i_assert(data->parts->next == NULL); - message_parse_from_parts(data->parts->children, - data->stream, - parse_bodystructure_header, - mail->pool); - } else { - index_mail_parse_body(mail); - } + if (imap_body_parse_from_bodystructure( + data->bodystructure, str)) { + data->body = str_c(str); + return data->body; + } - t_push(); - str = p_strdup(mail->pool, imap_bodystructure_parse_finish( - data->parts, field == MAIL_FETCH_IMAP_BODYSTRUCTURE)); - t_pop(); - - /* should never fail */ - i_assert(str != NULL); + /* broken, continue.. */ + data->bodystructure = NULL; + mail_cache_set_corrupted(mail->ibox->cache, + "Corrupted BODYSTRUCTURE for mail %u", + mail->mail.uid); + } + p_free(mail->pool, str); - cache_field = field == MAIL_FETCH_IMAP_BODYSTRUCTURE ? - MAIL_CACHE_BODYSTRUCTURE : MAIL_CACHE_BODY; - index_mail_cache_add(mail, cache_field, str, strlen(str)+1); + index_mail_parse_bodystructure(mail, MAIL_CACHE_BODY); + return data->body; + case MAIL_FETCH_IMAP_BODYSTRUCTURE: + if (data->bodystructure != NULL) + return data->bodystructure; - if (field == MAIL_FETCH_IMAP_BODYSTRUCTURE) - data->bodystructure = str; - else - data->body = str; - return str; + str = str_new(mail->pool, 128); + if (mail_cache_lookup_string_field(mail->trans->cache_view, + str, mail->data.seq, + MAIL_CACHE_BODYSTRUCTURE) > 0) { + data->bodystructure = str_c(str); + return data->bodystructure; + } + p_free(mail->pool, str); + + index_mail_parse_bodystructure(mail, MAIL_CACHE_BODYSTRUCTURE); + return data->bodystructure; case MAIL_FETCH_IMAP_ENVELOPE: if (data->envelope != NULL) return data->envelope; @@ -550,13 +561,16 @@ index_mail_headers_close(mail); } -int index_mail_next(struct index_mail *mail, - const struct mail_index_record *rec, - uint32_t seq, int delay_open) +int index_mail_next(struct index_mail *mail, uint32_t seq) { struct index_mail_data *data = &mail->data; + const struct mail_index_record *rec; enum mail_cache_record_flag cache_flags; - int ret, open_mail; + + if (mail_index_lookup(mail->trans->trans_view, seq, &rec) < 0) { + mail_storage_set_index_error(mail->ibox); + return -1; + } t_push(); @@ -564,10 +578,7 @@ memset(data, 0, sizeof(*data)); p_clear(mail->pool); - data->cached_fields = - mail_cache_get_fields(mail->trans->cache_view, seq); - cache_flags = (data->cached_fields & MAIL_CACHE_INDEX_FLAGS) == 0 ? 0 : - mail_cache_get_record_flags(mail->trans->cache_view, seq); + cache_flags = mail_cache_get_record_flags(mail->trans->cache_view, seq); mail->mail.seq = seq; mail->mail.uid = rec->uid; @@ -599,7 +610,6 @@ get_cached_sent_date(mail, &data->sent_date); /* see if we have to parse the message */ - open_mail = FALSE; if ((mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS) && data->parts == NULL) data->parse_header = TRUE; @@ -607,36 +617,22 @@ data->bodystructure == NULL) { if (data->parts == NULL) data->parts = get_cached_parts(mail); - open_mail = TRUE; + data->open_mail = TRUE; data->parse_header = data->parts == NULL; - data->bodystructure_header_want = TRUE; + data->bodystructure_header_want = TRUE; } else if ((mail->wanted_fields & MAIL_FETCH_IMAP_BODY) && data->body == NULL && data->bodystructure == NULL) { if (data->parts == NULL) data->parts = get_cached_parts(mail); - open_mail = TRUE; + data->open_mail = TRUE; data->parse_header = data->parts == NULL; data->bodystructure_header_want = TRUE; } else if (mail->wanted_fields & (MAIL_FETCH_STREAM_HEADER | MAIL_FETCH_STREAM_BODY)) - open_mail = TRUE; + data->open_mail = TRUE; index_mail_headers_init_next(mail); - if ((open_mail || data->parse_header) && !delay_open) { - if (mail->mail.get_stream(&mail->mail, NULL, NULL) == NULL) - ret = data->deleted ? 0 : -1; - else - ret = 1; - } else { - if (mail->wanted_fields & MAIL_FETCH_RECEIVED_DATE) { - /* check this only after open_mail() */ - data->received_date = - index_mail_get_cached_received_date(mail); - } - ret = 1; - } - if ((mail->wanted_fields & MAIL_FETCH_DATE) && data->sent_date.time == (time_t)-1) data->save_sent_date = TRUE; @@ -645,7 +641,7 @@ data->save_envelope = TRUE; t_pop(); - return ret; + return 0; } void index_mail_deinit(struct index_mail *mail)
--- a/src/lib-storage/index/index-mail.h Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-storage/index/index-mail.h Thu Jul 08 23:26:15 2004 +0300 @@ -12,7 +12,6 @@ time_t date, received_date; uoff_t size; - enum mail_cache_field cached_fields; struct mail_sent_date sent_date; buffer_t *headers; @@ -46,6 +45,7 @@ unsigned int header_data_cached_partial:1; unsigned int header_fully_parsed:1; unsigned int header_save:1; + unsigned int open_mail:1; }; struct index_mail { @@ -68,9 +68,7 @@ struct index_mail *mail, enum mail_fetch_field wanted_fields, const char *const wanted_headers[]); -int index_mail_next(struct index_mail *mail, - const struct mail_index_record *rec, - uint32_t seq, int delay_open); +int index_mail_next(struct index_mail *mail, uint32_t seq); void index_mail_deinit(struct index_mail *mail); void index_mail_parse_header_init(struct index_mail *mail, @@ -80,9 +78,6 @@ struct index_mail *mail); void index_mail_cache_transaction_begin(struct index_mail *mail); -void index_mail_cache_add(struct index_mail *mail, enum mail_cache_field field, - const void *data, size_t size); - int index_mail_parse_headers(struct index_mail *mail); void index_mail_headers_init(struct index_mail *mail);
--- a/src/lib-storage/index/index-search.c Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-storage/index/index-search.c Thu Jul 08 23:26:15 2004 +0300 @@ -810,21 +810,15 @@ struct mail *index_storage_search_next(struct mail_search_context *_ctx) { struct index_search_context *ctx = (struct index_search_context *)_ctx; - const struct mail_index_record *rec; int ret; ret = 0; while (ctx->seq1 <= ctx->seq2) { - if (mail_index_lookup(ctx->view, ctx->seq1, &rec) < 0) { + if (index_mail_next(&ctx->imail, ctx->seq1++) < 0) { ctx->failed = TRUE; - mail_storage_set_index_error(ctx->ibox); return NULL; } - ret = index_mail_next(&ctx->imail, rec, ctx->seq1++, TRUE); - if (ret < 0) - break; - t_push(); ret = search_match_next(ctx); t_pop();
--- a/src/lib-storage/index/index-storage.c Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-storage/index/index-storage.c Thu Jul 08 23:26:15 2004 +0300 @@ -1,6 +1,7 @@ /* Copyright (C) 2002-2003 Timo Sirainen */ #include "lib.h" +#include "buffer.h" #include "ioloop.h" #include "mail-index.h" #include "index-storage.h" @@ -172,15 +173,17 @@ destroy_unrefed(TRUE); } -static enum mail_cache_field get_cache_fields(const char *fields) +static void set_cache_fields(const char *fields, + enum mail_cache_decision_type dest[32], + enum mail_cache_decision_type dec) { - static enum mail_cache_field field_masks[] = { + static enum mail_cache_field field_enums[] = { MAIL_CACHE_SENT_DATE, MAIL_CACHE_RECEIVED_DATE, MAIL_CACHE_VIRTUAL_FULL_SIZE, MAIL_CACHE_BODY, MAIL_CACHE_BODYSTRUCTURE, - MAIL_CACHE_MESSAGEPART, + MAIL_CACHE_MESSAGEPART }; static const char *field_names[] = { "sent_date", @@ -193,17 +196,15 @@ }; const char *const *arr; - enum mail_cache_field ret; int i; if (fields == NULL || *fields == '\0') - return 0; + return; - ret = 0; for (arr = t_strsplit_spaces(fields, " ,"); *arr != NULL; arr++) { for (i = 0; field_names[i] != NULL; i++) { if (strcasecmp(field_names[i], *arr) == 0) { - ret |= field_masks[i]; + dest[field_enums[i]] = dec; break; } } @@ -212,34 +213,22 @@ *arr); } } - - return ret; } -static enum mail_cache_field get_default_cache_fields(void) +static const enum mail_cache_decision_type *get_default_cache_decisions(void) { - static enum mail_cache_field ret = 0; - static int ret_set = FALSE; - - if (ret_set) - return ret; + static enum mail_cache_decision_type dec[32]; + static int dec_set = FALSE; - ret = get_cache_fields(getenv("MAIL_CACHE_FIELDS")); - ret_set = TRUE; - return ret; -} + if (dec_set) + return dec; -static enum mail_cache_field get_never_cache_fields(void) -{ - static enum mail_cache_field ret = 0; - static int ret_set = FALSE; - - if (ret_set) - return ret; - - ret = get_cache_fields(getenv("MAIL_NEVER_CACHE_FIELDS")); - ret_set = TRUE; - return ret; + memset(dec, 0, sizeof(dec)); + set_cache_fields(getenv("MAIL_CACHE_FIELDS"), dec, + MAIL_CACHE_DECISION_TEMP); + set_cache_fields(getenv("MAIL_NEVER_CACHE_FIELDS"), dec, + MAIL_CACHE_DECISION_NO | MAIL_CACHE_DECISION_FORCED); + return dec; } void index_storage_lock_notify(struct index_mailbox *ibox, @@ -339,9 +328,7 @@ ibox->cache = mail_index_get_cache(index); mail_cache_set_defaults(ibox->cache, - get_default_cache_fields(), - get_never_cache_fields()); - + get_default_cache_decisions()); ibox->view = mail_index_view_open(index); return ibox; } while (0);
--- a/src/lib-storage/index/maildir/maildir-mail.c Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-storage/index/maildir/maildir-mail.c Thu Jul 08 23:26:15 2004 +0300 @@ -87,6 +87,11 @@ if (data->received_date != (time_t)-1) return data->received_date; + if (data->open_mail && data->stream == NULL) { + /* we're going to open the mail anyway */ + (void)_mail->get_stream(_mail, NULL, NULL); + } + if (data->stream != NULL) { fd = i_stream_get_fd(data->stream); i_assert(fd != -1); @@ -103,8 +108,9 @@ } data->received_date = st.st_mtime; - index_mail_cache_add(mail, MAIL_CACHE_RECEIVED_DATE, - &data->received_date, sizeof(data->received_date)); + mail_cache_add(mail->trans->cache_trans, mail->data.seq, + MAIL_CACHE_RECEIVED_DATE, + &data->received_date, sizeof(data->received_date)); return data->received_date; } @@ -141,9 +147,9 @@ } if (*p == ':' || *p == ',' || *p == '\0') { - index_mail_cache_add(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE, - &virtual_size, - sizeof(virtual_size)); + mail_cache_add(mail->trans->cache_trans, mail->data.seq, + MAIL_CACHE_VIRTUAL_FULL_SIZE, + &virtual_size, sizeof(virtual_size)); return virtual_size; } } @@ -162,8 +168,10 @@ if (data->stream == NULL) { data->stream = maildir_open_mail(mail->ibox, mail->mail.uid, &deleted); - if (data->stream == NULL) + if (data->stream == NULL) { + data->deleted = deleted; return NULL; + } } return index_mail_init_stream(mail, hdr_size, body_size);
--- a/src/lib-storage/index/maildir/maildir-save.c Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-storage/index/maildir/maildir-save.c Thu Jul 08 23:26:15 2004 +0300 @@ -201,11 +201,7 @@ t_pop(); if (mail_r != NULL) { - const struct mail_index_record *rec; - - if (mail_index_lookup(t->ictx.trans_view, seq, &rec) < 0) - return -1; - if (index_mail_next(&ctx->mail, rec, seq, FALSE) <= 0) + if (index_mail_next(&ctx->mail, seq) < 0) return -1; *mail_r = &ctx->mail.mail; }
--- a/src/lib-storage/index/mbox/mbox-mail.c Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-storage/index/mbox/mbox-mail.c Thu Jul 08 23:26:15 2004 +0300 @@ -20,6 +20,9 @@ uint64_t offset; int ret; + if (mail->data.deleted) + return 0; + if (ibox->mbox_lock_type == F_UNLCK) { if (mbox_sync(ibox, FALSE, FALSE, TRUE) < 0) return -1; @@ -36,7 +39,9 @@ if (ret <= 0) { if (ret < 0) mail_storage_set_index_error(ibox); - return -1; + else + mail->data.deleted = TRUE; + return ret; } offset = *((const uint64_t *)data); @@ -47,7 +52,7 @@ mail_index_mark_corrupted(ibox->index); return -1; } - return 0; + return 1; } static const struct mail_full_flags *mbox_mail_get_flags(struct mail *_mail) @@ -74,7 +79,7 @@ if (data->received_date != (time_t)-1) return data->received_date; - if (mbox_mail_seek(mail) < 0) + if (mbox_mail_seek(mail) <= 0) return (time_t)-1; data->received_date = istream_raw_mbox_get_received_time(mail->ibox->mbox_stream); @@ -84,9 +89,9 @@ data->received_date = 0; } - index_mail_cache_add(mail, MAIL_CACHE_RECEIVED_DATE, - &data->received_date, - sizeof(data->received_date)); + mail_cache_add(mail->trans->cache_trans, mail->data.seq, + MAIL_CACHE_RECEIVED_DATE, + &data->received_date, sizeof(data->received_date)); return data->received_date; } @@ -96,7 +101,7 @@ struct index_mail *mail = (struct index_mail *)_mail; if (field == MAIL_FETCH_FROM_ENVELOPE) { - if (mbox_mail_seek(mail) < 0) + if (mbox_mail_seek(mail) <= 0) return NULL; return istream_raw_mbox_get_sender(mail->ibox->mbox_stream); @@ -116,10 +121,9 @@ uoff_t offset; if (data->stream == NULL) { - if (mbox_mail_seek(mail) < 0) + if (mbox_mail_seek(mail) <= 0) return NULL; - // FIXME: need to hide the headers raw_stream = mail->ibox->mbox_stream; offset = istream_raw_mbox_get_header_offset(raw_stream); raw_stream = i_stream_create_limit(default_pool, raw_stream,
--- a/src/lib-storage/index/mbox/mbox-save.c Thu Jul 08 23:24:48 2004 +0300 +++ b/src/lib-storage/index/mbox/mbox-save.c Thu Jul 08 23:26:15 2004 +0300 @@ -344,11 +344,7 @@ t_pop(); if (mail_r != NULL) { - const struct mail_index_record *rec; - - if (mail_index_lookup(t->ictx.trans_view, seq, &rec) < 0) - return -1; - if (index_mail_next(&ctx->mail, rec, seq, FALSE) <= 0) + if (index_mail_next(&ctx->mail, seq) < 0) return -1; *mail_r = &ctx->mail.mail; }