mail-cache.c revision 0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834
/* Copyright (C) 2003-2004 Timo Sirainen */
#include "lib.h"
#include "buffer.h"
#include "byteorder.h"
#include "file-lock.h"
#include "mmap-util.h"
#include "write-full.h"
#include "mail-cache-private.h"
#include <stddef.h>
#include <unistd.h>
unsigned int mail_cache_field_sizes[32] = {
sizeof(enum mail_index_record_flag),
sizeof(uoff_t),
16,
sizeof(struct mail_sent_date),
sizeof(time_t),
sizeof(uoff_t),
sizeof(uoff_t),
0, 0, 0, 0, 0,
/* variable sized */
(unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1,
(unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1,
(unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1,
(unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1,
(unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1
};
};
#if 0
{
unsigned char buf[4];
offset >>= 2;
}
{
return 0;
}
const char *function)
{
return;
}
"%s failed with index cache file %s: %m",
}
{
(void)mail_cache_reset(cache);
return;
t_push();
t_pop();
}
{
}
cache->mmap_length = 0;
}
}
{
int fd;
if (fd == -1) {
return -1;
}
return 0;
}
{
struct mail_cache_header *hdr;
/* check that the header is still ok */
return 0;
}
/* index id changed */
return 0;
}
/* we've updated used_file_size, do nothing */
return 1;
}
/* only check the header if we're locked */
return 1;
return 0;
}
return 0;
}
/* maybe a crash truncated the file - just fix it */
return -1;
}
}
return 1;
}
{
/* if sequence has changed, the file has to be reopened.
note that if main index isn't locked, it may change again */
if (!mail_cache_file_reopen(cache))
return -1;
}
!cache->mmap_refresh) {
/* already mapped */
if (size != 0)
return 1;
/* requesting the whole file - see if we need to
re-mmap */
return -1;
}
return 1;
}
/* in the middle of transaction - write the changes */
MS_SYNC) < 0) {
return -1;
}
}
}
/* map the whole file */
cache->mmap_length = 0;
return -1;
}
/* re-mmaped, check header */
return 0;
}
{
if (ret > 0)
return TRUE;
if (ret < 0)
return FALSE;
if (!mmap_verify_header(cache))
return FALSE;
/* see if cache file was rebuilt - do it only once to avoid
infinite looping */
break;
if (!mail_cache_file_reopen(cache))
return FALSE;
}
return TRUE;
}
{
return 0;
return -1;
}
return -1;
}
return 0;
return -1;
/* verify that this really is the cache for wanted index */
if (!mmap_verify_header(cache)) {
return 0;
}
return 1;
}
struct mail_cache_header *hdr)
{
if (ret != 0)
return ret > 0;
/* we'll have to clear cache_offsets which requires exclusive lock */
return FALSE;
/* maybe a rebuild.. */
if (fd == -1) {
return FALSE;
}
/* see if someone else just created the cache file */
if (ret != 0) {
return ret > 0;
}
/* rebuild then */
return FALSE;
}
return FALSE;
}
// FIXME: recreate index file with cache_offsets cleared
}
return FALSE;
}
return FALSE;
return TRUE;
}
{
struct mail_cache_header hdr;
struct mail_cache *cache;
/* we'll do anon-mmaping only if initially requested. if we fail
because of out of disk space, we'll just let the main index code
know it and fail. */
return FALSE;
}
return TRUE;
}
{
}
{
}
{
struct mail_cache_header hdr;
if (fd == -1) {
return -1;
}
return -1;
}
return -1;
}
return -1;
}
return -1;
return 0;
}
{
int ret;
return TRUE;
if (nonblock) {
if (ret < 0)
} else {
if (ret <= 0)
}
if (ret > 0) {
if (!mmap_update(cache, 0, 0)) {
(void)mail_cache_unlock(cache);
return -1;
}
/* we have the cache file locked and sync_id still
doesn't match. it means we crashed between updating
cache file and updating sync_id in index header.
just update the sync_ids so they match. */
i_warning("Updating broken sync_id in cache file %s",
}
}
return ret;
}
{
return TRUE;
return FALSE;
}
return TRUE;
}
{
}
struct mail_cache_view *
{
struct mail_cache_view *view;
return view;
}
{
}
#else
{
return 0;
}
{
}
enum mail_cache_field never_cache_fields) {}
/* Compress cache file. */
/* Reset the cache file, clearing all data. */
/* Explicitly lock the cache file. Returns 1 if ok, 0 if nonblock is TRUE and
we couldn't immediately get a lock, or -1 if error. */
/* Returns TRUE if cache file is locked. */
struct mail_cache_view *
/* Begin transaction. Cache transaction may be committed or rollbacked multiple
times. It will finish when index transaction is committed or rollbacked.
The transaction might also be partially committed automatically, so this
is kind of fake transaction, it's only purpose being optimizing writes.
Returns same as mail_cache_lock(). */
struct mail_index_transaction *t,
struct mail_cache_transaction_ctx **ctx_r)
{
return 1;
}
{return 0;}
/* Should be called only by mail_transaction_commit/rollback: */
{return 0;}
/* Return NULL-terminated list of headers for given index, or NULL if
header index isn't used. */
unsigned int idx)
{return NULL;}
/* Set list of headers for given index. */
{return 0;}
/* Add new field to given record. Updates are not allowed. Fixed size fields
must be exactly the expected size and they're converted to network byte
order in disk. */
enum mail_cache_field field,
{return 0;}
/* Mark the given record deleted. */
{return 0;}
/* Return all fields that are currently cached for record. */
enum mail_cache_field
/* Set data_r and size_r to point to wanted field in cache file.
Returns TRUE if field was found. If field contains multiple fields,
first one found is returned. This is mostly useful for finding headers. */
enum mail_cache_field field,
/* Return string field. */
const char *
enum mail_cache_field field) {return 0;}
/* Copy fixed size field to given buffer. buffer_size must be exactly the
expected size. The result will be converted to host byte order.
Returns TRUE if field was found. */
enum mail_cache_field field,
/* Mark given fields as missing, ie. they should be cached when possible. */
enum mail_cache_field fields) {}
/* Return index flags. */
{return 0;}
/* Update index flags. The cache file must be locked and the flags must be
already inserted to the record. */
enum mail_index_record_flag flags)
{return 0;}
/* Update location offset. External locking is assumed to take care of locking
readers out to prevent race conditions. */
{return 0;}
/* "Error in index cache file %s: ...". */
{}
#endif