mail-cache.c revision e015e2f7e7f48874495f9df8b0dd192b7ffcb5cc
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenuint32_t mail_cache_uint32_to_offset(uint32_t offset)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen buf[0] = 0x80 | ((offset & 0x0fe00000) >> 21);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen buf[1] = 0x80 | ((offset & 0x001fc000) >> 14);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenuint32_t mail_cache_offset_to_uint32(uint32_t offset)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const unsigned char *buf = (const unsigned char *) &offset;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenvoid mail_cache_set_syscall_error(struct mail_cache *cache,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen "%s failed with index cache file %s: %m",
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainenvoid mail_cache_set_corrupted(struct mail_cache *cache, const char *fmt, ...)
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen mail_index_set_error(cache->index, "Corrupted index cache file %s: %s",
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainenvoid mail_cache_file_close(struct mail_cache *cache)
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen if (munmap(cache->mmap_base, cache->mmap_length) < 0)
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen mail_cache_set_syscall_error(cache, "munmap()");
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen mail_cache_set_syscall_error(cache, "close()");
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainenint mail_cache_reopen(struct mail_cache *cache)
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen if (MAIL_CACHE_IS_UNUSABLE(cache) && cache->need_compress) {
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen /* unusable, we're just waiting for compression */
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen mail_cache_set_syscall_error(cache, "open()");
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (cache->hdr->file_seq != cache->index->hdr->cache_file_seq) {
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen /* still different - maybe a race condition or maybe the
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen file_seq really is corrupted. either way, this shouldn't
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen happen often so we'll just mark cache to be compressed
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen later which fixes this. */
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainenstatic int mmap_verify_header(struct mail_cache *cache)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen /* check that the header is still ok */
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (cache->mmap_length < sizeof(struct mail_cache_header)) {
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen mail_cache_set_corrupted(cache, "File too small");
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (cache->hdr->version != MAIL_CACHE_VERSION) {
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen /* version changed - upgrade silently */
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (cache->hdr->indexid != cache->index->indexid) {
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen /* index id changed */
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen mail_cache_set_corrupted(cache, "indexid changed");
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen /* only check the header if we're locked */
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (hdr->used_file_size < sizeof(struct mail_cache_header)) {
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen mail_cache_set_corrupted(cache, "used_file_size too small");
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen if ((hdr->used_file_size % sizeof(uint32_t)) != 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen mail_cache_set_corrupted(cache, "used_file_size not aligned");
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen if (hdr->used_file_size > cache->mmap_length) {
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen mail_cache_set_corrupted(cache, "used_file_size too large");
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainenint mail_cache_map(struct mail_cache *cache, size_t offset, size_t size)
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen /* already mapped */
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen if (munmap(cache->mmap_base, cache->mmap_length) < 0)
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen mail_cache_set_syscall_error(cache, "munmap()");
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen /* unusable, waiting for compression */
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen /* map the whole file */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen cache->mmap_base = mmap_ro_file(cache->fd, &cache->mmap_length);
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen mail_cache_set_syscall_error(cache, "mmap()");
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainenstatic int mail_cache_open_and_verify(struct mail_cache *cache)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen cache->filepath = i_strconcat(cache->index->filepath,
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen mail_cache_set_syscall_error(cache, "open()");
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen if (mail_cache_map(cache, 0, sizeof(struct mail_cache_header)) < 0)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainenstruct mail_cache *mail_cache_open_or_create(struct mail_index *index)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen cache->field_pool = pool_alloconly_create("Cache fields", 512);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen hash_create(default_pool, cache->field_pool, 0,
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen strcase_hash, (hash_cmp_callback_t *)strcasecmp);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen if (!index->mmap_disable && !index->mmap_no_write) {
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen /* failed for some reason - doesn't really matter,
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen it's disabled for now. */
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen if (cache->hdr->file_seq != cache->index->hdr->cache_file_seq) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* we want the latest cache file */
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen for (i = 0; i < 3; i++) {
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen if ((ret = file_wait_lock(cache->fd, F_WRLCK)) <= 0) {
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen mail_cache_set_syscall_error(cache, "file_wait_lock()");
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen if (cache->hdr->file_seq == cache->index->hdr->cache_file_seq) {
87842f621233257b7a7945d994ba931508b34877Timo Sirainen /* okay, so it was just compressed. try again. */
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainenstatic void mail_cache_update_need_compress(struct mail_cache *cache)
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen const struct mail_cache_header *hdr = cache->hdr;
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen cont_percentage = hdr->continued_record_count * 100 /
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen if (cont_percentage >= COMPRESS_CONTINUED_PERCENTAGE &&
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen /* too many continued rows, compress */
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen /* see if we've reached the max. deleted space in file */
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen max_del_space = hdr->used_file_size / 100 * COMPRESS_PERCENTAGE;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainenvoid mail_cache_unlock(struct mail_cache *cache)
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen mail_cache_set_syscall_error(cache, "pwrite_full()");
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen mail_cache_set_syscall_error(cache, "file_wait_lock(F_UNLCK)");
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainenmail_cache_view_open(struct mail_cache *cache, struct mail_index_view *iview)