mail-cache.c revision 25c22e54d1071d120641e9eecd0023e7373e65ff
/* Copyright (c) 2003-2008 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "buffer.h"
#include "hash.h"
#include "nfs-workarounds.h"
#include "file-cache.h"
#include "mmap-util.h"
#include "write-full.h"
#include "mail-cache-private.h"
#include <unistd.h>
const char *function)
{
return;
}
"%s failed with index cache file %s: %m",
}
{
/* mark the cache as unusable */
T_BEGIN {
"Corrupted index cache file %s: %s",
} T_END;
}
{
}
cache->mmap_length = 0;
}
}
{
return;
}
{
if (MAIL_CACHE_IS_UNUSABLE(cache)) {
if (cache->need_compress_file_seq != 0) {
/* we're waiting for compression */
return FALSE;
}
/* disabled */
return FALSE;
}
}
return TRUE;
/* see if the file has changed */
}
return TRUE;
}
/* file changed */
return TRUE;
}
/* if the old file has been deleted, the new file may have
the same inode as the old one. we'll catch this here by
checking if fstat() fails with ESTALE */
return TRUE;
return FALSE;
}
}
return FALSE;
}
{
struct mail_index_view *view;
const struct mail_index_ext *ext;
if (!mail_cache_need_reopen(cache)) {
/* reopening does no good */
return 0;
}
cache->need_compress_file_seq = 0;
else
return -1;
}
if (mail_cache_map(cache, 0, 0) < 0)
return -1;
if (mail_cache_header_fields_read(cache) < 0)
return -1;
/* still different - maybe a race condition or maybe the
file_seq really is corrupted. either way, this shouldn't
happen often so we'll just mark cache to be compressed
later which fixes this. */
return 0;
}
return 1;
}
{
unsigned int cont_percentage;
/* too many continued rows, compress */
}
/* see if we've reached the max. deleted space in file */
}
{
/* check that the header is still ok */
return FALSE;
}
/* version changed - upgrade silently */
return FALSE;
}
/* architecture change - handle silently(?) */
return FALSE;
}
/* index id changed - handle silently */
return FALSE;
}
return FALSE;
}
/* only check the header if we're locked */
return TRUE;
return FALSE;
}
return FALSE;
}
return FALSE;
}
return TRUE;
}
{
cache->remap_counter++;
if (size == 0)
size = sizeof(struct mail_cache_header);
if (ret < 0) {
/* In case of ESTALE we'll simply fail without error
messages. The caller will then just have to
fallback to generating the value itself.
We can't simply reopen the cache flie, because
using it requires also having updated file
offsets. */
return -1;
}
&cache->mmap_length);
if (offset == 0) {
if (!mail_cache_verify_header(cache)) {
return -1;
}
sizeof(cache->hdr_ro_copy));
}
if (offset == 0)
return 0;
}
/* already mapped */
return 0;
}
} else {
/* unusable, waiting for compression or
index is in memory */
return -1;
}
}
/* map the whole file */
cache->mmap_length = 0;
return -1;
}
if (!mail_cache_verify_header(cache)) {
return -1;
}
if (offset == 0)
return 0;
}
{
return 0;
cache->need_compress_file_seq = 0;
return 0;
}
return -1;
}
return -1;
return 1;
}
{
int ret;
if (ret > 0)
if (ret < 0) {
/* failed for some reason - doesn't really matter,
it's disabled for now. */
}
return ret;
}
{
struct mail_cache *cache;
if (!MAIL_INDEX_IS_IN_MEMORY(index)) {
if (index->mmap_disable)
}
}
return cache;
}
{
struct mail_cache *cache;
return cache;
}
{
struct mail_cache *cache;
if (!MAIL_INDEX_IS_IN_MEMORY(index)) {
}
return cache;
}
{
}
}
{
int ret;
if (cache->last_lock_failed) {
/* previous locking failed. don't waste time waiting on it
again, just try once to see if it's available now. */
}
nonblock ? 0 : MAIL_CACHE_LOCK_TIMEOUT,
} else {
enum dotlock_create_flags flags =
if (ret < 0) {
"file_dotlock_create()");
}
}
/* don't bother warning if locking failed due to a timeout. since cache
updating isn't all that important we're using a very short timeout
so it can be triggered sometimes on heavy load */
if (ret <= 0)
return ret;
TRUE);
return 1;
}
{
else
}
static int
bool nonblock)
{
const struct mail_index_ext *ext;
struct mail_index_view *iview;
int i, ret;
(void)mail_cache_open_and_verify(cache);
if (MAIL_CACHE_IS_UNUSABLE(cache) ||
return 0;
/* cache not used */
return 0;
}
for (i = 0; i < 3; i++) {
(require_same_reset_id || i == 0)) {
/* we want the latest cache file */
/* either we're still waiting for index to
catch up with a cache compression, or
that catching up is never going to happen */
ret = 0;
break;
}
break;
}
ret = -1;
break;
}
/* got it */
break;
}
/* okay, so it was just compressed. try again. */
(void)mail_cache_unlock(cache);
ret = 0;
}
if (ret > 0) {
/* make sure our header is up to date */
sizeof(struct mail_cache_header));
}
if (mail_cache_map(cache, 0, 0) == 0)
else {
(void)mail_cache_unlock(cache);
ret = -1;
}
}
return ret;
}
{
}
{
}
{
int ret = 0;
if (MAIL_CACHE_IS_UNUSABLE(cache)) {
/* we found it to be broken during the lock. just clean up. */
return -1;
}
if (cache->hdr_modified) {
ret = -1;
}
}
return ret;
}
{
return -1;
}
/* data pointer may change if file cache was grown */
&cache->mmap_length);
}
return 0;
}
struct mail_cache_view *
{
struct mail_cache_view *view;
return view;
}
{
}
{
const struct mail_index_header *idx_hdr;
return 1;
&message_count)) {
/* all messages are too old */
return message_count+1;
}
return first_new_seq;
}