Mercurial > dovecot > original-hg > dovecot-1.2
view src/lib-storage/index/dbox/dbox-mail.c @ 6289:4a57baddc8b8 HEAD
Added mail.close() virtual function.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 13 Aug 2007 17:19:59 +0300 |
parents | eb7c9d8ece54 |
children | 7b71ba1250e3 |
line wrap: on
line source
/* Copyright (C) 2005 Timo Sirainen */ #include "lib.h" #include "ioloop.h" #include "hex-dec.h" #include "read-full.h" #include "istream.h" #include "index-mail.h" #include "dbox-file.h" #include "dbox-sync.h" #include "dbox-storage.h" #include <fcntl.h> #include <unistd.h> #include <sys/stat.h> static int dbox_mail_parse_mail_header(struct index_mail *mail, struct dbox_file *file) { struct dbox_mailbox *mbox = (struct dbox_mailbox *)mail->mail.mail.box; const struct dbox_mail_header *hdr = &file->seeked_mail_header; uint32_t hdr_uid = hex2dec(hdr->uid_hex, sizeof(hdr->uid_hex)); if (hdr_uid != mail->mail.mail.uid) { mail_storage_set_critical(&mbox->storage->storage, "dbox %s: Cached file offset broken", mbox->file->path); /* make sure we get it fixed */ (void)dbox_sync(mbox, TRUE); return -1; } /* Note that the mail may already have an expunge flag, but we don't care since we can still read it */ mail->data.physical_size = mail->data.virtual_size = hex2dec(hdr->mail_size_hex, sizeof(hdr->mail_size_hex)); mail->data.received_date = hex2dec(hdr->received_time_hex, sizeof(hdr->received_time_hex)); return 1; } int dbox_mail_lookup_offset(struct index_transaction_context *trans, uint32_t seq, uint32_t *file_seq_r, uoff_t *offset_r) { struct dbox_mailbox *mbox = (struct dbox_mailbox *)trans->ibox; uint32_t uid; bool synced = FALSE; int ret; for (;;) { ret = dbox_file_lookup_offset(mbox, trans->trans_view, seq, file_seq_r, offset_r); if (ret <= 0) return ret; if (*file_seq_r != 0) return 1; /* lost file sequence/offset */ if (synced) return -1; mail_index_lookup_uid(trans->trans_view, seq, &uid); mail_storage_set_critical(&mbox->storage->storage, "Cached message offset lost for uid %u in " "dbox %s", uid, mbox->path); /* resync and try again */ if (dbox_sync(mbox, TRUE) < 0) return -1; synced = TRUE; } } static bool dbox_mail_try_open(struct index_mail *mail, uint32_t *file_seq_r, uoff_t *offset_r, int *ret_r) { struct dbox_mailbox *mbox = (struct dbox_mailbox *)mail->ibox; struct dbox_transaction_context *t = (struct dbox_transaction_context *)mail->trans; uint32_t seq = mail->mail.mail.seq; *ret_r = dbox_mail_lookup_offset(mail->trans, seq, file_seq_r, offset_r); if (*ret_r <= 0) { if (*ret_r == 0) mail_set_expunged(&mail->mail.mail); return TRUE; } if ((*ret_r = dbox_file_seek(mbox, *file_seq_r, *offset_r, seq >= t->first_saved_mail_seq)) < 0) return TRUE; if (*ret_r > 0) { /* ok */ *ret_r = dbox_mail_parse_mail_header(mail, mbox->file); return TRUE; } return FALSE; } static int dbox_mail_open(struct index_mail *mail, uoff_t *offset_r) { struct dbox_mailbox *mbox = (struct dbox_mailbox *)mail->ibox; uint32_t file_seq, prev_file_seq = 0; uoff_t prev_offset = 0; int i, ret; if (mail->mail.mail.expunged || mbox->syncing) return 0; for (i = 0; i < 3; i++) { if (dbox_mail_try_open(mail, &file_seq, offset_r, &ret)) return ret; if (prev_file_seq == file_seq && prev_offset == *offset_r) { /* broken offset */ break; } else { /* mail was moved. resync dbox to find out the new offset and try again. */ if (dbox_sync(mbox, FALSE) < 0) return -1; } prev_file_seq = file_seq; prev_offset = *offset_r; } mail_storage_set_critical(&mbox->storage->storage, "Cached message offset (%u, %"PRIuUOFF_T") " "broken for uid %u in dbox %s", file_seq, *offset_r, mail->mail.mail.uid, mbox->path); if (dbox_sync(mbox, TRUE) < 0) return -1; if (dbox_mail_try_open(mail, &file_seq, offset_r, &ret)) return ret; return -1; } static int dbox_mail_get_received_date(struct mail *_mail, time_t *date_r) { struct index_mail *mail = (struct index_mail *)_mail; struct index_mail_data *data = &mail->data; uoff_t offset; uint32_t t; (void)index_mail_get_received_date(_mail, date_r); if (*date_r != (time_t)-1) return 0; if (dbox_mail_open(mail, &offset) <= 0) return (time_t)-1; if (data->received_date == (time_t)-1) { /* it's broken and conflicts with our "not found" return value. change it. */ data->received_date = 0; } t = data->received_date; index_mail_cache_add(mail, MAIL_CACHE_RECEIVED_DATE, &t, sizeof(t)); *date_r = data->received_date; return 0; } static int dbox_mail_get_save_date(struct mail *_mail, time_t *date_r) { struct index_mail *mail = (struct index_mail *)_mail; struct index_mail_data *data = &mail->data; uoff_t offset; (void)index_mail_get_save_date(_mail, date_r); if (*date_r != (time_t)-1) return 0; if (dbox_mail_open(mail, &offset) <= 0) return -1; if (data->save_date == (time_t)-1) { /* it's broken and conflicts with our "not found" return value. change it. */ data->save_date = ioloop_time; } index_mail_cache_add(mail, MAIL_CACHE_SAVE_DATE, &data->save_date, sizeof(data->save_date)); *date_r = data->save_date; 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; uoff_t offset; (void)index_mail_get_physical_size(_mail, size_r); if (*size_r != (uoff_t)-1) return 0; if (dbox_mail_open(mail, &offset) <= 0) return -1; index_mail_cache_add(mail, MAIL_CACHE_PHYSICAL_FULL_SIZE, &data->physical_size, sizeof(data->physical_size)); *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 index_mail *mail = (struct index_mail *)_mail; struct dbox_mailbox *mbox = (struct dbox_mailbox *)mail->ibox; uoff_t offset; if (mail->data.stream == NULL) { if (dbox_mail_open(mail, &offset) <= 0) return -1; offset += mbox->file->mail_header_size; mail->data.stream = i_stream_create_limit(mbox->file->input, offset, mbox->file->seeked_mail_size); } return index_mail_init_stream(mail, hdr_size, body_size, stream_r); } struct mail_vfuncs dbox_mail_vfuncs = { index_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_physical_size, /* physical = virtual in our case */ 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 };