[dovecot-cvs] dovecot/src/lib-index mail-cache-compress.c, 1.4,
1.5 mail-cache-decisions.c, 1.2, 1.3 mail-cache-lookup.c, 1.7,
1.8 mail-cache-private.h, 1.4, 1.5 mail-cache-transaction.c,
1.7, 1.8 mail-cache.c, 1.34, 1.35 mail-cache.h, 1.13,
1.14 mail-index-sync.c, 1.26, 1.27
cras at procontrol.fi
cras at procontrol.fi
Sun Jul 4 14:50:51 EEST 2004
Update of /home/cvs/dovecot/src/lib-index
In directory talvi:/tmp/cvs-serv22881/lib-index
Modified Files:
mail-cache-compress.c mail-cache-decisions.c
mail-cache-lookup.c mail-cache-private.h
mail-cache-transaction.c mail-cache.c mail-cache.h
mail-index-sync.c
Log Message:
Cache file compression works now and compressed cache file is reopened.
Several other cleanups related to opening - cache file isn't created
immediately anymore.
Index: mail-cache-compress.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-cache-compress.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- mail-cache-compress.c 29 Jun 2004 16:23:54 -0000 1.4
+++ mail-cache-compress.c 4 Jul 2004 11:50:48 -0000 1.5
@@ -4,6 +4,7 @@
#include "buffer.h"
#include "byteorder.h"
#include "ostream.h"
+#include "file-set-size.h"
#include "mail-cache-private.h"
static unsigned char null4[4] = { 0, 0, 0, 0 };
@@ -100,39 +101,46 @@
removed. */
if (mail_index_get_header(view, &idx_hdr) < 0)
return -1;
- if (mail_index_lookup_uid_range(view, idx_hdr->day_first_uid[7],
- (uint32_t)-1, &first_new_seq,
- &message_count) < 0)
- return -1;
- if (first_new_seq == 0)
- first_new_seq = message_count+1;
+ if (idx_hdr->day_first_uid[7] == 0) {
+ first_new_seq = 1;
+ message_count = mail_index_view_get_message_count(view);
+ } else {
+ if (mail_index_lookup_uid_range(view, idx_hdr->day_first_uid[7],
+ (uint32_t)-1, &first_new_seq,
+ &message_count) < 0)
+ return -1;
+ if (first_new_seq == 0)
+ first_new_seq = message_count+1;
+ }
cache_view = mail_cache_view_open(cache, view);
t = mail_index_transaction_begin(view, FALSE);
output = o_stream_create_file(fd, default_pool, 0, FALSE);
memset(&hdr, 0, sizeof(hdr));
- hdr.indexid = cache->hdr->indexid;
- hdr.file_seq = cache->hdr->file_seq + 1;
+ hdr.indexid = idx_hdr->indexid;
+ hdr.file_seq = idx_hdr->cache_file_seq + 1;
- memcpy(hdr.field_usage_decision_type,
- cache->hdr->field_usage_decision_type,
- sizeof(hdr.field_usage_decision_type));
- memcpy(hdr.field_usage_last_used,
- cache->hdr->field_usage_last_used,
- sizeof(hdr.field_usage_last_used));
+ if (cache->hdr != NULL) {
+ memcpy(hdr.field_usage_decision_type,
+ cache->hdr->field_usage_decision_type,
+ sizeof(hdr.field_usage_decision_type));
+ memcpy(hdr.field_usage_last_used,
+ cache->hdr->field_usage_last_used,
+ sizeof(hdr.field_usage_last_used));
- keep_fields = temp_fields = 0;
- for (i = 0; i < 32; i++) {
- if (cache->hdr->field_usage_decision_type[i] &
- MAIL_CACHE_DECISION_YES)
- keep_fields |= 1 << i;
- else if (cache->hdr->field_usage_decision_type[i] &
- MAIL_CACHE_DECISION_TEMP)
- temp_fields |= 1 << i;
+ keep_fields = temp_fields = 0;
+ for (i = 0; i < 32; i++) {
+ if (cache->hdr->field_usage_decision_type[i] &
+ MAIL_CACHE_DECISION_YES)
+ keep_fields |= 1 << i;
+ else if (cache->hdr->field_usage_decision_type[i] &
+ MAIL_CACHE_DECISION_TEMP)
+ temp_fields |= 1 << i;
+ }
}
- offset = sizeof(hdr);
+ o_stream_send(output, &hdr, sizeof(hdr));
/* merge all the header pieces into one. if some message doesn't have
all the required pieces, we'll just have to drop them all. */
@@ -145,7 +153,8 @@
if (str == NULL)
header_idx = -1;
else {
- hdr.header_offsets[0] = mail_cache_uint32_to_offset(offset);
+ hdr.header_offsets[0] =
+ mail_cache_uint32_to_offset(output->offset);
header_idx = i;
size = strlen(str) + 1;
@@ -198,9 +207,26 @@
}
hdr.used_file_size = uint32_to_nbo(output->offset);
- o_stream_unref(output);
+ o_stream_seek(output, 0);
+ o_stream_send(output, &hdr, sizeof(hdr));
+
mail_cache_view_close(cache_view);
+ if (o_stream_flush(output) < 0) {
+ errno = output->stream_errno;
+ mail_cache_set_syscall_error(cache, "o_stream_flush()");
+ (void)mail_index_transaction_rollback(t);
+ o_stream_unref(output);
+ return -1;
+ }
+
+ if (output->offset < MAIL_CACHE_INITIAL_SIZE) {
+ /* grow the file some more. doesn't matter if it fails */
+ (void)file_set_size(fd, MAIL_CACHE_INITIAL_SIZE);
+ }
+
+ o_stream_unref(output);
+
if (fdatasync(fd) < 0) {
mail_cache_set_syscall_error(cache, "fdatasync()");
(void)mail_index_transaction_rollback(t);
@@ -212,12 +238,13 @@
int mail_cache_compress(struct mail_cache *cache, struct mail_index_view *view)
{
- int fd, ret;
+ int fd, ret, locked;
i_assert(cache->trans_ctx == NULL);
- if ((ret = mail_cache_lock(cache, TRUE)) <= 0)
- return ret;
+ if ((ret = mail_cache_lock(cache, TRUE)) < 0)
+ return -1;
+ locked = ret > 0;
#ifdef DEBUG
i_warning("Compressing cache file %s", cache->filepath);
@@ -232,6 +259,7 @@
return -1;
}
+ ret = 0;
if (mail_cache_copy(cache, view, fd) < 0) {
(void)file_dotlock_delete(cache->filepath, NULL, fd);
ret = -1;
@@ -246,7 +274,7 @@
mail_cache_file_close(cache);
cache->fd = fd;
- if (mail_cache_mmap_update(cache, 0, 0) < 0)
+ if (mail_cache_map(cache, 0, 0) < 0)
ret = -1;
}
}
@@ -255,8 +283,10 @@
memset(cache->split_offsets, 0, sizeof(cache->split_offsets));
memset(cache->split_headers, 0, sizeof(cache->split_headers));
- if (mail_cache_unlock(cache) < 0)
- return -1;
+ if (locked) {
+ if (mail_cache_unlock(cache) < 0)
+ return -1;
+ }
if (ret == 0)
cache->need_compress = FALSE;
@@ -265,5 +295,5 @@
int mail_cache_need_compress(struct mail_cache *cache)
{
- return FALSE; //FIXME:cache->need_compress;
+ return cache->need_compress;
}
Index: mail-cache-decisions.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-cache-decisions.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- mail-cache-decisions.c 30 Jun 2004 12:18:35 -0000 1.2
+++ mail-cache-decisions.c 4 Jul 2004 11:50:49 -0000 1.3
@@ -132,6 +132,9 @@
unsigned int idx;
uint32_t uid;
+ if (MAIL_CACHE_IS_UNUSABLE(view->cache))
+ return;
+
idx = mail_cache_field_index(field);
if (view->cache->hdr->field_usage_decision_type[idx] !=
MAIL_CACHE_DECISION_NO) {
Index: mail-cache-lookup.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-cache-lookup.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- mail-cache-lookup.c 28 Jun 2004 17:35:27 -0000 1.7
+++ mail-cache-lookup.c 4 Jul 2004 11:50:49 -0000 1.8
@@ -13,7 +13,7 @@
uint32_t offset, data_size;
unsigned char *buf;
- if (cache->disabled)
+ if (MAIL_CACHE_IS_UNUSABLE(cache))
return NULL;
offset = mail_cache_offset_to_uint32(cache->hdr->header_offsets[idx]);
@@ -21,7 +21,7 @@
if (offset == 0)
return NULL;
- if (mail_cache_mmap_update(cache, offset, CACHE_PREFETCH) < 0)
+ if (mail_cache_map(cache, offset, CACHE_PREFETCH) < 0)
return NULL;
if (offset + sizeof(data_size) > cache->mmap_length) {
@@ -42,7 +42,7 @@
}
if (data_size + sizeof(data_size) > CACHE_PREFETCH) {
- if (mail_cache_mmap_update(cache, offset, data_size) < 0)
+ if (mail_cache_map(cache, offset, data_size) < 0)
return NULL;
}
@@ -93,7 +93,7 @@
i_assert(idx < MAIL_CACHE_HEADERS_COUNT);
- if (view->cache->disabled)
+ if (MAIL_CACHE_IS_UNUSABLE(view->cache))
return NULL;
/* t_strsplit() is a bit slow, so we cache it */
@@ -127,8 +127,8 @@
if (offset == 0)
return NULL;
- if (mail_cache_mmap_update(cache, offset,
- sizeof(*cache_rec) + CACHE_PREFETCH) < 0)
+ if (mail_cache_map(cache, offset,
+ sizeof(*cache_rec) + CACHE_PREFETCH) < 0)
return NULL;
if (offset + sizeof(*cache_rec) > cache->mmap_length) {
@@ -143,7 +143,7 @@
return NULL;
}
if (size > CACHE_PREFETCH) {
- if (mail_cache_mmap_update(cache, offset, size) < 0)
+ if (mail_cache_map(cache, offset, size) < 0)
return NULL;
}
@@ -154,42 +154,48 @@
return cache_rec;
}
-struct mail_cache_record *
-mail_cache_get_next_record(struct mail_cache *cache,
- struct mail_cache_record *rec)
+int mail_cache_lookup_offset(struct mail_cache_view *view, uint32_t seq,
+ uint32_t *offset_r, int skip_expunged)
{
- struct mail_cache_record *next;
+ const struct mail_index_record *rec;
+ struct mail_index_map *map;
+ int i, ret;
- next = mail_cache_get_record(cache, rec->next_offset, FALSE);
- if (next != NULL && next <= rec) {
- mail_cache_set_corrupted(cache, "next_offset points backwards");
- return NULL;
+ for (i = 0; i < 2; i++) {
+ ret = mail_index_lookup_full(view->view, seq, &map, &rec);
+ if (ret < 0)
+ return -1;
+ if (ret == 0 && skip_expunged)
+ return 0;
+
+ if (map->hdr->cache_file_seq == view->cache->hdr->file_seq) {
+ *offset_r = rec->cache_offset;
+ return 1;
+ }
+
+ if ((ret = mail_cache_reopen(view->cache)) <= 0)
+ return ret;
}
- return next;
+
+ return 0;
}
struct mail_cache_record *
mail_cache_lookup(struct mail_cache_view *view, uint32_t seq,
enum mail_cache_field fields)
{
- const struct mail_index_record *rec;
- struct mail_index_map *map;
+ uint32_t offset;
if (mail_cache_transaction_autocommit(view, seq, fields) < 0)
return NULL;
- if (view->cache->disabled)
- return NULL;
-
- if (mail_index_lookup_full(view->view, seq, &map, &rec) < 0)
+ if (MAIL_CACHE_IS_UNUSABLE(view->cache))
return NULL;
- if (map->hdr->cache_file_seq != view->cache->hdr->file_seq) {
- /* FIXME: we should check if newer file is available? */
+ if (mail_cache_lookup_offset(view, seq, &offset, FALSE) <= 0)
return NULL;
- }
- return mail_cache_get_record(view->cache, rec->cache_offset, TRUE);
+ return mail_cache_get_record(view->cache, offset, TRUE);
}
enum mail_cache_field
@@ -201,7 +207,9 @@
cache_rec = mail_cache_lookup(view, seq, 0);
while (cache_rec != NULL) {
fields |= cache_rec->fields;
- cache_rec = mail_cache_get_next_record(view->cache, cache_rec);
+ cache_rec = mail_cache_get_record(view->cache,
+ cache_rec->next_offset,
+ FALSE);
}
return fields;
@@ -280,7 +288,9 @@
return cache_get_field(view->cache, cache_rec, field,
data_r, size_r);
}
- cache_rec = mail_cache_get_next_record(view->cache, cache_rec);
+ cache_rec = mail_cache_get_record(view->cache,
+ cache_rec->next_offset,
+ FALSE);
}
return FALSE;
Index: mail-cache-private.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-cache-private.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- mail-cache-private.h 28 Jun 2004 17:35:27 -0000 1.4
+++ mail-cache-private.h 4 Jul 2004 11:50:49 -0000 1.5
@@ -27,6 +27,9 @@
#define CACHE_RECORD(cache, offset) \
((struct mail_cache_record *) ((char *) (cache)->mmap_base + offset))
+#define MAIL_CACHE_IS_UNUSABLE(cache) \
+ ((cache)->hdr == NULL)
+
enum mail_cache_decision_type {
/* Not needed currently */
MAIL_CACHE_DECISION_NO = 0x00,
@@ -83,10 +86,7 @@
struct mail_cache_transaction_ctx *trans_ctx;
unsigned int locks;
- unsigned int mmap_refresh:1;
unsigned int need_compress:1;
- unsigned int silent:1;
- unsigned int disabled:1;
};
struct mail_cache_view {
@@ -111,10 +111,9 @@
struct mail_cache_record *
mail_cache_get_record(struct mail_cache *cache, uint32_t offset,
int index_offset);
-struct mail_cache_record *
-mail_cache_get_next_record(struct mail_cache *cache,
- struct mail_cache_record *rec);
+int mail_cache_lookup_offset(struct mail_cache_view *view, uint32_t seq,
+ uint32_t *offset, int skip_expunged);
struct mail_cache_record *
mail_cache_lookup(struct mail_cache_view *view, uint32_t seq,
enum mail_cache_field fields);
@@ -123,9 +122,9 @@
mail_cache_transaction_autocommit(struct mail_cache_view *view,
uint32_t seq, enum mail_cache_field fields);
-int mail_cache_mmap_update(struct mail_cache *cache,
- size_t offset, size_t size);
+int mail_cache_map(struct mail_cache *cache, size_t offset, size_t size);
void mail_cache_file_close(struct mail_cache *cache);
+int mail_cache_reopen(struct mail_cache *cache);
void mail_cache_handle_decisions(struct mail_cache_view *view, uint32_t seq,
enum mail_cache_field field);
Index: mail-cache-transaction.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-cache-transaction.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- mail-cache-transaction.c 28 Jun 2004 17:35:27 -0000 1.7
+++ mail-cache-transaction.c 4 Jul 2004 11:50:49 -0000 1.8
@@ -7,6 +7,7 @@
#include "mmap-util.h"
#include "mail-cache-private.h"
+#include <stddef.h>
#include <sys/stat.h>
struct mail_cache_transaction_ctx {
@@ -174,7 +175,7 @@
if (ctx->used_file_size + size <= (uoff_t)st.st_size) {
/* no need to grow, just update mmap */
- if (mail_cache_mmap_update(cache, 0, 0) < 0)
+ if (mail_cache_map(cache, 0, (size_t)st.st_size) < 0)
return -1;
i_assert(cache->mmap_length >= (uoff_t)st.st_size);
@@ -186,7 +187,7 @@
return -1;
}
- return mail_cache_mmap_update(cache, 0, 0);
+ return mail_cache_map(cache, 0, (size_t)new_fsize);
}
static uint32_t mail_cache_append_space(struct mail_cache_transaction_ctx *ctx,
@@ -217,10 +218,8 @@
static int mail_cache_write(struct mail_cache_transaction_ctx *ctx)
{
struct mail_cache *cache = ctx->cache;
- struct mail_cache_record *cache_rec, *next;
- const struct mail_index_record *rec;
- struct mail_index_map *map;
- uint32_t write_offset, update_offset;
+ struct mail_cache_record *cache_rec;
+ uint32_t offset, write_offset;
const void *buf;
size_t size, buf_size;
int ret;
@@ -230,16 +229,10 @@
size = sizeof(*cache_rec) + buf_size;
ctx->cache_rec.size = uint32_to_nbo(size);
- ret = mail_index_lookup_full(ctx->view->view, ctx->prev_seq,
- &map, &rec);
+ ret = mail_cache_lookup_offset(ctx->view, ctx->prev_seq, &offset, TRUE);
if (ret < 0)
return -1;
- if (map->hdr->cache_file_seq != cache->hdr->file_seq) {
- /* FIXME: we should check if newer file is available? */
- ret = 0;
- }
-
if (ret == 0) {
/* it's been expunged already, do nothing */
} else {
@@ -247,22 +240,25 @@
if (write_offset == 0)
return -1;
- cache_rec = mail_cache_get_record(cache, rec->cache_offset,
- TRUE);
+ cache_rec = mail_cache_get_record(cache, offset, TRUE);
if (cache_rec == NULL) {
/* first cache record - update offset in index file */
mail_index_update_cache(ctx->trans, ctx->prev_seq,
write_offset);
} else {
- /* find the last cache record */
- while ((next = mail_cache_get_next_record(cache,
- cache_rec)) != NULL)
- cache_rec = next;
+ /* find offset to last cache record */
+ for (;;) {
+ cache_rec = mail_cache_get_record(cache, offset,
+ FALSE);
+ if (cache_rec == NULL)
+ break;
+ offset = cache_rec->next_offset;
+ }
/* mark next_offset to be updated later */
- update_offset = (char *) &cache_rec->next_offset -
- (char *) cache->mmap_base;
- mark_update(&ctx->cache_marks, update_offset,
+ offset = mail_cache_offset_to_uint32(offset) +
+ offsetof(struct mail_cache_record, next_offset);
+ mark_update(&ctx->cache_marks, offset,
mail_cache_uint32_to_offset(write_offset));
}
@@ -285,7 +281,7 @@
{
int ret = 0;
- if (ctx->cache->disabled) {
+ if (MAIL_CACHE_IS_UNUSABLE(ctx->cache)) {
mail_cache_transaction_flush(ctx);
return 0;
}
@@ -541,7 +537,8 @@
do {
deleted_space -= nbo_to_uint32(cache_rec->size);
- cache_rec = mail_cache_get_next_record(cache, cache_rec);
+ cache_rec = mail_cache_get_record(cache, cache_rec->next_offset,
+ FALSE);
} while (cache_rec != NULL);
/* see if we've reached the max. deleted space in file */
Index: mail-cache.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-cache.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- mail-cache.c 28 Jun 2004 22:17:59 -0000 1.34
+++ mail-cache.c 4 Jul 2004 11:50:49 -0000 1.35
@@ -9,7 +9,6 @@
#include "mail-cache-private.h"
#include <unistd.h>
-#include <sys/stat.h>
unsigned int mail_cache_field_sizes[32] = {
sizeof(enum mail_cache_record_flag),
@@ -92,10 +91,8 @@
{
va_list va;
- (void)mail_cache_reset(cache);
-
- if (cache->silent)
- return;
+ (void)unlink(cache->filepath);
+ mail_cache_file_close(cache);
va_start(va, fmt);
t_push();
@@ -123,20 +120,37 @@
}
}
-static int mail_cache_file_reopen(struct mail_cache *cache)
+int mail_cache_reopen(struct mail_cache *cache)
{
- int fd;
+ if (MAIL_CACHE_IS_UNUSABLE(cache) && cache->need_compress) {
+ /* unusable, we're just waiting for compression */
+ return 0;
+ }
- fd = open(cache->filepath, O_RDWR);
- if (fd == -1) {
- mail_cache_set_syscall_error(cache, "open()");
+ mail_cache_file_close(cache);
+
+ cache->fd = open(cache->filepath, O_RDWR);
+ if (cache->fd == -1) {
+ if (errno == ENOENT)
+ cache->need_compress = TRUE;
+ else
+ mail_cache_set_syscall_error(cache, "open()");
return -1;
}
- mail_cache_file_close(cache);
+ if (mail_cache_map(cache, 0, 0) < 0)
+ return -1;
- cache->fd = fd;
- return 0;
+ if (cache->hdr->file_seq != cache->index->hdr->cache_file_seq) {
+ /* 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. */
+ cache->need_compress = TRUE;
+ return 0;
+ }
+
+ return 1;
}
static int mmap_verify_header(struct mail_cache *cache)
@@ -147,75 +161,52 @@
/* check that the header is still ok */
if (cache->mmap_length < sizeof(struct mail_cache_header)) {
mail_cache_set_corrupted(cache, "File too small");
- return 0;
+ return FALSE;
}
cache->hdr = hdr = cache->mmap_base;
if (cache->hdr->indexid != cache->index->indexid) {
/* index id changed */
- if (cache->hdr->indexid != 0)
- mail_cache_set_corrupted(cache, "indexid changed");
- return 0;
+ mail_cache_set_corrupted(cache, "indexid changed");
+ return FALSE;
}
if (cache->trans_ctx != NULL) {
/* we've updated used_file_size, do nothing */
- return 1;
+ return TRUE;
}
/* only check the header if we're locked */
if (cache->locks == 0)
- return 1;
+ return TRUE;
used_file_size = nbo_to_uint32(hdr->used_file_size);
if (used_file_size < sizeof(struct mail_cache_header)) {
mail_cache_set_corrupted(cache, "used_file_size too small");
- return 0;
+ return FALSE;
}
if ((used_file_size % sizeof(uint32_t)) != 0) {
mail_cache_set_corrupted(cache, "used_file_size not aligned");
- return 0;
+ return FALSE;
}
if (used_file_size > cache->mmap_length) {
mail_cache_set_corrupted(cache, "used_file_size too large");
- return 0;
+ return FALSE;
}
- return 1;
+ return TRUE;
}
-static int mmap_update_nocheck(struct mail_cache *cache,
- size_t offset, size_t size)
+int mail_cache_map(struct mail_cache *cache, size_t offset, size_t size)
{
- struct stat st;
-
-#if 0 // FIXME
- /* if sequence has changed, the file has to be reopened.
- note that if main index isn't locked, it may change again */
- if (cache->hdr->file_seq != cache->index->hdr->cache_file_seq &&
- cache->mmap_base != NULL) {
- if (mail_cache_file_reopen(cache) < 0)
- return -1;
- }
-#endif
+ if (size == 0)
+ size = sizeof(struct mail_cache_header);
if (offset < cache->mmap_length &&
- size <= cache->mmap_length - offset &&
- !cache->mmap_refresh) {
+ size <= cache->mmap_length - offset) {
/* already mapped */
- if (size != 0)
- return 1;
-
- /* requesting the whole file - see if we need to
- re-mmap */
- if (fstat(cache->fd, &st) < 0) {
- mail_cache_set_syscall_error(cache, "fstat()");
- return -1;
- }
- if ((uoff_t)st.st_size == cache->mmap_length)
- return 1;
+ return 0;
}
- cache->mmap_refresh = FALSE;
if (cache->mmap_base != NULL) {
if (cache->locks != 0) {
@@ -229,10 +220,14 @@
if (munmap(cache->mmap_base, cache->mmap_length) < 0)
mail_cache_set_syscall_error(cache, "munmap()");
+ } else {
+ if (cache->fd == -1) {
+ /* unusable, waiting for compression */
+ i_assert(cache->need_compress);
+ return -1;
+ }
}
- i_assert(cache->fd != -1);
-
/* map the whole file */
cache->hdr = NULL;
cache->mmap_length = 0;
@@ -244,156 +239,48 @@
return -1;
}
- /* re-mmaped, check header */
- return 0;
-}
-
-int mail_cache_mmap_update(struct mail_cache *cache, size_t offset, size_t size)
-{
- int synced, ret;
-
- ret = mmap_update_nocheck(cache, offset, size);
- if (ret > 0)
- return 0;
- if (ret < 0)
- return -1;
-
- if (mmap_verify_header(cache) <= 0)
+ if (!mmap_verify_header(cache)) {
+ cache->need_compress = TRUE;
return -1;
+ }
-#if 0 // FIXME
- /* see if cache file was rebuilt - do it only once to avoid
- infinite looping */
- if (cache->hdr->file_seq == cache->index->hdr->cache_file_seq ||
- synced)
- break;
-
- if (mail_cache_file_reopen(cache) < 0)
- return -1;
-#endif
return 0;
}
-static int mail_cache_open_and_verify(struct mail_cache *cache, int silent)
+static int mail_cache_open_and_verify(struct mail_cache *cache)
{
- struct stat st;
- int ret;
-
- mail_cache_file_close(cache);
+ cache->filepath = i_strconcat(cache->index->filepath,
+ MAIL_CACHE_FILE_PREFIX, NULL);
cache->fd = open(cache->filepath, O_RDWR);
if (cache->fd == -1) {
- if (errno == ENOENT)
+ if (errno == ENOENT) {
+ cache->need_compress = TRUE;
return 0;
+ }
mail_cache_set_syscall_error(cache, "open()");
return -1;
}
- if (fstat(cache->fd, &st) < 0) {
- mail_cache_set_syscall_error(cache, "fstat()");
- return -1;
- }
-
- if (st.st_size < sizeof(struct mail_cache_header))
- return 0;
-
- cache->mmap_refresh = TRUE;
- if (mmap_update_nocheck(cache, 0, sizeof(struct mail_cache_header)) < 0)
- return -1;
-
- /* verify that this really is the cache for wanted index */
- cache->silent = silent;
- if ((ret = mmap_verify_header(cache)) <= 0) {
- cache->silent = FALSE;
- return ret;
- }
-
- cache->silent = FALSE;
- return 1;
-}
-
-static int mail_cache_open_or_create_file(struct mail_cache *cache,
- struct mail_cache_header *hdr)
-{
- int ret, fd;
-
- cache->filepath = i_strconcat(cache->index->filepath,
- MAIL_CACHE_FILE_PREFIX, NULL);
-
- ret = mail_cache_open_and_verify(cache, FALSE);
- if (ret != 0)
- return ret < 0 ? -1 : 0;
-
- /* maybe a rebuild.. */
- fd = file_dotlock_open(cache->filepath, NULL, NULL,
- MAIL_CACHE_LOCK_TIMEOUT,
- MAIL_CACHE_LOCK_CHANGE_TIMEOUT,
- MAIL_CACHE_LOCK_IMMEDIATE_TIMEOUT, NULL, NULL);
- if (fd == -1) {
- mail_cache_set_syscall_error(cache, "file_dotlock_open()");
- return -1;
- }
-
- /* see if someone else just created the cache file */
- ret = mail_cache_open_and_verify(cache, TRUE);
- if (ret != 0) {
- (void)file_dotlock_delete(cache->filepath, NULL, fd);
- return ret < 0 ? -1 : 0;
- }
-
- /* rebuild then */
- if (write_full(fd, hdr, sizeof(*hdr)) < 0) {
- mail_cache_set_syscall_error(cache, "write_full()");
- (void)file_dotlock_delete(cache->filepath, NULL, fd);
- return -1;
- }
- if (file_set_size(fd, MAIL_CACHE_INITIAL_SIZE) < 0) {
- mail_cache_set_syscall_error(cache, "file_set_size()");
- (void)file_dotlock_delete(cache->filepath, NULL, fd);
- return -1;
- }
-
- mail_cache_file_close(cache);
- cache->fd = dup(fd);
-
- if (file_dotlock_replace(cache->filepath, NULL, fd, FALSE) < 0) {
- mail_cache_set_syscall_error(cache, "file_dotlock_replace()");
- return -1;
- }
-
- if (mail_cache_mmap_update(cache, 0,
- sizeof(struct mail_cache_header)) < 0)
- return -1;
-
- return 0;
+ return mail_cache_map(cache, 0, sizeof(struct mail_cache_header));
}
struct mail_cache *mail_cache_open_or_create(struct mail_index *index)
{
- struct mail_cache_header hdr;
struct mail_cache *cache;
- memset(&hdr, 0, sizeof(hdr));
- hdr.indexid = index->indexid;
- hdr.file_seq = index->hdr->cache_file_seq + 1;
- hdr.used_file_size = uint32_to_nbo(sizeof(hdr));
-
cache = i_new(struct mail_cache, 1);
cache->index = index;
cache->fd = -1;
cache->split_header_pool = pool_alloconly_create("Headers", 512);
- if (index->mmap_disable ||
- mail_cache_open_or_create_file(cache, &hdr) < 0) {
- /* failed for some reason - doesn't really matter,
- just disable caching. */
- mail_cache_file_close(cache);
-
- i_free(cache->filepath);
- cache->filepath = i_strdup_printf("(disabled cache for %s)",
- index->filepath);
- cache->disabled = TRUE;
+ if (!index->mmap_disable) {
+ if (mail_cache_open_and_verify(cache) < 0) {
+ /* failed for some reason - doesn't really matter,
+ it's disabled for now. */
+ mail_cache_file_close(cache);
+ }
}
return cache;
@@ -418,83 +305,51 @@
cache->never_cache_fields = never_cache_fields;
}
-int mail_cache_reset(struct mail_cache *cache)
-{
- struct mail_cache_header hdr;
- int fd;
-
- memset(&hdr, 0, sizeof(hdr));
- hdr.indexid = cache->index->indexid;
- hdr.file_seq = cache->index->hdr->cache_file_seq + 1;
- hdr.used_file_size = uint32_to_nbo(sizeof(hdr));
-
- fd = file_dotlock_open(cache->filepath, NULL, NULL,
- MAIL_CACHE_LOCK_TIMEOUT,
- MAIL_CACHE_LOCK_CHANGE_TIMEOUT,
- MAIL_CACHE_LOCK_IMMEDIATE_TIMEOUT, NULL, NULL);
- if (fd == -1) {
- mail_cache_set_syscall_error(cache, "file_dotlock_open()");
- return -1;
- }
-
- if (write_full(fd, &hdr, sizeof(hdr)) < 0) {
- mail_cache_set_syscall_error(cache, "write_full()");
- (void)file_dotlock_delete(cache->filepath, NULL, fd);
- return -1;
- }
- if (file_set_size(fd, MAIL_CACHE_INITIAL_SIZE) < 0) {
- mail_cache_set_syscall_error(cache, "file_set_size()");
- (void)file_dotlock_delete(cache->filepath, NULL, fd);
- return -1;
- }
-
- mail_cache_file_close(cache);
- cache->fd = dup(fd);
-
- if (file_dotlock_replace(cache->filepath, NULL, fd, FALSE) < 0) {
- mail_cache_set_syscall_error(cache, "file_dotlock_replace()");
- return -1;
- }
-
- cache->mmap_refresh = TRUE;
- if (mail_cache_mmap_update(cache, 0,
- sizeof(struct mail_cache_header)) < 0)
- return -1;
-
- return 0;
-}
-
int mail_cache_lock(struct mail_cache *cache, int nonblock)
{
- int ret;
+ int i, ret;
if (cache->locks != 0)
return 1;
- if (cache->disabled)
+ if (MAIL_CACHE_IS_UNUSABLE(cache))
return 0;
- if (nonblock) {
- ret = file_try_lock(cache->fd, F_WRLCK);
- if (ret < 0)
- mail_cache_set_syscall_error(cache, "file_try_lock()");
- } else {
- ret = file_wait_lock(cache->fd, F_WRLCK);
- if (ret <= 0)
- mail_cache_set_syscall_error(cache, "file_wait_lock()");
+ if (cache->hdr->file_seq != cache->index->hdr->cache_file_seq) {
+ /* we want the latest cache file */
+ if ((ret = mail_cache_reopen(cache)) <= 0)
+ return ret;
}
- if (ret > 0) {
- if (mail_cache_mmap_update(cache, 0, 0) < 0) {
- (void)mail_cache_unlock(cache);
- return -1;
+ for (i = 0; i < 3; i++) {
+ if (nonblock) {
+ ret = file_try_lock(cache->fd, F_WRLCK);
+ if (ret < 0) {
+ mail_cache_set_syscall_error(cache,
+ "file_try_lock()");
+ }
+ } else {
+ ret = file_wait_lock(cache->fd, F_WRLCK);
+ if (ret <= 0) {
+ mail_cache_set_syscall_error(cache,
+ "file_wait_lock()");
+ }
}
- if (cache->hdr->file_seq != cache->index->hdr->cache_file_seq) {
- mail_cache_unlock(cache);
- return 0;
+ if (ret <= 0)
+ break;
+
+ if (cache->hdr->file_seq == cache->index->hdr->cache_file_seq) {
+ /* got it */
+ cache->locks++;
+ break;
}
- cache->locks++;
+
+ /* okay, so it was just compressed. try again. */
+ mail_cache_unlock(cache);
+ if ((ret = mail_cache_reopen(cache)) <= 0)
+ return ret;
+ ret = 0;
}
return ret;
}
@@ -517,19 +372,6 @@
return cache->locks > 0;
}
-int mail_cache_need_reset(struct mail_cache *cache, uint32_t *new_file_seq_r)
-{
- if (!cache->disabled &&
- cache->hdr->file_seq != cache->index->hdr->cache_file_seq) {
- if (mail_cache_lock(cache, TRUE) == 0) {
- *new_file_seq_r = cache->hdr->file_seq;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
struct mail_cache_view *
mail_cache_view_open(struct mail_cache *cache, struct mail_index_view *iview)
{
Index: mail-cache.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-cache.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- mail-cache.h 28 Jun 2004 22:17:59 -0000 1.13
+++ mail-cache.h 4 Jul 2004 11:50:49 -0000 1.14
@@ -83,20 +83,14 @@
/* Compress cache file. */
int mail_cache_compress(struct mail_cache *cache, struct mail_index_view *view);
-/* Reset the cache file, clearing all data. */
-int mail_cache_reset(struct mail_cache *cache);
-
-/* Explicitly lock the cache file. Returns -1 if error, 1 if ok,
- 0 if we couldn't lock (nonblock = TRUE or index file needs a cache reset) */
+/* Explicitly lock the cache file. Returns -1 if error, 1 if ok, 0 if we
+ couldn't lock */
int mail_cache_lock(struct mail_cache *cache, int nonblock);
int mail_cache_unlock(struct mail_cache *cache);
/* Returns TRUE if cache file is locked. */
int mail_cache_is_locked(struct mail_cache *cache);
-/* Returns TRUE if index's cache_file_seq doesn't match the latest cache file */
-int mail_cache_need_reset(struct mail_cache *cache, uint32_t *new_file_seq_r);
-
struct mail_cache_view *
mail_cache_view_open(struct mail_cache *cache, struct mail_index_view *iview);
void mail_cache_view_close(struct mail_cache_view *view);
Index: mail-index-sync.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index-sync.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- mail-index-sync.c 3 Jul 2004 17:21:26 -0000 1.26
+++ mail-index-sync.c 4 Jul 2004 11:50:49 -0000 1.27
@@ -207,7 +207,7 @@
(index->hdr->log_file_seq == log_file_seq &&
index->hdr->log_file_offset >= log_file_offset)) {
/* already synced */
- return 0;
+ return mail_cache_need_compress(index->cache);
}
return 1;
@@ -219,7 +219,7 @@
uint32_t log_file_seq, uoff_t log_file_offset)
{
struct mail_index_sync_ctx *ctx;
- uint32_t seq, new_file_seq;
+ uint32_t seq;
uoff_t offset;
unsigned int lock_id;
@@ -270,17 +270,6 @@
return -1;
}
- /* check here if cache file's sequence has changed unexpectedly */
- if (mail_cache_need_reset(index->cache, &new_file_seq)) {
- uint32_t seq;
- uoff_t offset;
- struct mail_index_transaction *t;
-
- t = mail_index_transaction_begin(ctx->view, FALSE);
- mail_index_reset_cache(t, new_file_seq);
- mail_index_transaction_commit(t, &seq, &offset);
- }
-
*ctx_r = ctx;
*view_r = ctx->view;
return 1;
More information about the dovecot-cvs
mailing list