mail-cache-transaction.c revision ba482d3624ca4f1b3d638e6e8470ba5134f21493
/* Copyright (C) 2003-2004 Timo Sirainen */
#include "lib.h"
#include "buffer.h"
#include "byteorder.h"
#include "file-set-size.h"
#include "mmap-util.h"
#include "mail-cache-private.h"
struct mail_cache_transaction_ctx {
struct mail_cache *cache;
struct mail_cache_view *view;
struct mail_index_transaction *trans;
unsigned int next_unused_header_lowwater;
struct mail_cache_record cache_rec;
enum mail_cache_field prev_fields;
};
static const unsigned char *null4[] = { 0, 0, 0, 0 };
struct mail_index_transaction *t,
struct mail_cache_transaction_ctx **ctx_r)
{
struct mail_cache_transaction_ctx *ctx;
int ret;
if (ret <= 0)
return ret;
return 1;
}
{
int ret = 0;
(void)mail_cache_transaction_rollback(ctx);
ret = -1;
return ret;
}
{
ctx->prev_fields = 0;
}
{
}
{
return -1;
}
data += 2;
}
return 0;
}
{
/* write everything to disk */
return -1;
}
return -1;
}
return 0;
/* now that we're sure it's written, set on all the used-bits */
if (write_mark_updates(cache) < 0)
return -1;
/* update continued records count */
(sizeof(uint32_t) * 2);
/* too many continued rows, compress */
//FIXME:cache->index->set_flags |= MAIL_INDEX_HDR_FLAG_COMPRESS_CACHE;
}
return 0;
}
static int
{
if (grow_size < 16384)
grow_size = 16384;
new_fsize &= ~1023;
return -1;
}
/* no need to grow, just update mmap */
if (mail_cache_mmap_update(cache, 0, 0) < 0)
return -1;
return 0;
}
return -1;
}
return mail_cache_mmap_update(cache, 0, 0);
}
{
/* NOTE: must be done within transaction or rollback would break it */
if (offset >= 0x40000000) {
"Cache file too large: %s",
return 0;
}
return 0;
}
return offset;
}
{
const struct mail_index_record *rec;
struct mail_index_map *map;
const void *buf;
int ret;
// FIXME: check cache_offset in transaction
if (ret < 0)
return -1;
/* FIXME: we should check if newer file is available? */
ret = 0;
}
if (ret == 0) {
/* it's been expunged already, do nothing */
} else {
if (write_offset == 0)
return -1;
TRUE);
/* first cache record - update offset in index file */
} else {
/* find the last cache record */
/* mark next_offset to be updated later */
}
}
/* reset the write context */
ctx->prev_fields = 0;
return 0;
}
{
int ret = 0;
return 0;
}
if (mail_cache_write(ctx) < 0)
return -1;
}
if (commit_all_changes(ctx) < 0)
ret = -1;
/* they're all used - compress the cache to get more */
/* FIXME: ctx->cache->index->set_flags |=
MAIL_INDEX_HDR_FLAG_COMPRESS_CACHE;*/
}
return ret;
}
{
unsigned int i;
/* no need to actually modify the file - we just didn't update
used_file_size */
/* make sure we don't cache the headers */
for (i = 0; i < ctx->next_unused_header_lowwater; i++) {
if (mail_cache_offset_to_uint32(offset) == 0)
}
}
static const char *write_header_string(const char *const headers[],
{
if (buffer_get_used_size(buffer) != 0)
headers++;
}
if ((size & 3) != 0) {
}
}
{
const char *header_str, *prev_str;
header_offsets[idx]) == 0);
t_push();
if (idx != 0) {
t_pop();
return FALSE;
}
}
if (offset != 0) {
header_str, size);
/* update cached headers */
/* mark used-bit to be updated later. not really needed for
read-safety, but if transaction get rolled back we can't let
this point to invalid location. */
/* make sure get_header_fields() still works for this header
while the transaction isn't yet committed. */
}
t_pop();
return offset > 0;
}
enum mail_cache_field field)
{
const unsigned char *buf;
unsigned int mask;
int i;
return offset;
if ((mask & MAIL_CACHE_FIXED_MASK) != 0)
else {
sizeof(data_size));
}
}
}
i_unreached();
return offset;
}
{
unsigned int mask;
int i;
return i;
}
return -1;
}
enum mail_cache_field field,
{
unsigned char *buf;
int field_num;
if ((field & MAIL_CACHE_FIXED_MASK) != 0) {
} else if ((field & MAIL_CACHE_STRING_MASK) != 0) {
}
if (mail_cache_write(ctx) < 0)
return -1;
}
if ((field & MAIL_CACHE_FIXED_MASK) == 0)
full_size += sizeof(nb_data_size);
/* fields must be ordered. find where to insert it. */
else {
}
/* @UNSAFE */
if ((field & MAIL_CACHE_FIXED_MASK) == 0) {
buf += sizeof(nb_data_size);
}
if ((data_size & 3) != 0)
/* remember the transaction sequence range */
return 0;
}
{
struct mail_cache_record *cache_rec;
return 0;
/* we'll only update the deleted_space in header. we can't really
do any actual deleting as other processes might still be using
the data. also it's actually useful as some index views are still
able to ask cached data from messages that have already been
expunged. */
do {
/* see if we've reached the max. deleted space in file */
if (deleted_space >= max_del_space &&
//FIXME:cache->index->set_flags |= MAIL_INDEX_HDR_FLAG_COMPRESS_CACHE;
}
return 0;
}
int
{
/* write non-index changes */
return -1;
}
return -1;
}
return 0;
}
enum mail_cache_record_flag flags)
{
return -1;
}