Mercurial > dovecot > original-hg > dovecot-1.2
view src/lib-storage/index/dbox/dbox-mail.c @ 6842:d2c8269a0679 HEAD
Cleanups/rewrites to how/when date/size caching is done.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 22 Nov 2007 09:36:57 +0200 |
parents | f8baedac2417 |
children | 58b8daf695bf |
line wrap: on
line source
/* Copyright (c) 2007 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "istream.h" #include "index-mail.h" #include "dbox-storage.h" #include "dbox-file.h" #include <stdlib.h> struct dbox_mail { struct index_mail imail; struct dbox_file *open_file; uoff_t offset; }; struct mail * dbox_mail_alloc(struct mailbox_transaction_context *t, enum mail_fetch_field wanted_fields, struct mailbox_header_lookup_ctx *wanted_headers) { struct dbox_mail *mail; pool_t pool; pool = pool_alloconly_create("mail", 1024); mail = p_new(pool, struct dbox_mail, 1); mail->imail.mail.pool = pool; index_mail_init(&mail->imail, t, wanted_fields, wanted_headers); return &mail->imail.mail.mail; } static void dbox_mail_close(struct mail *_mail) { struct dbox_mail *mail = (struct dbox_mail *)_mail; if (mail->open_file != NULL) dbox_file_unref(&mail->open_file); index_mail_close(_mail); } static int dbox_mail_lookup(struct dbox_mail *mail, uoff_t *offset_r, struct dbox_file **file_r) { struct dbox_mailbox *mbox = (struct dbox_mailbox *)mail->imail.ibox; unsigned int file_id; if (mail->open_file == NULL) { if (!dbox_file_lookup(mbox, mbox->ibox.view, mail->imail.mail.mail.seq, &file_id, &mail->offset)) { mail_set_expunged(&mail->imail.mail.mail); return -1; } mail->open_file = dbox_file_init(mbox, file_id); } *file_r = mail->open_file; *offset_r = mail->offset; return 0; } static int dbox_mail_metadata_seek(struct dbox_mail *mail, struct dbox_file **file_r) { uoff_t offset; bool expunged; int ret; if (dbox_mail_lookup(mail, &offset, file_r) < 0) return -1; ret = dbox_file_metadata_seek_mail_offset(*file_r, offset, &expunged); if (ret <= 0) { if (ret < 0) return -1; /* FIXME */ return -1; } if (expunged) { mail_set_expunged(&mail->imail.mail.mail); return -1; } return 0; } static int dbox_mail_get_received_date(struct mail *_mail, time_t *date_r) { struct dbox_mail *mail = (struct dbox_mail *)_mail; struct index_mail_data *data = &mail->imail.data; struct dbox_file *file; const char *value; if (index_mail_get_received_date(_mail, date_r) == 0) return 0; if (dbox_mail_metadata_seek(mail, &file) < 0) return -1; value = dbox_file_metadata_get(file, DBOX_METADATA_RECEIVED_TIME); data->received_date = value == NULL ? 0 : strtoul(value, NULL, 16); *date_r = data->received_date; return 0; } static int dbox_mail_get_save_date(struct mail *_mail, time_t *date_r) { struct dbox_mail *mail = (struct dbox_mail *)_mail; struct index_mail_data *data = &mail->imail.data; struct dbox_file *file; const char *value; if (index_mail_get_save_date(_mail, date_r) == 0) return 0; if (dbox_mail_metadata_seek(mail, &file) < 0) return -1; value = dbox_file_metadata_get(file, DBOX_METADATA_SAVE_TIME); data->save_date = value == NULL ? 0 : strtoul(value, NULL, 16); *date_r = data->save_date; return 0; } static int dbox_mail_get_virtual_size(struct mail *_mail, uoff_t *size_r) { struct dbox_mail *mail = (struct dbox_mail *)_mail; struct index_mail_data *data = &mail->imail.data; struct dbox_file *file; const char *value; if (index_mail_get_cached_virtual_size(&mail->imail, size_r)) return 0; if (dbox_mail_metadata_seek(mail, &file) < 0) return -1; value = dbox_file_metadata_get(file, DBOX_METADATA_VIRTUAL_SIZE); if (value == NULL) return index_mail_get_virtual_size(_mail, size_r); data->virtual_size = strtoul(value, NULL, 16); *size_r = data->virtual_size; return 0; } static int dbox_mail_get_physical_size(struct mail *_mail, uoff_t *size_r) { struct index_mail *mail = (struct index_mail *)_mail; struct index_mail_data *data = &mail->data; struct istream *input; if (index_mail_get_physical_size(_mail, size_r) == 0) return 0; if (mail_get_stream(_mail, NULL, NULL, &input) < 0) return -1; i_assert(data->physical_size != (uoff_t)-1); *size_r = data->physical_size; return 0; } static int dbox_mail_get_stream(struct mail *_mail, struct message_size *hdr_size, struct message_size *body_size, struct istream **stream_r) { struct dbox_mail *mail = (struct dbox_mail *)_mail; struct index_mail_data *data = &mail->imail.data; struct istream *input; uoff_t offset, size; uint32_t uid; bool expunged; int ret; if (data->stream == NULL) { if (dbox_mail_lookup(mail, &offset, &mail->open_file) < 0) return -1; ret = dbox_file_get_mail_stream(mail->open_file, offset, &uid, &size, &input, &expunged); if (ret < 0) return -1; if (ret > 0 && expunged) { mail_set_expunged(_mail); return -1; } if (ret == 0 || uid != _mail->uid) { /* FIXME: broken file/offset */ if (ret > 0) i_stream_unref(&input); return -1; } data->physical_size = size; data->stream = input; } return index_mail_init_stream(&mail->imail, hdr_size, body_size, stream_r); } struct mail_vfuncs dbox_mail_vfuncs = { dbox_mail_close, index_mail_free, index_mail_set_seq, index_mail_set_uid, index_mail_get_flags, index_mail_get_keywords, index_mail_get_parts, index_mail_get_date, dbox_mail_get_received_date, dbox_mail_get_save_date, dbox_mail_get_virtual_size, dbox_mail_get_physical_size, index_mail_get_first_header, index_mail_get_headers, index_mail_get_header_stream, dbox_mail_get_stream, index_mail_get_special, index_mail_update_flags, index_mail_update_keywords, index_mail_expunge };