[dovecot-cvs] dovecot/src/lib-index mail-cache-compress.c, 1.6, 1.7 mail-cache-lookup.c, 1.9, 1.10 mail-cache-private.h, 1.6, 1.7 mail-cache-transaction.c, 1.9, 1.10 mail-cache.c, 1.36, 1.37 mail-cache.h, 1.15, 1.16 mail-index-private.h, 1.22, 1.23 mail-index-sync-update.c, 1.33, 1.34 mail-index-transaction-private.h, 1.8, 1.9 mail-index-transaction.c, 1.16, 1.17

cras at procontrol.fi cras at procontrol.fi
Sun Jul 4 23:00:50 EEST 2004


Update of /home/cvs/dovecot/src/lib-index
In directory talvi:/tmp/cvs-serv29570/lib-index

Modified Files:
	mail-cache-compress.c mail-cache-lookup.c mail-cache-private.h 
	mail-cache-transaction.c mail-cache.c mail-cache.h 
	mail-index-private.h mail-index-sync-update.c 
	mail-index-transaction-private.h mail-index-transaction.c 
Log Message:
Cache updating is done now by first reserving space where to write, and then
writing to it whenever buffer gets full. There is no persistent cache file
locks anymore because of this, but it also means that the same cached field
may be written multiple times to the file by different processes. Also since
we reserve more space than we actually need at first, it some space can be
wasted if multiple processes are updating the cache.



Index: mail-cache-compress.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-cache-compress.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- mail-cache-compress.c	4 Jul 2004 14:26:22 -0000	1.6
+++ mail-cache-compress.c	4 Jul 2004 20:00:47 -0000	1.7
@@ -166,7 +166,7 @@
 
 	ret = 0;
 	for (seq = 1; seq <= message_count; seq++) {
-		cache_rec = mail_cache_lookup(cache_view, seq, 0);
+		cache_rec = mail_cache_lookup(cache_view, seq);
 		if (cache_rec == NULL)
 			continue;
 
@@ -181,7 +181,7 @@
 		if (keep_fields == cached_fields &&
 		    cache_rec->prev_offset == 0) {
 			/* just one unmodified block, save it */
-                        mail_index_update_cache(t, seq, output->offset);
+                        mail_index_update_cache(t, seq, output->offset, NULL);
 			o_stream_send(output, cache_rec, cache_rec->size);
 
 			if ((cache_rec->size & 3) != 0) {
@@ -191,7 +191,7 @@
 		} else {
 			/* a) dropping fields
 			   b) multiple blocks, sort them into buffer */
-                        mail_index_update_cache(t, seq, output->offset);
+                        mail_index_update_cache(t, seq, output->offset, NULL);
 
 			t_push();
 			cache_rec = mail_cache_compress_record(cache_view, seq,
@@ -237,9 +237,7 @@
 {
 	int fd, ret, locked;
 
-	i_assert(cache->trans_ctx == NULL);
-
-	if ((ret = mail_cache_lock(cache, TRUE)) < 0)
+	if ((ret = mail_cache_lock(cache)) < 0)
 		return -1;
 	locked = ret > 0;
 

Index: mail-cache-lookup.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-cache-lookup.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- mail-cache-lookup.c	4 Jul 2004 14:26:22 -0000	1.9
+++ mail-cache-lookup.c	4 Jul 2004 20:00:47 -0000	1.10
@@ -10,7 +10,7 @@
 mail_cache_get_header_fields_str(struct mail_cache *cache, unsigned int idx)
 {
 	uint32_t offset, data_size;
-	unsigned char *buf;
+	const unsigned char *buf;
 
 	if (MAIL_CACHE_IS_UNUSABLE(cache))
 		return NULL;
@@ -147,19 +147,16 @@
 	return cache_rec;
 }
 
-int mail_cache_lookup_offset(struct mail_cache_view *view, uint32_t seq,
-			     uint32_t *offset_r, int skip_expunged)
+static int mail_cache_lookup_offset(struct mail_cache_view *view, uint32_t seq,
+				    uint32_t *offset_r)
 {
 	const struct mail_index_record *rec;
 	struct mail_index_map *map;
 	int i, ret;
 
 	for (i = 0; i < 2; i++) {
-		ret = mail_index_lookup_full(view->view, seq, &map, &rec);
-		if (ret < 0)
+		if (mail_index_lookup_full(view->view, seq, &map, &rec) < 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;
@@ -174,18 +171,16 @@
 }
 
 struct mail_cache_record *
-mail_cache_lookup(struct mail_cache_view *view, uint32_t seq,
-		  enum mail_cache_field fields)
+mail_cache_lookup(struct mail_cache_view *view, uint32_t seq)
 {
 	uint32_t offset;
 
-	if (mail_cache_transaction_autocommit(view, seq, fields) < 0)
-		return NULL;
+	// FIXME: check transactions too
 
-	if (MAIL_CACHE_IS_UNUSABLE(view->cache))
+        if (MAIL_CACHE_IS_UNUSABLE(view->cache))
 		return NULL;
 
-	if (mail_cache_lookup_offset(view, seq, &offset, FALSE) <= 0)
+	if (mail_cache_lookup_offset(view, seq, &offset) <= 0)
 		return NULL;
 
 	return mail_cache_get_record(view->cache, offset);
@@ -197,7 +192,7 @@
 	struct mail_cache_record *cache_rec;
         enum mail_cache_field fields = 0;
 
-	cache_rec = mail_cache_lookup(view, seq, 0);
+	cache_rec = mail_cache_lookup(view, seq);
 	while (cache_rec != NULL) {
 		fields |= cache_rec->fields;
 		cache_rec = mail_cache_get_record(view->cache,
@@ -271,7 +266,7 @@
 
 	mail_cache_handle_decisions(view, seq, field);
 
-	cache_rec = mail_cache_lookup(view, seq, field);
+	cache_rec = mail_cache_lookup(view, seq);
 	while (cache_rec != NULL) {
 		if ((cache_rec->fields & field) != 0) {
 			return cache_get_field(view->cache, cache_rec, field,

Index: mail-cache-private.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-cache-private.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- mail-cache-private.h	4 Jul 2004 14:26:22 -0000	1.6
+++ mail-cache-private.h	4 Jul 2004 20:00:47 -0000	1.7
@@ -9,6 +9,9 @@
 /* Never compress the file if it's smaller than this */
 #define COMPRESS_MIN_SIZE (1024*50)
 
+/* Don't bother remembering holes smaller than this */
+#define MAIL_CACHE_MIN_HOLE_SIZE 1024
+
 /* Compress the file when deleted space reaches n% of total size */
 #define COMPRESS_PERCENTAGE 20
 
@@ -55,6 +58,7 @@
 
 	uint32_t continued_record_count;
 
+	uint32_t hole_offset;
 	uint32_t used_file_size;
 	uint32_t deleted_space;
 
@@ -70,6 +74,17 @@
 	uint32_t size; /* full record size, including this header */
 };
 
+struct mail_cache_hole_header {
+	uint32_t next_offset; /* 0 if no holes left */
+	uint32_t size; /* including this header */
+
+	/* make sure we notice if we're treating hole as mail_cache_record.
+	   magic is a large number so if it's treated as size field, it'll
+	   point outside the file */
+#define MAIL_CACHE_HOLE_HEADER_MAGIC 0xffeedeff
+	uint32_t magic;
+};
+
 struct mail_cache {
 	struct mail_index *index;
 
@@ -79,7 +94,8 @@
 	void *mmap_base;
 	size_t mmap_length;
 
-	struct mail_cache_header *hdr;
+	const struct mail_cache_header *hdr;
+	struct mail_cache_header hdr_copy;
 
 	pool_t split_header_pool;
 	uint32_t split_offsets[MAIL_CACHE_HEADERS_COUNT];
@@ -90,10 +106,9 @@
 
 	uint32_t field_usage_uid_highwater[32];
 
-        struct mail_cache_transaction_ctx *trans_ctx;
-	unsigned int locks;
-
+	unsigned int locked:1;
 	unsigned int need_compress:1;
+	unsigned int hdr_modified:1;
 };
 
 struct mail_cache_view {
@@ -110,6 +125,11 @@
 uint32_t mail_cache_offset_to_uint32(uint32_t offset);
 unsigned int mail_cache_field_index(enum mail_cache_field field);
 
+/* 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);
+void mail_cache_unlock(struct mail_cache *cache);
+
 const char *
 mail_cache_get_header_fields_str(struct mail_cache *cache, unsigned int idx);
 const char *const *
@@ -118,22 +138,21 @@
 struct mail_cache_record *
 mail_cache_get_record(struct mail_cache *cache, uint32_t offset);
 
-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);
+mail_cache_lookup(struct mail_cache_view *view, uint32_t seq);
 
-int
-mail_cache_transaction_autocommit(struct mail_cache_view *view,
-				  uint32_t seq, enum mail_cache_field fields);
+int mail_cache_transaction_commit(struct mail_cache_transaction_ctx *ctx);
+void mail_cache_transaction_rollback(struct mail_cache_transaction_ctx *ctx);
 
 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);
 
+/* Update new_offset's prev_offset field to old_offset. */
 int mail_cache_link(struct mail_cache *cache, uint32_t old_offset,
 		    uint32_t new_offset);
+/* Mark record in given offset to be deleted. */
+int mail_cache_delete(struct mail_cache *cache, uint32_t offset);
 
 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.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- mail-cache-transaction.c	4 Jul 2004 14:26:22 -0000	1.9
+++ mail-cache-transaction.c	4 Jul 2004 20:00:47 -0000	1.10
@@ -3,8 +3,10 @@
 #include "lib.h"
 #include "buffer.h"
 #include "file-set-size.h"
-#include "mmap-util.h"
+#include "read-full.h"
+#include "write-full.h"
 #include "mail-cache-private.h"
+#include "mail-index-transaction-private.h"
 
 #include <stddef.h>
 #include <sys/stat.h>
[...961 lines suppressed...]
-
-int mail_cache_link(struct mail_cache *cache, uint32_t old_offset,
-		    uint32_t new_offset)
-{
-	struct mail_cache_record *cache_rec;
-
-	i_assert(cache->locks > 0);
-
-	if (mail_cache_map(cache, new_offset, sizeof(*cache_rec)) < 0)
-		return -1;
-
-	if (new_offset + sizeof(*cache_rec) > cache->mmap_length) {
-		mail_cache_set_corrupted(cache, "record points outside file");
-		return -1;
-	}
-	cache_rec = CACHE_RECORD(cache, new_offset);
-	cache_rec->prev_offset = old_offset;
+	cache->hdr_modified = TRUE;
 	return 0;
 }

Index: mail-cache.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-cache.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -d -r1.36 -r1.37
--- mail-cache.c	4 Jul 2004 14:26:22 -0000	1.36
+++ mail-cache.c	4 Jul 2004 20:00:47 -0000	1.37
@@ -154,7 +154,7 @@
 
 static int mmap_verify_header(struct mail_cache *cache)
 {
-	struct mail_cache_header *hdr;
+	const struct mail_cache_header *hdr;
 
 	/* check that the header is still ok */
 	if (cache->mmap_length < sizeof(struct mail_cache_header)) {
@@ -174,13 +174,8 @@
 		return FALSE;
 	}
 
-	if (cache->trans_ctx != NULL) {
-		/* we've updated used_file_size, do nothing */
-		return TRUE;
-	}
-
 	/* only check the header if we're locked */
-	if (cache->locks == 0)
+	if (cache->locked)
 		return TRUE;
 
 	if (hdr->used_file_size < sizeof(struct mail_cache_header)) {
@@ -211,15 +206,6 @@
 	}
 
 	if (cache->mmap_base != NULL) {
-		if (cache->locks != 0) {
-			/* in the middle of transaction - write the changes */
-			if (msync(cache->mmap_base, cache->mmap_length,
-				  MS_SYNC) < 0) {
-				mail_cache_set_syscall_error(cache, "msync()");
-				return -1;
-			}
-		}
-
 		if (munmap(cache->mmap_base, cache->mmap_length) < 0)
 			mail_cache_set_syscall_error(cache, "munmap()");
 	} else {
@@ -234,7 +220,7 @@
 	cache->hdr = NULL;
 	cache->mmap_length = 0;
 
-	cache->mmap_base = mmap_rw_file(cache->fd, &cache->mmap_length);
+	cache->mmap_base = mmap_ro_file(cache->fd, &cache->mmap_length);
 	if (cache->mmap_base == MAP_FAILED) {
 		cache->mmap_base = NULL;
 		mail_cache_set_syscall_error(cache, "mmap()");
@@ -290,8 +276,6 @@
 
 void mail_cache_free(struct mail_cache *cache)
 {
-	i_assert(cache->trans_ctx == NULL);
-
 	mail_cache_file_close(cache);
 
 	pool_unref(cache->split_header_pool);
@@ -307,12 +291,11 @@
 	cache->never_cache_fields = never_cache_fields;
 }
 
-int mail_cache_lock(struct mail_cache *cache, int nonblock)
+int mail_cache_lock(struct mail_cache *cache)
 {
 	int i, ret;
 
-	if (cache->locks != 0)
-		return 1;
+	i_assert(!cache->locked);
 
 	if (MAIL_CACHE_IS_UNUSABLE(cache))
 		return 0;
@@ -324,26 +307,14 @@
 	}
 
 	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 (ret <= 0)
+		if ((ret = file_wait_lock(cache->fd, F_WRLCK)) <= 0) {
+			mail_cache_set_syscall_error(cache, "file_wait_lock()");
 			break;
+		}
+		cache->locked = TRUE;
 
 		if (cache->hdr->file_seq == cache->index->hdr->cache_file_seq) {
 			/* got it */
-			cache->locks++;
 			break;
 		}
 
@@ -353,21 +324,50 @@
 			return ret;
 		ret = 0;
 	}
+
+	if (ret > 0)
+		cache->hdr_copy = *cache->hdr;
+
 	return ret;
 }
 
-void mail_cache_unlock(struct mail_cache *cache)
+static void mail_cache_update_need_compress(struct mail_cache *cache)
 {
-	if (--cache->locks > 0)
-		return;
+	const struct mail_cache_header *hdr = cache->hdr;
+	unsigned int cont_percentage;
+	uoff_t max_del_space;
 
-	if (file_wait_lock(cache->fd, F_UNLCK) <= 0)
-		mail_cache_set_syscall_error(cache, "file_wait_lock(F_UNLCK)");
+        cont_percentage = hdr->continued_record_count * 100 /
+		cache->index->map->records_count;
+	if (cont_percentage >= COMPRESS_CONTINUED_PERCENTAGE &&
+	    hdr->used_file_size >= COMPRESS_MIN_SIZE) {
+		/* too many continued rows, compress */
+		cache->need_compress = TRUE;
+	}
+
+	/* see if we've reached the max. deleted space in file */
+	max_del_space = hdr->used_file_size / 100 * COMPRESS_PERCENTAGE;
+	if (hdr->deleted_space >= max_del_space &&
+	    hdr->used_file_size >= COMPRESS_MIN_SIZE)
+		cache->need_compress = TRUE;
 }
 
-int mail_cache_is_locked(struct mail_cache *cache)
+void mail_cache_unlock(struct mail_cache *cache)
 {
-	return cache->locks > 0;
+	i_assert(cache->locked);
+
+	cache->locked = FALSE;
+
+	if (cache->hdr_modified) {
+		cache->hdr_modified = FALSE;
+		if (pwrite_full(cache->fd, &cache->hdr_copy,
+				sizeof(cache->hdr_copy), 0) < 0)
+			mail_cache_set_syscall_error(cache, "pwrite_full()");
+                mail_cache_update_need_compress(cache);
+	}
+
+	if (file_wait_lock(cache->fd, F_UNLCK) <= 0)
+		mail_cache_set_syscall_error(cache, "file_wait_lock(F_UNLCK)");
 }
 
 struct mail_cache_view *

Index: mail-cache.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-cache.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- mail-cache.h	4 Jul 2004 14:26:22 -0000	1.15
+++ mail-cache.h	4 Jul 2004 20:00:47 -0000	1.16
@@ -83,30 +83,14 @@
 /* Compress cache file. */
 int mail_cache_compress(struct mail_cache *cache, struct mail_index_view *view);
 
-/* 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);
-void mail_cache_unlock(struct mail_cache *cache);
-
-/* Returns TRUE if cache file is locked. */
-int mail_cache_is_locked(struct mail_cache *cache);
-
 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);
 
-/* 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(). */
-int mail_cache_transaction_begin(struct mail_cache_view *view, int nonblock,
-				 struct mail_index_transaction *t,
-				 struct mail_cache_transaction_ctx **ctx_r);
-int mail_cache_transaction_commit(struct mail_cache_transaction_ctx *ctx);
-void mail_cache_transaction_rollback(struct mail_cache_transaction_ctx *ctx);
-
-void mail_cache_transaction_end(struct mail_cache_transaction_ctx *ctx);
+/* Get index transaction specific cache transaction. */
+struct mail_cache_transaction_ctx *
+mail_cache_get_transaction(struct mail_cache_view *view,
+			   struct mail_index_transaction *t);
 
 /* Return NULL-terminated list of headers for given index, or NULL if
    header index isn't used. */
@@ -117,14 +101,10 @@
 				 unsigned int idx, const char *const headers[]);
 
 /* 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. */
-int mail_cache_add(struct mail_cache_transaction_ctx *ctx, uint32_t seq,
-		   enum mail_cache_field field,
-		   const void *data, size_t data_size);
-
-/* Mark the given record deleted. */
-int mail_cache_delete(struct mail_cache_transaction_ctx *ctx, uint32_t seq);
+   must be exactly the expected size. */
+void mail_cache_add(struct mail_cache_transaction_ctx *ctx, uint32_t seq,
+		    enum mail_cache_field field,
+		    const void *data, size_t data_size);
 
 /* Return all fields that are currently cached for record. */
 enum mail_cache_field

Index: mail-index-private.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index-private.h,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- mail-index-private.h	24 Jun 2004 11:10:41 -0000	1.22
+++ mail-index-private.h	4 Jul 2004 20:00:47 -0000	1.23
@@ -133,7 +133,8 @@
 void mail_index_reset_cache(struct mail_index_transaction *t,
 			    uint32_t new_file_seq);
 void mail_index_update_cache(struct mail_index_transaction *t,
-			     uint32_t seq, uint32_t offset);
+			     uint32_t seq, uint32_t offset,
+			     uint32_t *old_offset_r);
 
 int mail_index_fix_header(struct mail_index *index, struct mail_index_map *map,
 			  struct mail_index_header *hdr, const char **error_r);

Index: mail-index-sync-update.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index-sync-update.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- mail-index-sync-update.c	4 Jul 2004 14:26:22 -0000	1.33
+++ mail-index-sync-update.c	4 Jul 2004 20:00:47 -0000	1.34
@@ -57,6 +57,18 @@
 		hdr->first_deleted_uid_lowwater = rec->uid;
 }
 
+static void mail_index_sync_cache_expunge(struct mail_index_sync_ctx *sync_ctx,
+					  uoff_t cache_offset)
+{
+	if (!sync_ctx->cache_locked) {
+		if (mail_cache_lock(sync_ctx->view->index->cache) <= 0)
+			return;
+		sync_ctx->cache_locked = TRUE;
+	}
+
+	(void)mail_cache_delete(sync_ctx->index->cache, cache_offset);
+}
+
 static int sync_expunge(const struct mail_transaction_expunge *e, void *context)
 {
         struct mail_index_sync_ctx *sync_ctx = context;
@@ -78,6 +90,11 @@
 	for (seq = seq1; seq <= seq2; seq++) {
                 rec = MAIL_INDEX_MAP_IDX(map, seq-1);
 		mail_index_header_update_counts(hdr, rec->flags, 0);
+		
+		if (rec->cache_offset != 0) {
+			mail_index_sync_cache_expunge(sync_ctx,
+						      rec->cache_offset);
+		}
 	}
 
 	/* @UNSAFE */
@@ -225,7 +242,7 @@
 	if (rec->cache_offset != 0) {
 		/* we'll need to link the old and new cache records */
 		if (!sync_ctx->cache_locked) {
-			if (mail_cache_lock(view->index->cache, FALSE) <= 0)
+			if (mail_cache_lock(view->index->cache) <= 0)
 				return -1;
 			sync_ctx->cache_locked = TRUE;
 		}

Index: mail-index-transaction-private.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index-transaction-private.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- mail-index-transaction-private.h	3 Jul 2004 10:57:52 -0000	1.8
+++ mail-index-transaction-private.h	4 Jul 2004 20:00:47 -0000	1.9
@@ -19,11 +19,13 @@
 
 	unsigned char hdr_change[sizeof(struct mail_index_header)];
 	unsigned char hdr_mask[sizeof(struct mail_index_header)];
-	uint32_t new_cache_file_seq;
 
 	buffer_t *extra_rec_updates[MAIL_INDEX_MAX_EXTRA_RECORDS];
 
+	uint32_t new_cache_file_seq;
 	buffer_t *cache_updates;
+        struct mail_cache_transaction_ctx *cache_trans_ctx;
+
 	unsigned int hide_transaction:1;
 	unsigned int hdr_changed:1;
 };

Index: mail-index-transaction.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index-transaction.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- mail-index-transaction.c	3 Jul 2004 10:57:53 -0000	1.16
+++ mail-index-transaction.c	4 Jul 2004 20:00:47 -0000	1.17
@@ -8,6 +8,7 @@
 #include "buffer.h"
 #include "mail-index-view-private.h"
 #include "mail-transaction-log.h"
+#include "mail-cache-private.h"
 #include "mail-index-transaction-private.h"
 
 #include <stddef.h>
@@ -124,10 +125,15 @@
 	int ret;
 
 	if (mail_index_view_is_inconsistent(t->view)) {
-		mail_index_transaction_unref(t);
+		mail_index_transaction_rollback(t);
 		return -1;
 	}
 
+	if (t->cache_trans_ctx != NULL) {
+		mail_cache_transaction_commit(t->cache_trans_ctx);
+                t->cache_trans_ctx = NULL;
+	}
+
 	if (t->last_update.uid1 != 0)
 		mail_index_transaction_add_last(t);
 
@@ -144,6 +150,10 @@
 
 void mail_index_transaction_rollback(struct mail_index_transaction *t)
 {
+	if (t->cache_trans_ctx != NULL) {
+		mail_cache_transaction_rollback(t->cache_trans_ctx);
+                t->cache_trans_ctx = NULL;
+	}
         mail_index_transaction_unref(t);
 }
 
@@ -499,8 +509,9 @@
 		      &update, sizeof(update));
 }
 
-static void mail_index_update_seq_buffer(buffer_t **buffer, uint32_t seq,
-					 const void *record, size_t record_size)
+static int mail_index_update_seq_buffer(buffer_t **buffer, uint32_t seq,
+					const void *record, size_t record_size,
+					void *old_record)
 {
 	unsigned int idx, left_idx, right_idx;
 	void *data;
@@ -530,8 +541,12 @@
 				right_idx = idx;
 			else {
 				/* already there, update */
+				if (old_record != NULL) {
+					memcpy(old_record, seq_p+1,
+					       record_size);
+				}
 				memcpy(seq_p+1, record, record_size);
-				return;
+				return TRUE;
 			}
 		}
 	}
@@ -545,6 +560,7 @@
 
 	*seq_p = seq;
 	memcpy(seq_p+1, record, record_size);
+	return FALSE;
 }
 
 void mail_index_reset_cache(struct mail_index_transaction *t,
@@ -554,17 +570,21 @@
 }
 
 void mail_index_update_cache(struct mail_index_transaction *t,
-			     uint32_t seq, uint32_t offset)
+			     uint32_t seq, uint32_t offset,
+			     uint32_t *old_offset_r)
 {
 	struct mail_index_record *rec;
 
 	if (seq >= t->first_new_seq) {
 		/* just appended message, modify it directly */
 		rec = mail_index_transaction_lookup(t, seq);
+		*old_offset_r = rec->cache_offset;
 		rec->cache_offset = offset;
 	} else {
-		mail_index_update_seq_buffer(&t->cache_updates, seq,
-					     &offset, sizeof(offset));
+		if (!mail_index_update_seq_buffer(&t->cache_updates, seq,
+						  &offset, sizeof(offset),
+						  old_offset_r))
+			*old_offset_r = 0;
 	}
 }
 
@@ -585,7 +605,7 @@
 		       data, index->extra_records[data_id].size);
 	} else {
 		mail_index_update_seq_buffer(&t->extra_rec_updates[data_id],
-			seq, data, index->extra_records[data_id].size);
+			seq, data, index->extra_records[data_id].size, NULL);
 	}
 }
 



More information about the dovecot-cvs mailing list