Mercurial > dovecot > original-hg > dovecot-1.2
changeset 6265:0ee2b0691f3e HEAD
Cache received date, sent date, save date and physical size when saving
mails if they're wanted.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 11 Aug 2007 14:35:36 +0300 |
parents | 10acca6dd37d |
children | 3fabc189d17c |
files | src/lib-storage/index/cydir/cydir-save.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/maildir/maildir-save.c src/lib-storage/index/mbox/mbox-save.c |
diffstat | 6 files changed, 160 insertions(+), 70 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/cydir/cydir-save.c Sat Aug 11 14:27:40 2007 +0300 +++ b/src/lib-storage/index/cydir/cydir-save.c Sat Aug 11 14:35:36 2007 +0300 @@ -29,6 +29,7 @@ struct istream *input; struct ostream *output; struct mail *mail, *cur_dest_mail; + time_t cur_received_date; int fd; unsigned int failed:1; @@ -89,18 +90,6 @@ ctx->output = o_stream_create_crlf(output); o_stream_unref(&output); o_stream_cork(ctx->output); - - if (received_date != (time_t)-1) { - struct utimbuf ut; - - ut.actime = ioloop_time; - ut.modtime = received_date; - if (utime(path, &ut) < 0) { - mail_storage_set_critical(_t->box->storage, - "utime(%s) failed: %m", path); - /* ignore this error anyway */ - } - } } else { mail_storage_set_critical(_t->box->storage, "open(%s) failed: %m", path); @@ -130,6 +119,7 @@ ctx->cur_dest_mail = dest_mail; ctx->input = index_mail_cache_parse_init(dest_mail, input); + ctx->cur_received_date = received_date; *ctx_r = &ctx->ctx; return ctx->failed ? -1 : 0; @@ -167,6 +157,7 @@ struct cydir_save_context *ctx = (struct cydir_save_context *)_ctx; struct mail_storage *storage = &ctx->mbox->storage->storage; const char *path = cydir_get_save_path(ctx, ctx->mail_count); + struct stat st; ctx->finished = TRUE; @@ -184,6 +175,26 @@ } } + if (ctx->cur_received_date == (time_t)-1) { + if (fstat(ctx->fd, &st) == 0) + ctx->cur_received_date = st.st_mtime; + else { + mail_storage_set_critical(storage, + "fstat(%s) failed: %m", path); + ctx->failed = TRUE; + } + } else { + struct utimbuf ut; + + ut.actime = ioloop_time; + ut.modtime = ctx->cur_received_date; + if (utime(path, &ut) < 0) { + mail_storage_set_critical(storage, + "utime(%s) failed: %m", path); + ctx->failed = TRUE; + } + } + o_stream_destroy(&ctx->output); if (close(ctx->fd) < 0) { mail_storage_set_critical(storage, @@ -201,7 +212,8 @@ } } - index_mail_cache_parse_deinit(ctx->cur_dest_mail); + index_mail_cache_parse_deinit(ctx->cur_dest_mail, + ctx->cur_received_date); i_stream_unref(&ctx->input); return ctx->failed ? -1 : 0;
--- a/src/lib-storage/index/index-mail-headers.c Sat Aug 11 14:27:40 2007 +0300 +++ b/src/lib-storage/index/index-mail-headers.c Sat Aug 11 14:35:36 2007 +0300 @@ -341,8 +341,8 @@ index_mail_parse_header(mail->data.parts, hdr, mail); } -struct istream *index_mail_cache_parse_init(struct mail *_mail, - struct istream *input) +struct istream * +index_mail_cache_parse_init(struct mail *_mail, struct istream *input) { struct index_mail *mail = (struct index_mail *)_mail; struct tee_istream *tee;
--- a/src/lib-storage/index/index-mail.c Sat Aug 11 14:27:40 2007 +0300 +++ b/src/lib-storage/index/index-mail.c Sat Aug 11 14:35:36 2007 +0300 @@ -3,6 +3,7 @@ #include "lib.h" #include "array.h" #include "buffer.h" +#include "ioloop.h" #include "istream.h" #include "hex-binary.h" #include "str.h" @@ -225,11 +226,33 @@ return data->save_date; } +static void index_mail_cache_sent_date(struct index_mail *mail) +{ + struct index_mail_data *data = &mail->data; + const char *str; + time_t t; + int tz; + + if (data->sent_date.time != (uint32_t)-1) + return; + + str = mail_get_first_header(&mail->mail.mail, "Date"); + if (str == NULL || !message_date_parse((const unsigned char *)str, + strlen(str), &t, &tz)) { + /* 0 = not found / invalid */ + t = 0; + tz = 0; + } + data->sent_date.time = t; + data->sent_date.timezone = tz; + index_mail_cache_add(mail, MAIL_CACHE_SENT_DATE, + &data->sent_date, sizeof(data->sent_date)); +} + time_t index_mail_get_date(struct mail *_mail, int *timezone) { struct index_mail *mail = (struct index_mail *) _mail; struct index_mail_data *data = &mail->data; - const char *str; if (data->sent_date.time != (uint32_t)-1) { if (timezone != NULL) @@ -241,24 +264,7 @@ &data->sent_date, sizeof(data->sent_date)); - if (data->sent_date.time == (uint32_t)-1) { - time_t t; - int tz; - - str = mail_get_first_header(_mail, "Date"); - if (str == NULL || - !message_date_parse((const unsigned char *)str, - strlen(str), &t, &tz)) { - /* 0 = not found / invalid */ - t = 0; - tz = 0; - } - data->sent_date.time = t; - data->sent_date.timezone = tz; - index_mail_cache_add(mail, MAIL_CACHE_SENT_DATE, - &data->sent_date, sizeof(data->sent_date)); - } - + index_mail_cache_sent_date(mail); if (timezone != NULL) *timezone = data->sent_date.timezone; return data->sent_date.time; @@ -561,17 +567,27 @@ } } -static void -index_mail_body_parsed_cache_virtual_size(struct index_mail *mail) +static void index_mail_body_parsed_cache_sizes(struct index_mail *mail) { - unsigned int cache_field = - mail->ibox->cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx; + static enum index_cache_field date_fields[] = { + MAIL_CACHE_VIRTUAL_FULL_SIZE, + MAIL_CACHE_PHYSICAL_FULL_SIZE + }; + uoff_t sizes[N_ELEMENTS(date_fields)]; + unsigned int i, cache_field; - if (mail_cache_field_want_add(mail->trans->cache_trans, - mail->data.seq, cache_field)) { - index_mail_cache_add(mail, MAIL_CACHE_VIRTUAL_FULL_SIZE, - &mail->data.virtual_size, - sizeof(mail->data.virtual_size)); + sizes[0] = mail->data.virtual_size; + sizes[1] = mail->data.physical_size; + + for (i = 0; i < N_ELEMENTS(date_fields); i++) { + cache_field = mail->ibox->cache_fields[date_fields[i]].idx; + + i_assert(sizes[i] != (uoff_t)-1); + if (mail_cache_field_want_add(mail->trans->cache_trans, + mail->data.seq, cache_field)) { + index_mail_cache_add(mail, date_fields[i], + &sizes[i], sizeof(sizes[i])); + } } } @@ -592,7 +608,7 @@ index_mail_body_parsed_cache_flags(mail); index_mail_body_parsed_cache_message_parts(mail); index_mail_body_parsed_cache_bodystructure(mail, field); - index_mail_body_parsed_cache_virtual_size(mail); + index_mail_body_parsed_cache_sizes(mail); } static void index_mail_parse_body(struct index_mail *mail, @@ -1095,13 +1111,54 @@ } } -void index_mail_cache_parse_deinit(struct mail *_mail) +static void index_mail_cache_dates(struct index_mail *mail) +{ + static enum index_cache_field date_fields[] = { + MAIL_CACHE_RECEIVED_DATE, + MAIL_CACHE_SAVE_DATE + }; + time_t dates[N_ELEMENTS(date_fields)]; + unsigned int i, cache_field; + uint32_t t; + + dates[0] = mail->data.received_date; + dates[1] = mail->data.save_date; + + for (i = 0; i < N_ELEMENTS(date_fields); i++) { + cache_field = mail->ibox->cache_fields[date_fields[i]].idx; + + i_assert(dates[i] != (time_t)-1); + if (mail_cache_field_want_add(mail->trans->cache_trans, + mail->data.seq, cache_field)) { + t = dates[i]; + index_mail_cache_add(mail, date_fields[i], + &t, sizeof(t)); + } + } + + cache_field = mail->ibox->cache_fields[MAIL_CACHE_SENT_DATE].idx; + if (mail_cache_field_want_add(mail->trans->cache_trans, + mail->data.seq, cache_field)) + index_mail_cache_sent_date(mail); +} + +void index_mail_cache_parse_deinit(struct mail *_mail, time_t received_date) { struct index_mail *mail = (struct index_mail *)_mail; + if (mail->data.received_date == (time_t)-1) + mail->data.received_date = received_date; + if (mail->data.save_date == (time_t)-1) { + /* this save_date may not be exactly the same as what we get + in future, but then again neither mbox nor maildir + guarantees it anyway. */ + mail->data.save_date = ioloop_time; + } + mail->data.save_bodystructure_body = FALSE; mail->data.parsed_bodystructure = TRUE; index_mail_parse_body_finish(mail, 0, TRUE); + index_mail_cache_dates(mail); } int index_mail_update_flags(struct mail *mail, enum modify_type modify_type,
--- a/src/lib-storage/index/index-mail.h Sat Aug 11 14:27:40 2007 +0300 +++ b/src/lib-storage/index/index-mail.h Sat Aug 11 14:35:36 2007 +0300 @@ -187,6 +187,6 @@ struct istream *index_mail_cache_parse_init(struct mail *mail, struct istream *input); void index_mail_cache_parse_continue(struct mail *mail); -void index_mail_cache_parse_deinit(struct mail *mail); +void index_mail_cache_parse_deinit(struct mail *mail, time_t received_date); #endif
--- a/src/lib-storage/index/maildir/maildir-save.c Sat Aug 11 14:27:40 2007 +0300 +++ b/src/lib-storage/index/maildir/maildir-save.c Sat Aug 11 14:35:36 2007 +0300 @@ -427,36 +427,27 @@ int maildir_save_finish(struct mail_save_context *_ctx) { struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx; + struct mail_storage *storage = &ctx->mbox->storage->storage; struct utimbuf buf; + struct stat st; const char *path; int output_errno; - if (o_stream_flush(ctx->output) < 0) { - mail_storage_set_critical(&ctx->mbox->storage->storage, - "o_stream_flush(%s/%s) failed: %m", - ctx->tmpdir, ctx->file_last->basename); - ctx->failed = TRUE; - } - - if (ctx->cur_dest_mail != NULL) { - index_mail_cache_parse_deinit(ctx->cur_dest_mail); - i_stream_unref(&ctx->input); - } - ctx->finished = TRUE; if (ctx->failed && ctx->fd == -1) { /* tmp file creation failed */ return -1; } - /* remember the size in case we want to add it to filename */ - ctx->file_last->size = ctx->output->offset; - ctx->file_last->vsize = ctx->cur_dest_mail == NULL ? (uoff_t)-1 : - mail_get_virtual_size(ctx->cur_dest_mail); - t_push(); path = t_strconcat(ctx->tmpdir, "/", ctx->file_last->basename, NULL); + if (o_stream_flush(ctx->output) < 0) { + mail_storage_set_critical(storage, + "o_stream_flush(%s) failed: %m", path); + ctx->failed = TRUE; + } + if (ctx->received_date != (time_t)-1) { /* set the received_date by modifying mtime */ buf.actime = ioloop_time; @@ -464,23 +455,51 @@ if (utime(path, &buf) < 0) { ctx->failed = TRUE; - mail_storage_set_critical(&ctx->mbox->storage->storage, + mail_storage_set_critical(storage, "utime(%s) failed: %m", path); } + } else if (ctx->fd != -1) { + if (fstat(ctx->fd, &st) == 0) + ctx->received_date = st.st_mtime; + else { + ctx->failed = TRUE; + mail_storage_set_critical(storage, + "fstat(%s) failed: %m", path); + } + } else { + /* hardlinked */ + if (stat(path, &st) == 0) + ctx->received_date = st.st_mtime; + else { + ctx->failed = TRUE; + mail_storage_set_critical(storage, + "stat(%s) failed: %m", path); + } } + if (ctx->cur_dest_mail != NULL) { + index_mail_cache_parse_deinit(ctx->cur_dest_mail, + ctx->received_date); + i_stream_unref(&ctx->input); + } + + /* remember the size in case we want to add it to filename */ + ctx->file_last->size = ctx->output->offset; + ctx->file_last->vsize = ctx->cur_dest_mail == NULL ? (uoff_t)-1 : + mail_get_virtual_size(ctx->cur_dest_mail); + output_errno = ctx->output->stream_errno; o_stream_destroy(&ctx->output); if (!ctx->mbox->ibox.fsync_disable) { if (fsync(ctx->fd) < 0) { - mail_storage_set_critical(&ctx->mbox->storage->storage, + mail_storage_set_critical(storage, "fsync(%s) failed: %m", path); ctx->failed = TRUE; } } if (close(ctx->fd) < 0) { - mail_storage_set_critical(&ctx->mbox->storage->storage, + mail_storage_set_critical(storage, "close(%s) failed: %m", path); ctx->failed = TRUE; } @@ -491,16 +510,16 @@ /* delete the tmp file */ if (unlink(path) < 0 && errno != ENOENT) { - mail_storage_set_critical(&ctx->mbox->storage->storage, + mail_storage_set_critical(storage, "unlink(%s) failed: %m", path); } errno = output_errno; if (ENOSPACE(errno)) { - mail_storage_set_error(&ctx->mbox->storage->storage, + mail_storage_set_error(storage, MAIL_ERROR_NOSPACE, MAIL_ERRSTR_NO_SPACE); } else if (errno != 0) { - mail_storage_set_critical(&ctx->mbox->storage->storage, + mail_storage_set_critical(storage, "write(%s) failed: %m", ctx->mbox->path); }
--- a/src/lib-storage/index/mbox/mbox-save.c Sat Aug 11 14:27:40 2007 +0300 +++ b/src/lib-storage/index/mbox/mbox-save.c Sat Aug 11 14:35:36 2007 +0300 @@ -39,6 +39,7 @@ struct mail *mail; uoff_t append_offset, mail_offset; time_t orig_atime; + time_t received_date; string_t *headers; size_t space_end_idx; @@ -465,6 +466,7 @@ ctx->eoh_input_offset = (uoff_t)-1; ctx->eoh_offset = (uoff_t)-1; ctx->last_char = '\n'; + ctx->received_date = received_date; if (write_from_line(ctx, received_date, from_envelope) < 0) ctx->failed = TRUE; @@ -611,7 +613,7 @@ } if (ctx->mail != NULL) - index_mail_cache_parse_deinit(ctx->mail); + index_mail_cache_parse_deinit(ctx->mail, ctx->received_date); if (ctx->input != NULL) i_stream_destroy(&ctx->input); if (ctx->body_output != NULL)