mail-cache.c revision 114a0f74e0f825c6bd8aeadfafb248a030762a1f
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes/* Copyright (C) 2003-2004 Timo Sirainen */
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholesvoid mail_cache_set_syscall_error(struct mail_cache *cache,
ac7985784d08a3655291f24f711812b4d8b1cbcffuankg const char *function)
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes "%s failed with index cache file %s: %m",
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholesvoid mail_cache_set_corrupted(struct mail_cache *cache, const char *fmt, ...)
16b55a35cff91315d261d1baa776138af465c4e4fuankg mail_index_set_error(cache->index, "Corrupted index cache file %s: %s",
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes if (munmap(cache->mmap_base, cache->mmap_length) < 0)
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes if (MAIL_CACHE_IS_UNUSABLE(cache) && cache->need_compress) {
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes /* unusable, we're just waiting for compression */
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes ext = mail_index_view_get_ext(view, cache->ext_id);
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes if (ext == NULL || cache->hdr->file_seq != ext->reset_id) {
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes /* still different - maybe a race condition or maybe the
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes file_seq really is corrupted. either way, this shouldn't
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes happen often so we'll just mark cache to be compressed
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes later which fixes this. */
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholesstatic int mail_cache_verify_header(struct mail_cache *cache)
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes const struct mail_cache_header *hdr = cache->data;
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes /* check that the header is still ok */
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes if (cache->mmap_length < sizeof(struct mail_cache_header)) {
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes mail_cache_set_corrupted(cache, "File too small");
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes /* version changed - upgrade silently */
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes if (cache->hdr->indexid != cache->index->indexid) {
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes /* index id changed */
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes mail_cache_set_corrupted(cache, "indexid changed");
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes /* only check the header if we're locked */
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes if (hdr->used_file_size < sizeof(struct mail_cache_header)) {
ac7985784d08a3655291f24f711812b4d8b1cbcffuankg mail_cache_set_corrupted(cache, "used_file_size too small");
16b55a35cff91315d261d1baa776138af465c4e4fuankg mail_cache_set_corrupted(cache, "used_file_size not aligned");
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes mail_cache_set_corrupted(cache, "used_file_size too large");
ac7985784d08a3655291f24f711812b4d8b1cbcffuankgint mail_cache_map(struct mail_cache *cache, size_t offset, size_t size)
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes ret = file_cache_read(cache->file_cache, offset, size);
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes // FIXME: ESTALE
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes cache->data = file_cache_get_map(cache->file_cache,
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes if (offset == 0 && !mail_cache_verify_header(cache)) {
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes /* already mapped */
ac7985784d08a3655291f24f711812b4d8b1cbcffuankg if (munmap(cache->mmap_base, cache->mmap_length) < 0)
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes /* unusable, waiting for compression */
0b2a6b63977ab27352a0b525bdad1e1982a1c0b1bnicholes /* map the whole file */
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes cache->mmap_base = mmap_ro_file(cache->fd, &cache->mmap_length);
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholesstatic int mail_cache_open_and_verify(struct mail_cache *cache)
16b55a35cff91315d261d1baa776138af465c4e4fuankg cache->filepath = i_strconcat(cache->index->filepath,
16b55a35cff91315d261d1baa776138af465c4e4fuankg if (cache->index->mmap_disable || cache->index->mmap_no_write)
16b55a35cff91315d261d1baa776138af465c4e4fuankg if (mail_cache_map(cache, 0, sizeof(struct mail_cache_header)) < 0)
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholesstruct mail_cache *mail_cache_open_or_create(struct mail_index *index)
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes cache->field_pool = pool_alloconly_create("Cache fields", 1024);
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes /* failed for some reason - doesn't really matter,
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes it's disabled for now. */
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes mail_index_register_expunge_handler(index, cache->ext_id,
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes mail_index_register_sync_handler(index, cache->ext_id,
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes if (mail_index_view_open_locked(cache->index, &view) < 0)
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes /* cache not used */
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes /* we want the latest cache file */
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes for (i = 0; i < 3; i++) {
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes ret = mail_index_lock_fd(cache->index, cache->fd, F_WRLCK,
e76fdcdfb8994ad70776526f50fa013b3e9a6033bnicholes if (ret <= 0) {
ret = 0;
if (ret > 0) {
sizeof(struct mail_cache_header));
return ret;
unsigned int cont_percentage;
struct mail_cache_view *
return view;