mail-cache-compress.c revision 6e07b4251bf6a3cf34019c351a32a65c08392e58
/* Copyright (c) 2003-2008 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "ostream.h"
#include "nfs-workarounds.h"
#include "read-full.h"
#include "close-keep-errno.h"
#include "file-dotlock.h"
#include "file-cache.h"
#include "file-set-size.h"
#include "mail-cache-private.h"
struct mail_cache_copy_context {
struct mail_cache *cache;
ARRAY_DEFINE(bitmask_pos, unsigned int);
bool new_msg;
};
static void
const struct mail_cache_iterate_field *field)
{
unsigned char *dest;
unsigned int i, *pos;
if (*pos == 0) {
/* we decided to drop this field */
return;
}
}
static void
const struct mail_cache_iterate_field *field)
{
struct mail_cache_field *cache_field;
enum mail_cache_decision_type dec;
return;
/* duplicate */
return;
}
if (dec == MAIL_CACHE_DECISION_NO)
return;
} else {
if (dec != MAIL_CACHE_DECISION_YES)
return;
}
}
/* remember the position in case we need to update it */
}
}
static uint32_t
{
const struct mail_index_ext *ext;
}
static void
unsigned int used_fields_count)
{
struct mail_cache_field *field;
unsigned int i, j, idx;
/* Make mail_cache_header_fields_get() return the fields in
the same order as we saved them. */
/* reverse mapping */
i_new(unsigned int, used_fields_count);
for (i = j = 0; i < cache->fields_count; i++) {
j++;
}
/* change permanent decisions to temporary decisions.
if they're still permanent they'll get updated later. */
}
i_assert(j == used_fields_count);
}
static int
{
struct mail_cache_copy_context ctx;
struct mail_cache_lookup_iterate_ctx iter;
struct mail_cache_iterate_field field;
struct mail_index_view *view;
struct mail_cache_view *cache_view;
const struct mail_index_header *idx_hdr;
struct mail_cache_header hdr;
struct mail_cache_record cache_rec;
unsigned int i, used_fields_count, orig_fields_count;
ctx.field_seen_value = 0;
/* @UNSAFE: drop unused fields and create a field mapping for
used fields */
if (cache->file_fields_count == 0) {
/* creating the initial cache file. add all fields. */
for (i = 0; i < orig_fields_count; i++)
ctx.field_file_map[i] = i;
used_fields_count = i;
} else {
for (i = used_fields_count = 0; i < orig_fields_count; i++) {
struct mail_cache_field_private *priv =
enum mail_cache_decision_type dec =
/* if the decision isn't forced and this field hasn't
been accessed for a while, drop it */
if ((dec & MAIL_CACHE_DECISION_FORCED) == 0 &&
}
/* drop all fields we don't want */
if ((dec & ~MAIL_CACHE_DECISION_FORCED) ==
}
}
}
/* get sequence of first message which doesn't need its temp fields
removed. */
(void)array_append_space(ext_offsets);
continue;
}
if (++ctx.field_seen_value == 0) {
}
/* nothing cached */
ext_offset = 0;
} else {
sizeof(cache_rec));
}
}
o_stream_seek(output, 0);
if (o_stream_flush(output) < 0) {
return -1;
}
/* grow the file some more. doesn't matter if it fails */
}
return -1;
}
}
return 0;
}
{
struct mail_cache_header hdr;
unsigned int i;
for (i = 0;; i++) {
if (fd == -1) {
return 0;
return -1;
}
if (ret >= 0) {
if (ret == 0)
return 0;
if (cache->need_compress_file_seq == 0) {
/* previously it didn't exist */
return 1;
}
return -1;
}
}
}
struct mail_index_transaction *trans,
bool *unlock)
{
unsigned int i, count;
/* get the latest info on fields */
if (mail_cache_header_fields_read(cache) < 0)
return -1;
0, &dotlock);
if (fd == -1) {
return -1;
}
if (ret < 0)
return -1;
/* was just compressed, forget this */
cache->need_compress_file_seq = 0;
if (*unlock) {
(void)mail_cache_unlock(cache);
}
return mail_cache_reopen(cache);
}
return -1;
}
(void)file_dotlock_delete(&dotlock);
return -1;
}
(void)file_dotlock_delete(&dotlock);
return -1;
}
if (file_dotlock_replace(&dotlock,
"file_dotlock_replace()");
return -1;
}
/* once we're sure that the compression was successful,
update the offsets */
for (i = 0; i < count; i++) {
if (offsets[i] != 0) {
&offsets[i], &old_offset);
}
}
if (*unlock) {
(void)mail_cache_unlock(cache);
}
if (mail_cache_map(cache, 0, 0) < 0)
return -1;
if (mail_cache_header_fields_read(cache) < 0)
return -1;
cache->need_compress_file_seq = 0;
return 0;
}
struct mail_index_transaction *trans)
{
int ret;
return 0;
/* we're using dotlocking, cache file creation itself creates
the dotlock file we need. */
if (!MAIL_CACHE_IS_UNUSABLE(cache)) {
FALSE);
}
}
case -1:
return -1;
case 0:
/* couldn't lock, either it's broken or doesn't exist.
just start creating it. */
default:
/* locking succeeded. */
if (unlock) {
if (mail_cache_unlock(cache) < 0)
ret = -1;
}
return ret;
}
}
{
return cache->need_compress_file_seq != 0 &&
}