[dovecot-cvs] dovecot/src/lib-index mail-cache-lookup.c, 1.12, 1.13 mail-cache-private.h, 1.8, 1.9 mail-cache-transaction.c, 1.12, 1.13 mail-index-private.h, 1.25, 1.26 mail-index-transaction.c, 1.18, 1.19

cras at dovecot.org cras at dovecot.org
Sat Jul 10 14:16:07 EEST 2004


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

Modified Files:
	mail-cache-lookup.c mail-cache-private.h 
	mail-cache-transaction.c mail-index-private.h 
	mail-index-transaction.c 
Log Message:
Cache fixes. Lookups now look into transactions too.



Index: mail-cache-lookup.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-cache-lookup.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- mail-cache-lookup.c	8 Jul 2004 20:26:15 -0000	1.12
+++ mail-cache-lookup.c	10 Jul 2004 11:16:05 -0000	1.13
@@ -139,6 +139,7 @@
 	if (cache_rec->size > CACHE_PREFETCH) {
 		if (mail_cache_map(cache, offset, cache_rec->size) < 0)
 			return NULL;
+		cache_rec = CACHE_RECORD(cache, offset);
 	}
 
 	if (offset + cache_rec->size > cache->mmap_length) {
@@ -171,67 +172,81 @@
 	return 0;
 }
 
-int mail_cache_foreach(struct mail_cache_view *view, uint32_t seq,
-		       int (*callback)(struct mail_cache_view *view,
-				       enum mail_cache_field field,
-				       const void *data, size_t data_size,
-				       void *context), void *context)
+static int
+mail_cache_foreach_rec(struct mail_cache_view *view,
+		       const struct mail_cache_record *cache_rec,
+		       mail_cache_foreach_callback_t *callback, void *context)
 {
-	const struct mail_cache_record *cache_rec;
 	size_t pos, next_pos, max_size, data_size;
-	uint32_t offset, field;
+	uint32_t field;
 	int ret;
 
-        if (MAIL_CACHE_IS_UNUSABLE(view->cache))
-		return 0;
+	max_size = cache_rec->size;
+	if (max_size < sizeof(*cache_rec) + sizeof(uint32_t)*2) {
+		mail_cache_set_corrupted(view->cache,
+					 "record has invalid size");
+		return -1;
+	}
+	max_size -= sizeof(uint32_t);
 
-	if ((ret = mail_cache_lookup_offset(view, seq, &offset)) <= 0)
-		return ret;
+	for (pos = sizeof(*cache_rec); pos < max_size; ) {
+		field = *((const uint32_t *)CONST_PTR_OFFSET(cache_rec, pos));
+		pos += sizeof(uint32_t);
 
-	cache_rec = mail_cache_get_record(view->cache, offset);
-	while (cache_rec != NULL) {
-		max_size = cache_rec->size;
-		if (max_size < sizeof(*cache_rec) + sizeof(uint32_t)*2) {
+		data_size = mail_cache_field_sizes[field];
+		if (data_size == (unsigned int)-1) {
+			data_size = *((const uint32_t *)
+				      CONST_PTR_OFFSET(cache_rec, pos));
+			pos += sizeof(uint32_t);
+		}
+
+		next_pos = pos + ((data_size + 3) & ~3);
+		if (next_pos > cache_rec->size) {
 			mail_cache_set_corrupted(view->cache,
-				"record has invalid size");
+				"Record continues outside it's allocated size");
 			return -1;
 		}
-		max_size -= sizeof(uint32_t);
 
-		for (pos = sizeof(*cache_rec); pos < max_size; ) {
-			field = *((const uint32_t *)
-				  CONST_PTR_OFFSET(cache_rec, pos));
-			pos += sizeof(uint32_t);
+		ret = callback(view, field, CONST_PTR_OFFSET(cache_rec, pos),
+			       data_size, context);
+		if (ret <= 0)
+			return ret;
 
-			data_size = mail_cache_field_sizes[field];
-			if (data_size == (unsigned int)-1) {
-				data_size = *((const uint32_t *)
-					      CONST_PTR_OFFSET(cache_rec, pos));
-				pos += sizeof(uint32_t);
-			}
+		pos = next_pos;
+	}
+	return 1;
+}
 
-			next_pos = pos + ((data_size + 3) & ~3);
-			if (next_pos > cache_rec->size) {
-				mail_cache_set_corrupted(view->cache,
-					"Record continues outside it's "
-					"allocated size");
-				return -1;
-			}
+int mail_cache_foreach(struct mail_cache_view *view, uint32_t seq,
+                       mail_cache_foreach_callback_t *callback, void *context)
+{
+	const struct mail_cache_record *cache_rec;
+	uint32_t offset;
+	int ret;
 
-			ret = callback(view, field,
-				       CONST_PTR_OFFSET(cache_rec, pos),
-				       data_size, context);
-			if (ret <= 0)
-				return ret;
+        if (MAIL_CACHE_IS_UNUSABLE(view->cache))
+		return 0;
 
-			pos = next_pos;
-		}
+	if ((ret = mail_cache_lookup_offset(view, seq, &offset)) <= 0)
+		return ret;
+
+	cache_rec = mail_cache_get_record(view->cache, offset);
+	while (cache_rec != NULL) {
+		ret = mail_cache_foreach_rec(view, cache_rec,
+					     callback, context);
+		if (ret <= 0)
+			return ret;
 		cache_rec = mail_cache_get_record(view->cache,
 						  cache_rec->prev_offset);
 	}
 
-	if (view->transaction != NULL) {
-		// FIXME: update
+	if (view->trans_seq1 <= seq && view->trans_seq2 >= seq &&
+	    mail_cache_transaction_lookup(view->transaction, seq, &offset)) {
+		cache_rec = mail_cache_get_record(view->cache, offset);
+		if (cache_rec != NULL) {
+			return mail_cache_foreach_rec(view, cache_rec,
+						      callback, context);
+		}
 	}
 	return 1;
 }

Index: mail-cache-private.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-cache-private.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- mail-cache-private.h	8 Jul 2004 20:26:15 -0000	1.8
+++ mail-cache-private.h	10 Jul 2004 11:16:05 -0000	1.9
@@ -102,10 +102,17 @@
 	struct mail_index_view *view;
 
 	struct mail_cache_transaction_ctx *transaction;
+	uint32_t trans_seq1, trans_seq2;
+
 	char cached_exists[32];
 	uint32_t cached_exists_seq;
 };
 
+typedef int mail_cache_foreach_callback_t(struct mail_cache_view *view,
+					  enum mail_cache_field field,
+					  const void *data, size_t data_size,
+					  void *context);
+
 extern unsigned int mail_cache_field_sizes[32];
 extern enum mail_cache_field mail_cache_header_fields[MAIL_CACHE_HEADERS_COUNT];
 
@@ -126,14 +133,14 @@
 mail_cache_get_record(struct mail_cache *cache, uint32_t offset);
 
 int mail_cache_foreach(struct mail_cache_view *view, uint32_t seq,
-		       int (*callback)(struct mail_cache_view *view,
-				       enum mail_cache_field field,
-				       const void *data, size_t data_size,
-				       void *context), void *context);
+		       mail_cache_foreach_callback_t *callback, void *context);
 
 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_transaction_lookup(struct mail_cache_transaction_ctx *ctx,
+				  uint32_t seq, uint32_t *offset_r);
+
 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);

Index: mail-cache-transaction.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-cache-transaction.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- mail-cache-transaction.c	8 Jul 2004 20:26:15 -0000	1.12
+++ mail-cache-transaction.c	10 Jul 2004 11:16:05 -0000	1.13
@@ -27,9 +27,6 @@
 	uint32_t reserved_space_offset, reserved_space;
 	uint32_t last_grow_size;
 
-	uint32_t first_seq, last_seq;
-	enum mail_cache_field fields[32];
-
 	unsigned int changes:1;
 };
 
@@ -65,6 +62,7 @@
 static void mail_cache_transaction_free(struct mail_cache_transaction_ctx *ctx)
 {
 	ctx->view->transaction = NULL;
+	ctx->view->trans_seq1 = ctx->view->trans_seq2 = 0;
 
 	buffer_free(ctx->cache_data);
 	buffer_free(ctx->cache_data_seq);
@@ -489,21 +487,24 @@
 	size_t size;
 	unsigned int i;
 
-	mail_cache_transaction_free_space(ctx);
+	if (mail_cache_lock(cache) > 0) {
+		mail_cache_transaction_free_space(ctx);
 
-	buf = buffer_get_data(ctx->reservations, &size);
-	i_assert(size % sizeof(uint32_t)*2 == 0);
-	size /= sizeof(*buf);
+		buf = buffer_get_data(ctx->reservations, &size);
+		i_assert(size % sizeof(uint32_t)*2 == 0);
+		size /= sizeof(*buf);
 
-	if (size > 0) {
-		/* free flushed data as well. do it from end to beginning so
-		   we have a better chance of updating used_file_size instead
-		   of adding holes */
-		do {
-			size -= 2;
-			mail_cache_free_space(ctx->cache, buf[size],
-					      buf[size+1]);
-		} while (size > 0);
+		if (size > 0) {
+			/* free flushed data as well. do it from end to
+			   beginning so we have a better chance of updating
+			   used_file_size instead of adding holes */
+			do {
+				size -= 2;
+				mail_cache_free_space(ctx->cache, buf[size],
+						      buf[size+1]);
+			} while (size > 0);
+		}
+		mail_cache_unlock(cache);
 	}
 
 	/* make sure we don't cache the headers */
@@ -622,12 +623,10 @@
 
 		/* remember roughly what we have modified, so cache lookups can
 		   look into transactions to see changes. */
-		if (seq < ctx->first_seq || ctx->first_seq == 0)
-			ctx->first_seq = seq;
-		if (seq > ctx->last_seq)
-			ctx->last_seq = seq;
-		ctx->view->cached_exists[field] = TRUE;
-		ctx->fields[field] = TRUE;
+		if (seq < ctx->view->trans_seq1 || ctx->view->trans_seq1 == 0)
+			ctx->view->trans_seq1 = seq;
+		if (seq > ctx->view->trans_seq2)
+			ctx->view->trans_seq2 = seq;
 	}
 
 	full_size = (data_size + 3) & ~3;
@@ -658,6 +657,13 @@
 	return -1;
 }
 
+int mail_cache_transaction_lookup(struct mail_cache_transaction_ctx *ctx,
+				  uint32_t seq, uint32_t *offset_r)
+{
+	return mail_index_update_cache_lookup(ctx->trans, seq, offset_r);
+}
+
+
 int mail_cache_link(struct mail_cache *cache, uint32_t old_offset,
 		    uint32_t new_offset)
 {

Index: mail-index-private.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index-private.h,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- mail-index-private.h	8 Jul 2004 18:57:17 -0000	1.25
+++ mail-index-private.h	10 Jul 2004 11:16:05 -0000	1.26
@@ -136,6 +136,8 @@
 void mail_index_update_cache(struct mail_index_transaction *t, uint32_t seq,
 			     uint32_t file_seq, uint32_t offset,
 			     uint32_t *old_offset_r);
+int mail_index_update_cache_lookup(struct mail_index_transaction *t,
+				   uint32_t seq, uint32_t *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-transaction.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index-transaction.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- mail-index-transaction.c	4 Jul 2004 21:56:12 -0000	1.18
+++ mail-index-transaction.c	10 Jul 2004 11:16:05 -0000	1.19
@@ -509,20 +509,18 @@
 		      &update, sizeof(update));
 }
 
-static int mail_index_update_seq_buffer(buffer_t **buffer, uint32_t seq,
-					const void *record, size_t record_size,
-					void *old_record)
+static int
+mail_index_seq_buffer_lookup(buffer_t *buffer, uint32_t seq,
+			     size_t record_size, size_t *pos_r)
 {
 	unsigned int idx, left_idx, right_idx;
 	void *data;
 	uint32_t full_record_size, *seq_p;
 	size_t size;
 
-	full_record_size = record_size + sizeof(uint32_t);
+	full_record_size = record_size + sizeof(seq);
 
-	if (*buffer == NULL)
-		*buffer = buffer_create_dynamic(default_pool, 1024, (size_t)-1);
-	data = buffer_get_modifyable_data(*buffer, &size);
+	data = buffer_get_modifyable_data(buffer, &size);
 
 	/* we're probably appending it, check */
 	if (size == 0)
@@ -540,27 +538,46 @@
 			else if (*seq_p > seq)
 				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);
+				*pos_r = idx * full_record_size;
 				return TRUE;
 			}
 		}
 	}
 
-	idx *= full_record_size;
-	if (idx != size) {
-		buffer_copy(*buffer, idx + full_record_size,
-			    *buffer, idx, (size_t)-1);
+	*pos_r = idx * full_record_size;
+	return FALSE;
+}
+
+static int mail_index_update_seq_buffer(buffer_t **buffer, uint32_t seq,
+					const void *record, size_t record_size,
+					void *old_record)
+{
+	void *p;
+	size_t pos;
+
+	if (*buffer == NULL) {
+		*buffer = buffer_create_dynamic(default_pool, 1024, (size_t)-1);
+		buffer_append(*buffer, &seq, sizeof(seq));
+		buffer_append(*buffer, record, record_size);
+		return FALSE;
 	}
-	seq_p = buffer_get_space_unsafe(*buffer, idx, full_record_size);
 
-	*seq_p = seq;
-	memcpy(seq_p+1, record, record_size);
-	return FALSE;
+	if (mail_index_seq_buffer_lookup(*buffer, seq, record_size, &pos)) {
+		/* already there, update */
+		p = buffer_get_space_unsafe(*buffer, pos + sizeof(seq),
+					    record_size);
+		if (old_record != NULL)
+			memcpy(old_record, p, record_size);
+		memcpy(p, record, record_size);
+		return TRUE;
+	} else {
+		/* insert */
+		buffer_copy(*buffer, pos + sizeof(seq) + record_size,
+			    *buffer, pos, (size_t)-1);
+		buffer_write(*buffer, pos, &seq, sizeof(seq));
+		buffer_write(*buffer, pos + sizeof(seq), record, record_size);
+		return FALSE;
+	}
 }
 
 static void
@@ -614,6 +631,25 @@
 	}
 }
 
+int mail_index_update_cache_lookup(struct mail_index_transaction *t,
+				   uint32_t seq, uint32_t *offset_r)
+{
+	const void *p;
+	size_t pos;
+
+	if (t->cache_updates == NULL)
+		return FALSE;
+
+	if (!mail_index_seq_buffer_lookup(t->cache_updates, seq,
+					  sizeof(*offset_r), &pos))
+		return FALSE;
+
+	p = buffer_get_data(t->cache_updates, NULL);
+	memcpy(offset_r, CONST_PTR_OFFSET(p, pos + sizeof(*offset_r)),
+	       sizeof(*offset_r));
+	return TRUE;
+}
+
 void mail_index_update_extra_rec(struct mail_index_transaction *t,
 				 uint32_t seq, uint32_t data_id,
 				 const void *data)



More information about the dovecot-cvs mailing list