mail-transaction-log-view.c revision 44ff75ca53188056ff5a3e50428e3f2078800b3c
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen struct mail_transaction_log_file *cur, *head, *tail;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_transaction_log_view_open(struct mail_transaction_log *log)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view = i_new(struct mail_transaction_log_view, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_transaction_log_view_close(struct mail_transaction_log_view *view)
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen for (p = &view->log->views; *p != NULL; p = &(*p)->next) {
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen for (file = view->tail; file != view->head; file = file->next)
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainenvoid mail_transaction_log_views_close(struct mail_transaction_log *log)
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen for (view = log->views; view != NULL; view = view->next)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_transaction_log_view_set(struct mail_transaction_log_view *view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t min_file_seq, uoff_t min_file_offset,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t max_file_seq, uoff_t max_file_offset,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* FIXME: error handling for "not found" case is bad.. should the
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen caller after all check it and handle as it sees best..? */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_transaction_log_file *file, *first;
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen if (min_file_seq == view->log->tail->hdr.prev_file_seq &&
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen min_file_offset == view->log->tail->hdr.prev_file_offset) {
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen /* we can skip this */
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen min_file_offset = sizeof(struct mail_transaction_log_header);
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen /* empty view */
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen ret = mail_transaction_log_file_find(view->log, min_file_seq, &file);
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen "Lost transaction log file %s seq %u",
ed1f14af0d426b5550521a58fc414d130aa14172Timo Sirainen /* check these later than others as index file may have corrupted
ed1f14af0d426b5550521a58fc414d130aa14172Timo Sirainen log_file_offset. we should have recreated the log file and
ed1f14af0d426b5550521a58fc414d130aa14172Timo Sirainen skipped min_file_seq file above.. max_file_offset can be broken
ed1f14af0d426b5550521a58fc414d130aa14172Timo Sirainen only if min_file_seq = max_file_seq. */
ed1f14af0d426b5550521a58fc414d130aa14172Timo Sirainen i_assert(min_file_offset >= sizeof(struct mail_transaction_log_header));
ed1f14af0d426b5550521a58fc414d130aa14172Timo Sirainen i_assert(max_file_offset >= sizeof(struct mail_transaction_log_header));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = mail_transaction_log_file_map(file, min_file_offset, end_offset);
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen "Lost transaction log file %s seq %u",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (seq = min_file_seq+1; seq <= max_file_seq; seq++) {
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen if (file == NULL || file->hdr.file_seq != seq) {
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen "Lost transaction log file %s seq %u",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen end_offset = file->hdr.file_seq == max_file_seq ?
1b56f5fdd415270c743a38719d41b4d9497bcacdTimo Sirainen "Lost transaction log file %s seq %u",
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen i_assert(max_file_offset <= file->sync_offset);
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen /* we have all of them. update refcounts. */
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen if (view->tail->hdr.file_seq < first->hdr.file_seq) {
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen /* unref old files */
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen for (file = view->tail; file != first; file = file->next)
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen /* going backwards, reference them */
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen for (file = first; file != view->tail; file = file->next)
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen /* reference all new files */
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen for (file = view->head->next; file != NULL; file = file->next)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_transaction_log_view_get_prev_pos(struct mail_transaction_log_view *view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_transaction_log_view_set_corrupted(struct mail_transaction_log_view *view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *fmt, ...)
c1d45cada20777e1973579d40d0ebe43f89bb053Timo Sirainen mail_transaction_log_file_set_corrupted(view->log->head, "%s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_transaction_log_view_is_corrupted(struct mail_transaction_log_view *view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int log_view_get_next(struct mail_transaction_log_view *view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const void **data_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_type_map *type_rec;
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen view->cur_offset = sizeof(struct mail_transaction_log_header);
b7cf555b699d73f2d71de0dabc088af6a7be3627Timo Sirainen if (view->cur_offset >= view->max_file_offset &&
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen data = buffer_get_data(file->buffer, &file_size);
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen if (view->cur_offset + sizeof(*hdr) > file_size) {
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen "offset points outside file "
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen "(%"PRIuUOFF_T" + %"PRIuSIZE_T" > %"PRIuSIZE_T")",
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen hdr = CONST_PTR_OFFSET(data, view->cur_offset - file->buffer_offset);
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen hdr_size = mail_index_offset_to_uint32(hdr->size);
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen if (file_size - view->cur_offset < hdr_size) {
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen "record size too large (type=0x%x, offset=%"PRIuUOFF_T
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen "record size too small (type=0x%x, size=%u)",
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen hdr->type & MAIL_TRANSACTION_TYPE_MASK, hdr_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen type_rec = mail_transaction_type_lookup(hdr->type);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "unknown record type 0x%x",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) !=
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "found expunge without protection mask");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) != type_rec->type) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "extra bits in header type: 0x%x",
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen } else if (hdr->type == MAIL_TRANSACTION_EXTRA_REC_UPDATE) {
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen const struct mail_transaction_extra_rec_header *ehdr = data;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen if (ehdr->idx >= view->log->index->extra_records_count) {
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen "extra record update out of range (%u > %u)",
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen if ((hdr_size - sizeof(*hdr)) % record_size != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "record size wrong (type 0x%x, %u %% %u != 0)",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_transaction_log_view_next(struct mail_transaction_log_view *view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while ((ret = log_view_get_next(view, &hdr, &data)) > 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we don't want this record */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* FIXME: hide flag/cache updates for appends if
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen append isn't in mask */
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen mail_index_offset_to_uint32(view->tmp_hdr.size) - sizeof(*hdr);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* hide expunge protection */