mail-transaction-log-view.c revision 1f2c3bde353d45f6d76c5210adf1e0a952247f3a
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose/* Copyright (C) 2003-2004 Timo Sirainen */
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose struct mail_transaction_expunge_iter_ctx *exp_ctx;
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bosemail_transaction_log_view_open(struct mail_transaction_log *log)
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose view = i_new(struct mail_transaction_log_view, 1);
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose buffer_create_dynamic(default_pool, 512, (size_t)-1);
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bosevoid mail_transaction_log_view_close(struct mail_transaction_log_view *view)
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose for (p = &view->log->views; *p != NULL; p = &(*p)->next) {
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose if (*p == view) {
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bosevoid mail_transaction_log_views_close(struct mail_transaction_log *log)
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose for (view = log->views; view != NULL; view = view->next)
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bosemail_transaction_log_view_set(struct mail_transaction_log_view *view,
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose /* FIXME: error handling for "not found" case is bad.. should the
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose caller after all check it and handle as it sees best..? */
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose ret = mail_transaction_log_file_find(view->log, min_file_seq, &file);
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose min_file_seq == view->log->tail->hdr.prev_file_seq &&
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose min_file_offset == view->log->tail->hdr.prev_file_offset) {
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose /* we can skip this */
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose "Lost transaction log file %s seq %u",
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose /* empty view */
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose /* check these later than others as index file may have corrupted
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose log_file_offset. we should have recreated the log file and
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose skipped min_file_seq file above.. max_file_offset can be broken
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose only if min_file_seq = max_file_seq. */
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose i_assert(min_file_offset >= sizeof(struct mail_transaction_log_header));
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose i_assert(max_file_offset >= sizeof(struct mail_transaction_log_header));
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose ret = mail_transaction_log_file_map(file, min_file_offset, end_offset);
cd5033e86bb4065d75188e2b6ef287a4421344c8Sumit Bose for (seq = min_file_seq+1; seq <= max_file_seq; seq++) {
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose end_offset = file->hdr.file_seq == max_file_seq ?
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose i_assert(max_file_offset <= file->hdr.used_size);
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose /* we have it all, refcount the files */
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose for (file = first, seq = min_file_seq; seq <= max_file_seq; seq++) {
04d138472cc086fb7961f0d378852b09961b1a33Lukas Slebodnikvoid mail_transaction_log_view_unset(struct mail_transaction_log_view *view)
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose for (file = view->log->tail; file != NULL; file = file->next) {
fb81f337b68c85471c3f5140850dccf549a2d0acFabiano Fidênciomail_transaction_log_view_get_prev_pos(struct mail_transaction_log_view *view,
fb81f337b68c85471c3f5140850dccf549a2d0acFabiano Fidênciomail_transaction_log_view_set_corrupted(struct mail_transaction_log_view *view,
fb81f337b68c85471c3f5140850dccf549a2d0acFabiano Fidêncio const char *fmt, ...)
fb81f337b68c85471c3f5140850dccf549a2d0acFabiano Fidêncio mail_transaction_log_file_set_corrupted(view->log->head, "%s",
fb81f337b68c85471c3f5140850dccf549a2d0acFabiano Fidênciomail_transaction_log_view_is_corrupted(struct mail_transaction_log_view *view)
fb81f337b68c85471c3f5140850dccf549a2d0acFabiano Fidênciostatic int log_view_get_next(struct mail_transaction_log_view *view,
fb81f337b68c85471c3f5140850dccf549a2d0acFabiano Fidêncio const struct mail_transaction_header **hdr_r,
fb81f337b68c85471c3f5140850dccf549a2d0acFabiano Fidêncio const struct mail_transaction_type_map *type_rec;
fb81f337b68c85471c3f5140850dccf549a2d0acFabiano Fidêncio view->prev_file_offset = view->file_offset;
fb81f337b68c85471c3f5140850dccf549a2d0acFabiano Fidêncio if (view->file_offset != file->hdr.used_size)
fb81f337b68c85471c3f5140850dccf549a2d0acFabiano Fidêncio view->file_offset = sizeof(struct mail_transaction_log_header);
fe2ab0d67fe8c66fb6352e9d8f845bb46d1848cbSumit Bose data = buffer_get_data(file->buffer, &file_size);
fe2ab0d67fe8c66fb6352e9d8f845bb46d1848cbSumit Bose if (view->file_offset + sizeof(*hdr) > file_size) {
fe2ab0d67fe8c66fb6352e9d8f845bb46d1848cbSumit Bose "offset points outside file "
fe2ab0d67fe8c66fb6352e9d8f845bb46d1848cbSumit Bose "(%"PRIuUOFF_T" + %"PRIuSIZE_T" > %"PRIuSIZE_T")",
fe2ab0d67fe8c66fb6352e9d8f845bb46d1848cbSumit Bose hdr = CONST_PTR_OFFSET(data, view->file_offset - file->buffer_offset);
fe2ab0d67fe8c66fb6352e9d8f845bb46d1848cbSumit Bose "record size too large (type=0x%x, offset=%"PRIuUOFF_T
fe2ab0d67fe8c66fb6352e9d8f845bb46d1848cbSumit Bose type_rec = mail_transaction_type_lookup(hdr->type);
fe2ab0d67fe8c66fb6352e9d8f845bb46d1848cbSumit Bose "unknown record type 0x%x",
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose (MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT)) {
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose "found expunge without protection mask");
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose } else if ((hdr->type & MAIL_TRANSACTION_TYPE_MASK) != type_rec->type) {
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose "extra bits in header type: 0x%x",
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose "record size wrong (type 0x%x, %u %% %u != 0)",
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose *data_r = CONST_PTR_OFFSET(data, view->file_offset -
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bosestatic int seqfix_expunge(const struct mail_transaction_expunge *e,
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose struct mail_transaction_log_view *view = context;
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose if (!mail_transaction_expunge_iter_seek(view->exp_ctx,
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose /*FIXME:buffer_append(view->data_buf, e, sizeof(*e));
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose new_e.uid1 = new_e.uid2 = 0; // FIXME: this breaks anyway
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose while (mail_transaction_expunge_iter_get(view->exp_ctx,
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose buffer_append(view->data_buf, &new_e, sizeof(new_e));
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bosestatic int seqfix_flag_update(const struct mail_transaction_flag_update *u,
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose struct mail_transaction_log_view *view = context;
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose if (!mail_transaction_expunge_iter_seek(view->exp_ctx,
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose while (mail_transaction_expunge_iter_get(view->exp_ctx,
04d138472cc086fb7961f0d378852b09961b1a33Lukas Slebodnik buffer_append(view->data_buf, &new_u, sizeof(new_u));
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bosestatic int seqfix_cache_update(const struct mail_transaction_cache_update *u,
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose struct mail_transaction_log_view *view = context;
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose if (!mail_transaction_expunge_iter_seek(view->exp_ctx,
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose if (mail_transaction_expunge_iter_get(view->exp_ctx,
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose buffer_append(view->data_buf, &new_u, sizeof(new_u));
04d138472cc086fb7961f0d378852b09961b1a33Lukas Slebodnikint mail_transaction_log_view_next(struct mail_transaction_log_view *view,
04d138472cc086fb7961f0d378852b09961b1a33Lukas Slebodnik const struct mail_transaction_header **hdr_r,
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose struct mail_transaction_map_functions seqfix_funcs = {
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose seqfix_expunge, NULL, seqfix_flag_update, seqfix_cache_update
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose const void *data;
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose while ((ret = log_view_get_next(view, &hdr, &data)) > 0) {
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose /* we don't want this record */
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose mail_transaction_log_sort_expunges(view->expunges_buf,
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose /* FIXME: hide flag/cache updates for appends if
2fe140d3a41e1ac66400069d35adc9379348c1e5Sumit Bose append isn't in mask */
ca49ae1eee321751681e99f3ebe2547211db3bf6Sumit Bose if (buffer_get_used_size(view->expunges_buf) > 0) {
9da27cbc7532f775afc411d809735760dd5294a7Sumit Bose /* we have to fix sequences in the data */
9da27cbc7532f775afc411d809735760dd5294a7Sumit Bose mail_transaction_expunge_iter_init(view->expunges_buf);
9da27cbc7532f775afc411d809735760dd5294a7Sumit Bose ret = mail_transaction_map(hdr, data, &seqfix_funcs, view);
9da27cbc7532f775afc411d809735760dd5294a7Sumit Bose mail_transaction_expunge_iter_deinit(view->exp_ctx);
9da27cbc7532f775afc411d809735760dd5294a7Sumit Bose /* modified - size may have changed, so update header */
ca49ae1eee321751681e99f3ebe2547211db3bf6Sumit Bose i_assert(buffer_get_used_size(view->data_buf) == 0);
ca49ae1eee321751681e99f3ebe2547211db3bf6Sumit Bose if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) {
ca49ae1eee321751681e99f3ebe2547211db3bf6Sumit Bose mail_transaction_log_sort_expunges(view->expunges_buf,
ca49ae1eee321751681e99f3ebe2547211db3bf6Sumit Bose /* hide expunge protection */
ca49ae1eee321751681e99f3ebe2547211db3bf6Sumit Bose view->tmp_hdr.type &= ~MAIL_TRANSACTION_EXPUNGE_PROT;