void mail_cache_lookup_iter_init(struct mail_cache_view *view, uint32_t seq, struct mail_cache_lookup_iterate_ctx *ctx_r) { struct mail_cache_lookup_iterate_ctx *ctx = ctx_r; int ret; if (!view->cache->opened) (void)mail_cache_open_and_verify(view->cache); memset(ctx, 0, sizeof(*ctx)); ctx->view = view; ctx->seq = seq; if (!MAIL_CACHE_IS_UNUSABLE(view->cache)) { /* look up the first offset */ ret = mail_cache_lookup_offset(view->cache, view->view, seq, &ctx->offset); if (ret <= 0) { ctx->stop = TRUE; ctx->failed = ret < 0; } } ctx->remap_counter = view->cache->remap_counter; memset(&view->loop_track, 0, sizeof(view->loop_track)); }
static int mail_cache_lookup_iter_next_record(struct mail_cache_lookup_iterate_ctx *ctx) { struct mail_cache_view *view = ctx->view; if (ctx->failed) return -1; if (ctx->rec != NULL) ctx->offset = ctx->rec->prev_offset; if (ctx->offset == 0) { /* end of this record list. check newly appended data. */ if (view->trans_seq1 > ctx->seq || view->trans_seq2 < ctx->seq) return 0; /* check data still in memory. this works for recent mails even with INDEX=MEMORY */ if (!ctx->memory_appends_checked) { if (mail_cache_lookup_iter_transaction(ctx)) return 1; ctx->memory_appends_checked = TRUE; } if (MAIL_CACHE_IS_UNUSABLE(view->cache)) return 0; /* check data already written to cache file */ if (ctx->disk_appends_checked || mail_cache_lookup_offset(view->cache, view->trans_view, ctx->seq, &ctx->offset) <= 0) return 0; ctx->disk_appends_checked = TRUE; ctx->remap_counter = view->cache->remap_counter; memset(&view->loop_track, 0, sizeof(view->loop_track)); } if (ctx->stop) return 0; /* look up the next record */ if (mail_cache_get_record(view->cache, ctx->offset, &ctx->rec) < 0) return -1; if (mail_cache_track_loops(&view->loop_track, ctx->offset, ctx->rec->size)) { mail_cache_set_corrupted(view->cache, "record list is circular"); return -1; } ctx->remap_counter = view->cache->remap_counter; ctx->pos = sizeof(*ctx->rec); ctx->rec_size = ctx->rec->size; return 1; }