mail-transaction-log-view.c revision b5ac20e30146562322ceb7939f044d52d1e51184
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
3448096d5b1cd324ed5132045de0345cd7120a25Timo Sirainen /* a list of log files we've referenced. we have to keep this list
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen explicitly because more files may be added into the linked list
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen at any time. */
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen ARRAY_DEFINE(file_refs, struct mail_transaction_log_file *);
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody struct mail_transaction_log_file *cur, *head, *tail;
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmodymail_transaction_log_view_open(struct mail_transaction_log *log)
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen view = i_new(struct mail_transaction_log_view, 1);
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen array_append(&view->file_refs, &view->head, 1);
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenmail_transaction_log_view_unref_all(struct mail_transaction_log_view *view)
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila struct mail_transaction_log_file *const *files;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen unsigned int i, count;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen for (i = 0; i < count; i++)
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainenvoid mail_transaction_log_view_close(struct mail_transaction_log_view **_view)
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen struct mail_transaction_log_view *view = *_view;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen for (p = &view->log->views; *p != NULL; p = &(*p)->next) {
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainenvoid mail_transaction_log_views_close(struct mail_transaction_log *log)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen for (view = log->views; view != NULL; view = view->next)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainenmail_transaction_log_view_set(struct mail_transaction_log_view *view,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen uint32_t min_file_seq, uoff_t min_file_offset,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen uint32_t max_file_seq, uoff_t max_file_offset,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen struct mail_transaction_log_file *file, *first;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen /* transaction log is closed already. this log view shouldn't
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen be used anymore. */
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen /* index file doesn't exist yet. this transaction log should
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen start from the beginning */
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (view->log->files->hdr.prev_file_seq != 0) {
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen /* but it doesn't */
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen min_file_seq = view->log->files->hdr.file_seq;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (min_file_seq == view->log->files->hdr.prev_file_seq &&
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen min_file_offset == view->log->files->hdr.prev_file_offset) {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen /* we can skip this */
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen min_file_seq = view->log->files->hdr.file_seq;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen /* empty view */
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen /* find the oldest log file first. */
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody ret = mail_transaction_log_find_file(view->log, min_file_seq, &file);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen /* this could happen if internal transactions haven't yet been
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen committed but external are. just assume we're at the
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen beginning. */
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila if (max_file_offset == 0 && min_file_seq == max_file_seq)
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen i_assert(min_file_offset >= file->hdr.hdr_size);
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen if (min_file_seq == max_file_seq && min_file_offset > max_file_offset) {
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen /* log file offset is probably corrupted in the index file. */
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen min_file_seq, min_file_offset, max_file_offset);
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen ret = mail_transaction_log_file_map(file, min_file_offset, end_offset);
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen for (seq = min_file_seq+1; seq <= max_file_seq; seq++) {
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila if (file == NULL || file->hdr.file_seq != seq) {
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila /* see if we could find the missing file */
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen ret = mail_transaction_log_find_file(view->log,
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen /* not found / corrupted */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (file == NULL || file->hdr.file_seq != seq) {
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (file == NULL && max_file_seq == (uint32_t)-1) {
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen /* we just wanted to sync everything */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen /* missing files in the middle */
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila end_offset = file->hdr.file_seq == max_file_seq ?
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody ret = mail_transaction_log_file_map(file, file->hdr.hdr_size,
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila /* we have all of them. update refcounts. */
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen /* reference all used files */
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen for (file = view->tail; file != NULL; file = file->next) {
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen i_assert(view->cur_offset <= view->cur->sync_offset);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen i_assert(view->cur->hdr.file_seq == min_file_seq);
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenmail_transaction_log_view_get_prev_pos(struct mail_transaction_log_view *view,
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovilamail_transaction_log_view_get_last(struct mail_transaction_log_view *view,
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila struct mail_transaction_log_file *cur = view->cur;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila if (cur->hdr.file_seq == view->max_file_seq) {
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila /* last file */
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody /* we're all finished */
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila /* end of file, go to next one */
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila /* not EOF */
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovilabool mail_transaction_log_view_is_last(struct mail_transaction_log_view *view)
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila return mail_transaction_log_view_get_last(view, &cur, &cur_offset);
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovilamail_transaction_log_view_set_corrupted(struct mail_transaction_log_view *view,
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila const char *fmt, ...)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen mail_transaction_log_file_set_corrupted(view->log->head, "%s",
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenmail_transaction_log_view_is_corrupted(struct mail_transaction_log_view *view)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainenlog_view_is_record_valid(struct mail_transaction_log_file *file,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen const struct mail_transaction_type_map *type_rec)
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila rec_type = hdr->type & MAIL_TRANSACTION_TYPE_MASK;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen rec_size = mail_index_offset_to_uint32(hdr->size) - sizeof(*hdr);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen /* we want to be extra careful with expunges */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila "expunge record missing protection mask");
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila /* records that are exported by syncing and view syncing will be
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila checked here so that we don't have to implement the same validation
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen multiple times. other records are checked internally by
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen mail_index_sync_record(). */
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen uid_buf = buffer_create_const_data(pool_datastack_create(),
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen uid_buf = buffer_create_const_data(pool_datastack_create(),
c4b772bfbdafe68ac1a0076eab26cd681f8e5046Timo Sirainen const struct mail_transaction_keyword_update *rec = data;
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen seqset_offset = sizeof(*rec) + rec->name_size;
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen ((rec_size - seqset_offset) % (sizeof(uint32_t)*2)) != 0) {
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen "Invalid keyword update record size");
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen uid_buf = buffer_create_const_data(pool_datastack_create(),
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen array_create_from_buffer(&uids, uid_buf, sizeof(uint32_t)*2);
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen uid_buf = buffer_create_const_data(pool_datastack_create(),
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen sizeof(struct mail_transaction_keyword_reset));
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (rec->seq1 > rec->seq2 || rec->seq1 == 0) {
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila "Invalid UID range "
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen "(%u .. %u, type=0x%x)",
b1965419f329eb7cf78ee39e7c5942462eabb256Timo Sirainen if (prev != NULL && rec->seq1 <= prev->seq2) {
b1965419f329eb7cf78ee39e7c5942462eabb256Timo Sirainen "Non-sorted UID ranges (type=0x%x)",
t_pop();
return ret;
const void **data_r)
const void *data;
unsigned int record_size;
record_size = 0;
if (record_size != 0 &&
const void *data;
int ret = 0;
if (ret < 0) {
if (ret == 0)