changeset 2279:ed0bb4c12f03 HEAD

Cache API updates. Don't return direct pointers to mmaped cache file anymore.
author Timo Sirainen <tss@iki.fi>
date Mon, 05 Jul 2004 00:07:43 +0300
parents 675ef825829e
children d1318d47cd47
files src/lib-index/mail-cache-compress.c src/lib-index/mail-cache-lookup.c src/lib-index/mail-cache.h src/lib-storage/index/index-mail-headers.c src/lib-storage/index/index-mail.c src/lib-storage/index/index-mail.h
diffstat 6 files changed, 110 insertions(+), 129 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-cache-compress.c	Sun Jul 04 23:11:04 2004 +0300
+++ b/src/lib-index/mail-cache-compress.c	Mon Jul 05 00:07:43 2004 +0300
@@ -16,14 +16,15 @@
 	enum mail_cache_field cached_fields, field;
 	struct mail_cache_record cache_rec;
 	buffer_t *buffer;
+	pool_t pool;
 	const void *data;
 	size_t size, pos;
-	uint32_t size32;
+	uint32_t *p, size32 = 0;
 	int i;
 
 	memset(&cache_rec, 0, sizeof(cache_rec));
-	buffer = buffer_create_dynamic(pool_datastack_create(),
-				       4096, (size_t)-1);
+	pool = pool_datastack_create();
+	buffer = buffer_create_dynamic(pool, 4096, (size_t)-1);
 
 	cached_fields = orig_cached_fields & ~MAIL_CACHE_HEADERS_MASK;
 	buffer_append(buffer, &cache_rec, sizeof(cache_rec));
@@ -31,18 +32,24 @@
 		if ((cached_fields & field) == 0)
 			continue;
 
-		if (!mail_cache_lookup_field(view, seq, field, &data, &size)) {
+		pos = buffer_get_used_size(buffer);
+		if ((field & MAIL_CACHE_FIXED_MASK) == 0)
+			buffer_append(buffer, &size32, sizeof(size32));
+
+		if (!mail_cache_lookup_field(view, buffer, seq, field)) {
 			cached_fields &= ~field;
+			buffer_set_used_size(buffer, pos);
 			continue;
 		}
 
-		size32 = (uint32_t)size;
+		if ((field & MAIL_CACHE_FIXED_MASK) == 0) {
+			p = buffer_get_space_unsafe(buffer, pos,
+						    sizeof(uint32_t));
+			*p = (uint32_t)size;
+		}
 
-		if ((field & MAIL_CACHE_FIXED_MASK) == 0)
-			buffer_append(buffer, &size32, sizeof(size32));
-		buffer_append(buffer, data, size);
-		if ((size32 & 3) != 0)
-			buffer_append(buffer, null4, 4 - (size32 & 3));
+		if ((size & 3) != 0)
+			buffer_append(buffer, null4, 4 - (size & 3));
 	}
 
 	/* now merge all the headers if we have them all */
@@ -53,15 +60,15 @@
 
 		for (i = 0; i <= header_idx; i++) {
 			field = mail_cache_header_fields[i];
-			if (mail_cache_lookup_field(view, seq, field,
-						    &data, &size) && size > 1) {
-				size--; /* terminating \0 */
-				buffer_append(buffer, data, size);
-				size32 += size;
+			if (mail_cache_lookup_field(view, buffer, seq, field)) {
+				/* remove terminating \0 */
+				buffer_set_used_size(buffer,
+					buffer_get_used_size(buffer)-1);
 			}
 		}
 		buffer_append(buffer, null4, 1);
-		size32++;
+
+		size32 = buffer_get_used_size(buffer) - pos;
 		if ((size32 & 3) != 0)
 			buffer_append(buffer, null4, 4 - (size32 & 3));
 		buffer_write(buffer, pos, &size32, sizeof(size32));
--- a/src/lib-index/mail-cache-lookup.c	Sun Jul 04 23:11:04 2004 +0300
+++ b/src/lib-index/mail-cache-lookup.c	Mon Jul 05 00:07:43 2004 +0300
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "buffer.h"
+#include "str.h"
 #include "mail-cache-private.h"
 
 #define CACHE_PREFETCH 1024
@@ -204,8 +205,7 @@
 
 static int cache_get_field(struct mail_cache *cache,
 			   const struct mail_cache_record *cache_rec,
-			   enum mail_cache_field field,
-			   const void **data_r, size_t *size_r)
+			   enum mail_cache_field field, buffer_t *dest_buf)
 {
 	unsigned int mask;
 	uint32_t data_size;
@@ -247,8 +247,9 @@
 							 "Field size is 0");
 				return FALSE;
 			}
-			*data_r = CONST_PTR_OFFSET(cache_rec, offset);
-			*size_r = data_size;
+			buffer_append(dest_buf,
+				      CONST_PTR_OFFSET(cache_rec, offset),
+				      data_size);
 			return TRUE;
 		}
 		offset = prev_offset;
@@ -258,9 +259,8 @@
 	return FALSE;
 }
 
-int mail_cache_lookup_field(struct mail_cache_view *view, uint32_t seq,
-			    enum mail_cache_field field,
-			    const void **data_r, size_t *size_r)
+int mail_cache_lookup_field(struct mail_cache_view *view, buffer_t *dest_buf,
+			    uint32_t seq, enum mail_cache_field field)
 {
 	struct mail_cache_record *cache_rec;
 
@@ -270,7 +270,7 @@
 	while (cache_rec != NULL) {
 		if ((cache_rec->fields & field) != 0) {
 			return cache_get_field(view->cache, cache_rec, field,
-					       data_r, size_r);
+					       dest_buf);
 		}
 		cache_rec = mail_cache_get_record(view->cache,
 						  cache_rec->prev_offset);
@@ -279,45 +279,25 @@
 	return FALSE;
 }
 
-const char *
-mail_cache_lookup_string_field(struct mail_cache_view *view, uint32_t seq,
-			       enum mail_cache_field field)
+int mail_cache_lookup_string_field(struct mail_cache_view *view, string_t *dest,
+				   uint32_t seq, enum mail_cache_field field)
 {
-	const void *data;
-	size_t size;
+	size_t old_size, new_size;
 
 	i_assert((field & MAIL_CACHE_STRING_MASK) != 0);
 
-	if (!mail_cache_lookup_field(view, seq, field, &data, &size))
-		return NULL;
+	old_size = str_len(dest);
+	if (!mail_cache_lookup_field(view, dest, seq, field))
+		return FALSE;
 
-	if (((const char *)data)[size-1] != '\0') {
+	new_size = str_len(dest);
+	if (old_size == new_size ||
+	    str_data(dest)[new_size-1] != '\0') {
 		mail_cache_set_corrupted(view->cache,
 			"String field %x doesn't end with NUL", field);
-		return NULL;
+		return FALSE;
 	}
-	return data;
-}
-
-int mail_cache_copy_fixed_field(struct mail_cache_view *view, uint32_t seq,
-				enum mail_cache_field field,
-				void *buffer, size_t buffer_size)
-{
-	const void *data;
-	size_t size;
-
-	i_assert((field & MAIL_CACHE_FIXED_MASK) != 0);
-
-	if (!mail_cache_lookup_field(view, seq, field, &data, &size))
-		return FALSE;
-
-	if (buffer_size != size) {
-		i_panic("cache: fixed field %x wrong size "
-			"(%"PRIuSIZE_T" vs %"PRIuSIZE_T")",
-			field, size, buffer_size);
-	}
-
-	memcpy(buffer, data, buffer_size);
+	str_truncate(dest, new_size-1);
 	return TRUE;
 }
 
--- a/src/lib-index/mail-cache.h	Sun Jul 04 23:11:04 2004 +0300
+++ b/src/lib-index/mail-cache.h	Mon Jul 05 00:07:43 2004 +0300
@@ -113,21 +113,12 @@
 /* Set data_r and size_r to point to wanted field in cache file.
    Returns TRUE if field was found. If field contains multiple fields,
    first one found is returned. This is mostly useful for finding headers. */
-int mail_cache_lookup_field(struct mail_cache_view *view, uint32_t seq,
-			    enum mail_cache_field field,
-			    const void **data_r, size_t *size_r);
+int mail_cache_lookup_field(struct mail_cache_view *view, buffer_t *dest_buf,
+			    uint32_t seq, enum mail_cache_field field);
 
 /* Return string field. */
-const char *
-mail_cache_lookup_string_field(struct mail_cache_view *view, uint32_t seq,
-			       enum mail_cache_field field);
-
-/* Copy fixed size field to given buffer. buffer_size must be exactly the
-   expected size. The result will be converted to host byte order.
-   Returns TRUE if field was found. */
-int mail_cache_copy_fixed_field(struct mail_cache_view *view, uint32_t seq,
-				enum mail_cache_field field,
-				void *buffer, size_t buffer_size);
+int mail_cache_lookup_string_field(struct mail_cache_view *view, string_t *dest,
+				   uint32_t seq, enum mail_cache_field field);
 
 /* Mark given field as missing, ie. it should be cached when possible. */
 void mail_cache_mark_missing(struct mail_cache_view *view, uint32_t uid,
--- a/src/lib-storage/index/index-mail-headers.c	Sun Jul 04 23:11:04 2004 +0300
+++ b/src/lib-storage/index/index-mail-headers.c	Mon Jul 05 00:07:43 2004 +0300
@@ -419,30 +419,29 @@
 	struct message_header_parser_ctx *hdr_ctx;
 	struct message_header_line *hdr;
 	struct istream *istream;
-	const char *str, *const *idx_headers;
+	const char *const *idx_headers;
+	string_t *str;
 
-	t_push();
 	if (idx < data->header_data_cached) {
 		/* it's already in header_data. */
-		istream = i_stream_create_from_data(pool_datastack_create(),
+		istream = i_stream_create_from_data(mail->pool,
 						    str_data(data->header_data),
 						    str_len(data->header_data));
 		/* we might be parsing a bit more.. */
 		idx = data->header_data_cached-1;
 		data->header_stream = istream;
 	} else {
-		str = mail_cache_lookup_string_field(
-			mail->trans->cache_view, data->seq,
-			mail_cache_header_fields[idx]);
-		if (str == NULL) {
+		str = str_new(mail->pool, 32);
+		if (!mail_cache_lookup_string_field(
+				mail->trans->cache_view, str, data->seq,
+				mail_cache_header_fields[idx])) {
 			/* broken - we expected the header to exist */
-			t_pop();
 			return FALSE;
 		}
 
 		data->header_data_cached_partial = TRUE;
-		istream = i_stream_create_from_data(pool_datastack_create(),
-						    str, strlen(str));
+		istream = i_stream_create_from_data(mail->pool, str_data(str),
+						    str_len(str));
 	}
 
 	idx_headers = mail_cache_get_header_fields(mail->trans->cache_view,
@@ -450,7 +449,6 @@
 	if (idx_headers == NULL) {
 		mail_cache_set_corrupted(mail->ibox->cache,
 			"Headers %d names not found", idx);
-		t_pop();
 		return FALSE;
 	}
 
@@ -466,7 +464,6 @@
 
 	data->header_stream = NULL;
 	i_stream_unref(istream);
-	t_pop();
 
 	return TRUE;
 }
@@ -485,7 +482,7 @@
 int index_mail_parse_headers(struct index_mail *mail)
 {
 	struct index_mail_data *data = &mail->data;
-	const char *str, *const *headers;
+	const char *const *headers;
 	int idx, max;
 
 	if (data->stream == NULL) {
@@ -508,14 +505,12 @@
 		/* add all cached headers to beginning of header_data */
                 idx = data->header_data_cached; max = idx-1;
 		for (; idx < MAIL_CACHE_HEADERS_COUNT; idx++) {
-			str = mail_cache_lookup_string_field(
-				mail->trans->cache_view, mail->data.seq,
-				mail_cache_header_fields[idx]);
-			if (str == NULL)
+			if (!mail_cache_lookup_string_field(
+				mail->trans->cache_view, mail->data.header_data,
+				mail->data.seq, mail_cache_header_fields[idx]))
 				continue;
 
 			max = idx;
-			str_append(mail->data.header_data, str);
 		}
 		data->header_data_cached = max+1;
 		data->header_data_uncached_offset =
@@ -635,7 +630,7 @@
 	struct index_mail *mail = (struct index_mail *) _mail;
 	struct index_mail_data *data = &mail->data;
 	struct cached_header *hdr;
-	const char *const *tmp, *str;
+	const char *const *tmp;
 	int i, idx, all_saved;
 
 	i_assert(*minimum_fields != NULL);
@@ -652,13 +647,9 @@
 			trash_partial_headers(mail);
 		}
 		for (i = data->header_data_cached; i <= idx; i++) {
-			str = mail_cache_lookup_string_field(
-					mail->trans->cache_view, data->seq,
-					mail_cache_header_fields[i]);
-			if (str == NULL)
-				continue;
-
-			str_append(data->header_data, str);
+			(void)mail_cache_lookup_string_field(
+				mail->trans->cache_view, data->header_data,
+				data->seq, mail_cache_header_fields[i]);
 		}
 		data->header_data_cached = idx+1;
 		data->header_data_uncached_offset = str_len(data->header_data);
--- a/src/lib-storage/index/index-mail.c	Sun Jul 04 23:11:04 2004 +0300
+++ b/src/lib-storage/index/index-mail.c	Mon Jul 05 00:07:43 2004 +0300
@@ -18,9 +18,8 @@
 static struct message_part *get_cached_parts(struct index_mail *mail)
 {
 	struct message_part *part;
-	const void *part_data;
+	buffer_t *part_buf;
 	const char *error;
-	size_t part_size;
 
 	if ((mail->data.cached_fields & MAIL_CACHE_MESSAGEPART) == 0) {
 		mail_cache_mark_missing(mail->trans->cache_view, mail->data.seq,
@@ -28,14 +27,17 @@
 		return NULL;
 	}
 
-	if (!mail_cache_lookup_field(mail->trans->cache_view, mail->data.seq,
-				     MAIL_CACHE_MESSAGEPART,
-				     &part_data, &part_size)) {
+	part_buf = buffer_create_dynamic(pool_datastack_create(),
+					 128, (size_t)-1);
+	if (!mail_cache_lookup_field(mail->trans->cache_view, part_buf,
+				     mail->data.seq, MAIL_CACHE_MESSAGEPART)) {
 		/* unexpected - must be an error */
 		return NULL;
 	}
 
-	part = message_part_deserialize(mail->pool, part_data, part_size,
+	part = message_part_deserialize(mail->pool,
+					buffer_get_data(part_buf, NULL),
+					buffer_get_used_size(part_buf),
 					&error);
 	if (part == NULL) {
 		mail_cache_set_corrupted(mail->ibox->cache,
@@ -55,10 +57,10 @@
 	return part;
 }
 
-char *index_mail_get_cached_string(struct index_mail *mail,
-				   enum mail_cache_field field)
+const char *index_mail_get_cached_string(struct index_mail *mail,
+					 enum mail_cache_field field)
 {
-	const char *ret;
+	string_t *str;
 
 	if ((mail->data.cached_fields & field) == 0) {
 		mail_cache_mark_missing(mail->trans->cache_view,
@@ -66,9 +68,35 @@
 		return NULL;
 	}
 
-	ret = mail_cache_lookup_string_field(mail->trans->cache_view,
-					     mail->data.seq, field);
-	return p_strdup(mail->pool, ret);
+	str = str_new(mail->pool, 32);
+	if (!mail_cache_lookup_string_field(mail->trans->cache_view, str,
+					    mail->data.seq, field))
+		return NULL;
+
+	return str_c(str);
+}
+
+static int index_mail_get_fixed_field(struct index_mail *mail,
+				      enum mail_cache_field field,
+				      void *data, size_t data_size)
+{
+	buffer_t *buf;
+	int ret;
+
+	t_push();
+	buf = buffer_create_data(pool_datastack_create(), data, data_size);
+	if (!mail_cache_lookup_field(mail->trans->cache_view, buf,
+				     mail->data.seq, field)) {
+		mail_cache_mark_missing(mail->trans->cache_view,
+					mail->data.seq, field);
+		ret = FALSE;
+	} else {
+		i_assert(buffer_get_used_size(buf) == data_size);
+		ret = TRUE;
+	}
+	t_pop();
+
+	return ret;
 }
 
 uoff_t index_mail_get_cached_uoff_t(struct index_mail *mail,
@@ -76,13 +104,8 @@
 {
 	uoff_t uoff;
 
-	if (!mail_cache_copy_fixed_field(mail->trans->cache_view,
-					 mail->data.seq, field,
-					 &uoff, sizeof(uoff))) {
-		mail_cache_mark_missing(mail->trans->cache_view,
-					mail->data.seq, field);
+	if (!index_mail_get_fixed_field(mail, field, &uoff, sizeof(uoff)))
 		uoff = (uoff_t)-1;
-	}
 
 	return uoff;
 }
@@ -96,28 +119,17 @@
 {
 	time_t t;
 
-	if (!mail_cache_copy_fixed_field(mail->trans->cache_view,
-					 mail->data.seq,
-					 MAIL_CACHE_RECEIVED_DATE,
-					 &t, sizeof(t))) {
-		mail_cache_mark_missing(mail->trans->cache_view, mail->data.seq,
-					MAIL_CACHE_RECEIVED_DATE);
+	if (!index_mail_get_fixed_field(mail, MAIL_CACHE_RECEIVED_DATE,
+					&t, sizeof(t)))
 		t = (time_t)-1;
-	}
-
 	return t;
 }
 
 static void get_cached_sent_date(struct index_mail *mail,
 				 struct mail_sent_date *sent_date)
 {
-	if (!mail_cache_copy_fixed_field(mail->trans->cache_view,
-					 mail->data.seq,
-					 MAIL_CACHE_SENT_DATE,
-					 sent_date, sizeof(*sent_date))) {
-		mail_cache_mark_missing(mail->trans->cache_view, mail->data.seq,
-					MAIL_CACHE_SENT_DATE);
-
+	if (!index_mail_get_fixed_field(mail, MAIL_CACHE_SENT_DATE,
+					sent_date, sizeof(*sent_date))) {
 		sent_date->time = (time_t)-1;
 		sent_date->timezone = 0;
 	}
--- a/src/lib-storage/index/index-mail.h	Sun Jul 04 23:11:04 2004 +0300
+++ b/src/lib-storage/index/index-mail.h	Mon Jul 05 00:07:43 2004 +0300
@@ -109,8 +109,8 @@
 			    enum modify_type modify_type);
 int index_mail_expunge(struct mail *mail);
 
-char *index_mail_get_cached_string(struct index_mail *mail,
-				   enum mail_cache_field field);
+const char *index_mail_get_cached_string(struct index_mail *mail,
+					 enum mail_cache_field field);
 uoff_t index_mail_get_cached_uoff_t(struct index_mail *mail,
 				    enum mail_cache_field field);
 uoff_t index_mail_get_cached_virtual_size(struct index_mail *mail);