[dovecot-cvs] dovecot/src/lib-index mail-cache.c,NONE,1.1 mail-cache.h,NONE,1.1 mail-index-rebuild.c,NONE,1.1 Makefile.am,1.13,1.14 mail-custom-flags.c,1.22,1.23 mail-index-compress.c,1.26,1.27 mail-index-fsck.c,1.13,1.14 mail-index-open.c,1.40,1.41 mail-index.c,1.93,1.94 mail-index.h,1.84,1.85 mail-index-data.c,1.46,NONE mail-index-data.h,1.13,NONE mail-index-update-cache.c,1.13,NONE mail-index-update.c,1.53,NONE

cras at procontrol.fi cras at procontrol.fi
Thu Aug 7 00:16:04 EEST 2003


Update of /home/cvs/dovecot/src/lib-index
In directory danu:/tmp/cvs-serv13163/lib-index

Modified Files:
	Makefile.am mail-custom-flags.c mail-index-compress.c 
	mail-index-fsck.c mail-index-open.c mail-index.c mail-index.h 
Added Files:
	mail-cache.c mail-cache.h mail-index-rebuild.c 
Removed Files:
	mail-index-data.c mail-index-data.h mail-index-update-cache.c 
	mail-index-update.c 
Log Message:
Index cache file rewrite. It's not finished yet and mbox support is
completely broken. But it's getting difficult to maintain outside cvs :)



--- NEW FILE: mail-cache.c ---
/* Copyright (C) 2003 Timo Sirainen */

#define _XOPEN_SOURCE 500 /* for pwrite() / Linux */

#include "lib.h"
#include "buffer.h"
#include "byteorder.h"
#include "file-lock.h"
#include "file-set-size.h"
#include "ioloop.h"
#include "mmap-util.h"
#include "write-full.h"
#include "mail-index.h"
#include "mail-index-util.h"
#include "mail-cache.h"

#include <stddef.h>
#include <unistd.h>
#include <sys/stat.h>
[...1666 lines suppressed...]
	return cache->mmap_base;
}

int mail_cache_set_corrupted(struct mail_cache *cache, const char *fmt, ...)
{
	va_list va;

	/* rebuild */
        INDEX_MARK_CORRUPTED(cache->index);
        mail_cache_mark_file_deleted(cache);

	va_start(va, fmt);
	t_push();
	index_set_error(cache->index, "Corrupted index cache file %s: %s",
			cache->filepath, t_strdup_vprintf(fmt, va));
	t_pop();
	va_end(va);

	return FALSE;
}

--- NEW FILE: mail-cache.h ---
#ifndef __MAIL_CACHE_H
#define __MAIL_CACHE_H

#include "byteorder.h"
#include "mail-index.h"

#define MAIL_CACHE_FILE_PREFIX ".cache"

#define MAIL_CACHE_HEADERS_COUNT 4

struct mail_cache_transaction_ctx;

enum mail_cache_field {
	/* fixed size fields */
	MAIL_CACHE_INDEX_FLAGS		= NBO32_BIT0,
	MAIL_CACHE_LOCATION_OFFSET	= NBO32_BIT1,
	MAIL_CACHE_MD5			= NBO32_BIT2,
	MAIL_CACHE_SENT_DATE		= NBO32_BIT3,
	MAIL_CACHE_RECEIVED_DATE	= NBO32_BIT4,
	MAIL_CACHE_HEADER_SIZE		= NBO32_BIT5,
	MAIL_CACHE_BODY_SIZE		= NBO32_BIT6,
	MAIL_CACHE_VIRTUAL_HEADER_SIZE	= NBO32_BIT7,
	MAIL_CACHE_VIRTUAL_FULL_SIZE	= NBO32_BIT8,

	/* variable sized field */
	MAIL_CACHE_HEADERS1		= NBO32_BIT31,
	MAIL_CACHE_HEADERS2		= NBO32_BIT30,
	MAIL_CACHE_HEADERS3		= NBO32_BIT29,
	MAIL_CACHE_HEADERS4		= NBO32_BIT28,
	MAIL_CACHE_LOCATION		= NBO32_BIT27,
	MAIL_CACHE_BODY			= NBO32_BIT26,
	MAIL_CACHE_BODYSTRUCTURE	= NBO32_BIT25,
	MAIL_CACHE_MESSAGEPART		= NBO32_BIT24,

	MAIL_CACHE_FIXED_MASK		= MAIL_CACHE_INDEX_FLAGS |
					  MAIL_CACHE_LOCATION_OFFSET |
					  MAIL_CACHE_MD5 |
					  MAIL_CACHE_SENT_DATE |
					  MAIL_CACHE_RECEIVED_DATE |
					  MAIL_CACHE_HEADER_SIZE |
					  MAIL_CACHE_BODY_SIZE |
					  MAIL_CACHE_VIRTUAL_HEADER_SIZE |
					  MAIL_CACHE_VIRTUAL_FULL_SIZE,
	MAIL_CACHE_HEADERS_MASK		= MAIL_CACHE_HEADERS1 |
					  MAIL_CACHE_HEADERS2 |
					  MAIL_CACHE_HEADERS4 |
					  MAIL_CACHE_HEADERS4,
	MAIL_CACHE_STRING_MASK		= MAIL_CACHE_HEADERS_MASK |
					  MAIL_CACHE_LOCATION |
					  MAIL_CACHE_BODY |
					  MAIL_CACHE_BODYSTRUCTURE,
	MAIL_CACHE_BODYSTRUCTURE_MASK	= MAIL_CACHE_BODY |
					  MAIL_CACHE_BODYSTRUCTURE |
                                          MAIL_CACHE_MESSAGEPART
};

struct mail_sent_date {
	time_t time;
	int timezone;
};

extern enum mail_cache_field mail_cache_header_fields[MAIL_CACHE_HEADERS_COUNT];

int mail_cache_open_or_create(struct mail_index *index);
void mail_cache_free(struct mail_cache *cache);

void mail_cache_set_defaults(struct mail_cache *cache,
			     enum mail_cache_field default_cache_fields,
			     enum mail_cache_field never_cache_fields);

/* Compress cache file. */
int mail_cache_compress(struct mail_cache *cache);

/* Truncate the cache file and update it's indexid */
int mail_cache_truncate(struct mail_cache *cache);

/* Set indexid to 0 to notify other processes using this file that they should
   re-open it. */
int mail_cache_mark_file_deleted(struct mail_cache *cache);

/* Explicitly lock the cache file. Returns 1 if ok, 0 if nonblock is TRUE and
   we couldn't immediately get a lock, or -1 if error. */
int mail_cache_lock(struct mail_cache *cache, int nonblock);
int mail_cache_unlock(struct mail_cache *cache);

/* Mark the lock to be removed when unlocking index file. */
void mail_cache_unlock_later(struct mail_cache *cache);

/* Returns TRUE if cache file is locked. */
int mail_cache_is_locked(struct mail_cache *cache);

/* Begin transaction. Returns same as mail_cache_lock(). Note that if you
   call lookup functions for messages within first and last message in
   transaction, the transaction will be automatically committed. */
int mail_cache_transaction_begin(struct mail_cache *cache, int nonblock,
				 struct mail_cache_transaction_ctx **ctx_r);
/* End transaction. Single transaction can have multiple commits/rollbacks.
   If there's any pending changes, they will be rolled back. */
int mail_cache_transaction_end(struct mail_cache_transaction_ctx *ctx);

int mail_cache_transaction_commit(struct mail_cache_transaction_ctx *ctx);
int mail_cache_transaction_rollback(struct mail_cache_transaction_ctx *ctx);

/* Return NULL-terminated list of headers for given index, or NULL if
   header index isn't used. */
const char *const *mail_cache_get_header_fields(struct mail_cache *cache,
						unsigned int idx);
/* Set list of headers for given index. */
int mail_cache_set_header_fields(struct mail_cache_transaction_ctx *ctx,
				 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,
		   struct mail_index_record *rec, 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,
		      struct mail_index_record *rec);

/* Return all fields that are currently cached for record. */
enum mail_cache_field
mail_cache_get_fields(struct mail_cache *cache,
		      const struct mail_index_record *rec);

/* 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 *cache,
			    const struct mail_index_record *rec,
			    enum mail_cache_field field,
			    const void **data_r, size_t *size_r);

/* Return string field. */
const char *mail_cache_lookup_string_field(struct mail_cache *cache,
					   const struct mail_index_record *rec,
					   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 *cache,
				const struct mail_index_record *rec,
				enum mail_cache_field field,
				void *buffer, size_t buffer_size);

/* Mark given fields as missing, ie. they should be cached when possible. */
void mail_cache_mark_missing(struct mail_cache *cache,
			     enum mail_cache_field fields);

/* Return index flags. */
enum mail_index_record_flag
mail_cache_get_index_flags(struct mail_cache *cache,
			   const struct mail_index_record *rec);

/* Update index flags. The cache file must be locked and the flags must be
   already inserted to the record. */
int mail_cache_update_index_flags(struct mail_cache *cache,
				  struct mail_index_record *rec,
				  enum mail_index_record_flag flags);

/* Return the whole file mmaped. */
void *mail_cache_get_mmaped(struct mail_cache *cache, size_t *size);

/* "Error in index cache file %s: ...". */
int mail_cache_set_corrupted(struct mail_cache *cache, const char *fmt, ...)
	__attr_format__(2, 3);

#endif

--- NEW FILE: mail-index-rebuild.c ---
/* Copyright (C) 2002-2003 Timo Sirainen */

#include "lib.h"
#include "mail-index.h"
#include "mail-index-util.h"
#include "mail-cache.h"

#include <sys/mman.h>

int mail_index_rebuild(struct mail_index *index)
{
	if (!mail_index_set_lock(index, MAIL_LOCK_EXCLUSIVE))
		return FALSE;

	index->set_flags &= ~MAIL_INDEX_HDR_FLAG_REBUILD;

	/* reset the header */
	mail_index_init_header(index->header);
	index->mmap_used_length = index->header->used_file_size;

	/* update indexid, which also means that our state has completely
	   changed */
	index->indexid = index->header->indexid;
	index->inconsistent = TRUE;
	index->rebuilding = TRUE;

	if (!index->anon_mmap) {
		if (msync(index->mmap_base, index->header_size, MS_SYNC) < 0)
			return index_set_syscall_error(index, "msync()");
	}

	if (!mail_cache_truncate(index->cache))
		return FALSE;

	/* read the mails by syncing */
	if (!index->sync_and_lock(index, FALSE, MAIL_LOCK_UNLOCK, NULL))
		return FALSE;

	/* rebuild is complete - remove the flag */
	index->header->flags &= ~(MAIL_INDEX_HDR_FLAG_REBUILD |
				  MAIL_INDEX_HDR_FLAG_FSCK);
	index->header->flags |= index->set_flags;
	index->set_flags = 0;

	index->rebuilding = FALSE;
	return TRUE;
}

Index: Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/Makefile.am,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- Makefile.am	22 Jul 2003 23:31:53 -0000	1.13
+++ Makefile.am	6 Aug 2003 20:15:31 -0000	1.14
@@ -8,21 +8,20 @@
 	-I$(top_srcdir)/src/lib-imap
 
 libindex_a_SOURCES = \
+        mail-cache.c \
 	mail-custom-flags.c \
         mail-index.c \
         mail-index-compress.c \
         mail-index-file.c \
         mail-index-fsck.c \
-        mail-index-data.c \
         mail-index-open.c \
-        mail-index-update.c \
-        mail-index-update-cache.c \
+        mail-index-rebuild.c \
         mail-index-util.c \
 	mail-modifylog.c
 
 noinst_HEADERS = \
+        mail-cache.h \
 	mail-custom-flags.h \
 	mail-index.h \
-        mail-index-data.h \
         mail-index-util.h \
 	mail-modifylog.h

Index: mail-custom-flags.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-custom-flags.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- mail-custom-flags.c	4 Jun 2003 17:09:56 -0000	1.22
+++ mail-custom-flags.c	6 Aug 2003 20:15:31 -0000	1.23
@@ -534,7 +534,7 @@
 	if (!custom_flags_add(mcf, first_empty, flag))
 		return -1;
 
-	mcf->index->set_flags |= MAIL_INDEX_FLAG_DIRTY_CUSTOMFLAGS;
+	mcf->index->set_flags |= MAIL_INDEX_HDR_FLAG_DIRTY_CUSTOMFLAGS;
 
 	mcf->custom_flags[first_empty] = i_strdup(flag);
 	return first_empty;

Index: mail-index-compress.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index-compress.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- mail-index-compress.c	21 Jul 2003 14:35:39 -0000	1.26
+++ mail-index-compress.c	6 Aug 2003 20:15:31 -0000	1.27
@@ -3,8 +3,8 @@
 #include "lib.h"
 #include "write-full.h"
 #include "mail-index.h"
-#include "mail-index-data.h"
 #include "mail-index-util.h"
+#include "mail-cache.h"
 
 #include <stdio.h>
 #include <unistd.h>
@@ -15,7 +15,8 @@
 
 	i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
 
-	if (index->mmap_full_length <= INDEX_FILE_MIN_SIZE || index->anon_mmap)
+	if (index->mmap_full_length <= INDEX_FILE_MIN_SIZE(index) ||
+	    index->anon_mmap)
 		return TRUE;
 
 	/* really truncate the file only when it's almost empty */
@@ -29,11 +30,11 @@
 
 		/* keep the size record-aligned */
 		index->mmap_full_length -= (index->mmap_full_length -
-					    sizeof(struct mail_index_header)) %
+					    index->header_size) %
 			sizeof(struct mail_index_record);
 
-		if (index->mmap_full_length < INDEX_FILE_MIN_SIZE)
-                        index->mmap_full_length = INDEX_FILE_MIN_SIZE;
+		if (index->mmap_full_length < INDEX_FILE_MIN_SIZE(index))
+                        index->mmap_full_length = INDEX_FILE_MIN_SIZE(index);
 
 		if (ftruncate(index->fd, (off_t)index->mmap_full_length) < 0)
 			return index_set_syscall_error(index, "ftruncate()");
@@ -44,6 +45,7 @@
 	return TRUE;
 }
 
+#if 0
 static int mail_index_copy_data(struct mail_index *index,
 				int fd, const char *path)
 {
@@ -69,7 +71,7 @@
 	/* now we'll begin the actual moving. keep rebuild-flag on
 	   while doing it. */
 	index->header->flags |= MAIL_INDEX_FLAG_REBUILD;
-	if (!mail_index_fmdatasync(index, sizeof(struct mail_index_header)))
+	if (!mail_index_fmdatasync(index, index->header_size))
 		return FALSE;
 
 	offset = sizeof(data_hdr);
@@ -182,3 +184,4 @@
 
 	return mail_index_data_open(index);
 }
+#endif

Index: mail-index-fsck.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index-fsck.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- mail-index-fsck.c	21 Jul 2003 14:35:39 -0000	1.13
+++ mail-index-fsck.c	6 Aug 2003 20:15:31 -0000	1.14
@@ -46,7 +46,6 @@
 
 	i_assert(index->lock_type != MAIL_LOCK_SHARED);
 
-	/* Expunge tree can get easily corrupted, compress it away first. */
 	if (!mail_index_compress(index))
 		return FALSE;
 

Index: mail-index-open.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index-open.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- mail-index-open.c	21 Jul 2003 14:35:39 -0000	1.40
+++ mail-index-open.c	6 Aug 2003 20:15:31 -0000	1.41
@@ -9,8 +9,8 @@
 #include "unlink-lockfiles.h"
 #include "write-full.h"
 #include "mail-index.h"
-#include "mail-index-data.h"
 #include "mail-index-util.h"
+#include "mail-cache.h"
 #include "mail-modifylog.h"
 #include "mail-custom-flags.h"
 
@@ -29,7 +29,7 @@
 	index->maildir_have_new =
 		(hdr->flags & MAIL_INDEX_FLAG_MAILDIR_NEW) != 0;
 
-	if ((hdr->flags & MAIL_INDEX_FLAG_DIRTY_MESSAGES) != 0)
+	if ((hdr->flags & MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES) != 0)
 		index->next_dirty_flush = ioloop_time;
 
 	/* update \Recent message counters */
@@ -52,7 +52,7 @@
 
 	if (hdr->next_uid >= MAX_ALLOWED_UID - 1000) {
 		/* UID values are getting too high, rebuild index */
-		index->set_flags |= MAIL_INDEX_FLAG_REBUILD;
+		index->set_flags |= MAIL_INDEX_HDR_FLAG_REBUILD;
 	}
 
 	if (index->lock_type == MAIL_LOCK_EXCLUSIVE) {
@@ -71,34 +71,16 @@
 {
 	int rebuilt;
 
-	/* open/create the index files */
-	if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) == 0) {
-		if (!mail_index_data_open(index)) {
-			if ((index->set_flags & MAIL_INDEX_FLAG_REBUILD) == 0)
-				return FALSE;
+	if (!mail_cache_open_or_create(index))
+		return FALSE;
 
-			/* data file is corrupted, need to rebuild index */
-			flags |= _MAIL_INDEX_OPEN_FLAG_CREATING;
-			index->set_flags = 0;
-			index->inconsistent = FALSE;
-		}
-	}
+	if ((index->header->flags & MAIL_INDEX_HDR_FLAG_REBUILD) != 0 ||
+	    (index->set_flags & MAIL_INDEX_HDR_FLAG_REBUILD) != 0) {
 
-	if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) != 0) {
-		if (!mail_index_set_lock(index, MAIL_LOCK_EXCLUSIVE))
-			return FALSE;
-		if (!mail_index_data_create(index))
+		if (!index->rebuild(index))
 			return FALSE;
-	}
 
-	/* custom flags file needs to be open before
-	   rebuilding index */
-	if (!mail_custom_flags_open_or_create(index))
-		return FALSE;
-
-	if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) != 0 ||
-	    (index->header->flags & MAIL_INDEX_FLAG_REBUILD) != 0) {
-		if (!index->rebuild(index))
+		if ((index->header->flags & MAIL_INDEX_HDR_FLAG_REBUILD) != 0)
 			return FALSE;
 
 		/* no inconsistency problems since we're still opening
@@ -109,6 +91,10 @@
 		rebuilt = FALSE;
 	}
 
+	/* custom flags file needs to be open before rebuilding index */
+	if (!mail_custom_flags_open_or_create(index))
+		return FALSE;
+
 	if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) == 0) {
 		if (!mail_modifylog_open_or_create(index))
 			return FALSE;
@@ -117,7 +103,7 @@
 			return FALSE;
 	}
 
-	if (index->header->flags & MAIL_INDEX_FLAG_FSCK) {
+	if (index->header->flags & MAIL_INDEX_HDR_FLAG_FSCK) {
 		/* index needs fscking */
 		if (!index->fsck(index))
 			return FALSE;
@@ -130,8 +116,6 @@
 					  MAIL_LOCK_SHARED, NULL) &&
 		    !index->nodiskspace)
 			return FALSE;
-
-		index->inconsistent = FALSE;
 	}
 
 	/* we never want to keep shared lock if syncing happens to set it.
@@ -143,23 +127,15 @@
 	}
 
 	if ((flags & MAIL_INDEX_OPEN_FLAG_FAST) == 0) {
-		if (index->header->flags & MAIL_INDEX_FLAG_COMPRESS) {
+		if (index->header->flags & MAIL_INDEX_HDR_FLAG_COMPRESS) {
 			/* remove deleted blocks from index file */
 			if (!mail_index_compress(index))
 				return FALSE;
 		}
 
-		if (index->header->flags & MAIL_INDEX_FLAG_CACHE_FIELDS) {
-			/* need to update cached fields */
-			if (!mail_index_update_cache(index))
-				return FALSE;
-		}
-
-		if (index->header->flags & MAIL_INDEX_FLAG_COMPRESS_DATA) {
-			/* remove unused space from index data file.
-			   keep after cache updates which may move data
-			   and create unused space */
-			if (!mail_index_compress_data(index))
+		if (index->header->flags & MAIL_INDEX_HDR_FLAG_COMPRESS_CACHE) {
+			/* remove unused space from index data file. */
+			if (!mail_cache_compress(index->cache))
 				return FALSE;
 		}
 	}
@@ -189,16 +165,6 @@
 	return 1;
 }
 
-static int mail_index_is_compatible(const struct mail_index_header *hdr)
-{
-	return hdr->compat_data[0] == MAIL_INDEX_VERSION &&
-		hdr->compat_data[1] == MAIL_INDEX_COMPAT_FLAGS &&
-		hdr->compat_data[2] == sizeof(unsigned int) &&
-		hdr->compat_data[3] == sizeof(time_t) &&
-		hdr->compat_data[4] == sizeof(uoff_t) &&
-		hdr->compat_data[5] == INDEX_ALIGN_SIZE;
-}
-
 static int mail_index_init_file(struct mail_index *index,
 				const struct mail_index_header *hdr)
 {
@@ -224,27 +190,20 @@
 	return TRUE;
 }
 
-void mail_index_init_header(struct mail_index *index,
-			    struct mail_index_header *hdr)
+void mail_index_init_header(struct mail_index_header *hdr)
 {
+	i_assert(sizeof(struct mail_index_header) < 256);
+
 	memset(hdr, 0, sizeof(*hdr));
-	hdr->compat_data[0] = MAIL_INDEX_VERSION;
-	hdr->compat_data[1] = MAIL_INDEX_COMPAT_FLAGS;
-	hdr->compat_data[2] = sizeof(unsigned int);
-	hdr->compat_data[3] = sizeof(time_t);
-	hdr->compat_data[4] = sizeof(uoff_t);
-	hdr->compat_data[5] = INDEX_ALIGN_SIZE;
+	hdr->major_version = MAIL_INDEX_MAJOR_VERSION;
+	hdr->minor_version = MAIL_INDEX_MINOR_VERSION;
+	hdr->header_size = (uint8_t)sizeof(struct mail_index_header);
+
 	hdr->indexid = ioloop_time;
 
 	/* mark the index requiring rebuild - rebuild() removes this flag
 	   when it succeeds */
-	hdr->flags = MAIL_INDEX_FLAG_REBUILD;
-
-	if (!index->anon_mmap) {
-		/* set the fields we always want to cache,
-		   but not if we're building into memory */
-		hdr->cache_fields |= index->default_cache_fields;
-	}
+	hdr->flags = MAIL_INDEX_HDR_FLAG_REBUILD;
 
 	hdr->used_file_size = sizeof(struct mail_index_header);
 	hdr->uid_validity = ioloop_time;
@@ -282,14 +241,15 @@
 
 	flags |= _MAIL_INDEX_OPEN_FLAG_CREATING;
 
-	index->mmap_full_length = INDEX_FILE_MIN_SIZE;
+	index->header_size = sizeof(struct mail_index_header);
+	index->mmap_full_length = INDEX_FILE_MIN_SIZE(index);
 	index->mmap_base = mmap_anon(index->mmap_full_length);
 	if (index->mmap_base == MAP_FAILED) {
 		index->mmap_base = NULL;
 		return index_set_error(index, "mmap_anon() failed: %m");
 	}
 
-	mail_index_init_header(index, index->mmap_base);
+	mail_index_init_header(index->mmap_base);
 	index->header = index->mmap_base;
 	index->mmap_used_length = index->header->used_file_size;
 
@@ -332,8 +292,8 @@
 	if ((ret = mail_index_read_header(index, &hdr)) < 0)
 		return FALSE;
 
-	if (ret == 0 || !mail_index_is_compatible(&hdr) ||
-	    (hdr.flags & MAIL_INDEX_FLAG_REBUILD) != 0) {
+	if (ret == 0 || hdr.major_version != MAIL_INDEX_MAJOR_VERSION ||
+	    (hdr.flags & MAIL_INDEX_HDR_FLAG_REBUILD) != 0) {
 		if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
 			return FALSE;
 
@@ -347,7 +307,7 @@
 			return mail_index_open_index(index, flags);
 		}
 
-		mail_index_init_header(index, &hdr);
+		mail_index_init_header(&hdr);
 		if (!mail_index_init_file(index, &hdr))
 			return FALSE;
 	}
@@ -367,7 +327,7 @@
 	}
 
 	if (!index_open_and_fix(index, flags)) {
-		if ((index->set_flags & MAIL_INDEX_FLAG_REBUILD) == 0 ||
+		if ((index->set_flags & MAIL_INDEX_HDR_FLAG_REBUILD) == 0 ||
 		    (flags & _MAIL_INDEX_OPEN_FLAG_CREATING) != 0)
 			return FALSE;
 

Index: mail-index.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index.c,v
retrieving revision 1.93
retrieving revision 1.94
diff -u -d -r1.93 -r1.94
--- mail-index.c	26 Jul 2003 16:33:22 -0000	1.93
+++ mail-index.c	6 Aug 2003 20:15:31 -0000	1.94
@@ -6,8 +6,8 @@
 #include "file-set-size.h"
 #include "mmap-util.h"
 #include "mail-index.h"
-#include "mail-index-data.h"
 #include "mail-index-util.h"
+#include "mail-cache.h"
 #include "mail-modifylog.h"
 #include "mail-custom-flags.h"
 
@@ -27,7 +27,12 @@
 		return FALSE;
 	}
 
-	extra = (index->mmap_full_length - sizeof(struct mail_index_header)) %
+	/* keep the header set even if we fail, so we can update the flags */
+	hdr = index->mmap_base;
+	index->header = hdr;
+	index->header_size = hdr->header_size;
+
+	extra = (index->mmap_full_length - index->header_size) %
 		sizeof(struct mail_index_record);
 
 	if (extra != 0) {
@@ -39,25 +44,20 @@
 		(void)ftruncate(index->fd, (off_t)index->mmap_full_length);
 	}
 
-	/* keep the header set even if we fail, so we can update the flags */
-	hdr = index->mmap_base;
-	index->header = hdr;
-
 	if (hdr->used_file_size > index->mmap_full_length) {
 		index_set_corrupted(index,
 				    "used_file_size larger than real file size "
-				    "(%"PRIuUOFF_T" vs %"PRIuSIZE_T")",
+				    "(%u vs %"PRIuSIZE_T")",
 				    hdr->used_file_size,
 				    index->mmap_full_length);
 		return FALSE;
 	}
 
-	if (hdr->used_file_size < sizeof(struct mail_index_header) ||
-	    (hdr->used_file_size - sizeof(struct mail_index_header)) %
+	if (hdr->used_file_size < index->header_size ||
+	    (hdr->used_file_size - index->header_size) %
 	    sizeof(struct mail_index_record) != 0) {
 		index_set_corrupted(index, "Invalid used_file_size in header "
-				    "(%"PRIuUOFF_T")",
-				    hdr->used_file_size);
+				    "(%u)", hdr->used_file_size);
 		return FALSE;
 	}
 
@@ -139,14 +139,12 @@
 				 PROT_READ|PROT_WRITE);
 #endif
 			index->header->flags |= index->set_flags;
-			(void)msync(index->mmap_base,
-				    sizeof(struct mail_index_header), MS_SYNC);
+			(void)msync(index->mmap_base, index->header_size,
+				    MS_SYNC);
 		}
 		index->set_flags = 0;
 	}
 
-	index->set_cache_fields = 0;
-
 	index->opened = FALSE;
 	index->inconsistent = FALSE;
 
@@ -174,9 +172,9 @@
 	}
 	index->mmap_base = NULL;
 
-	if (index->data != NULL) {
-                mail_index_data_free(index->data);
-		index->data = NULL;
+	if (index->cache != NULL) {
+                mail_cache_free(index->cache);
+		index->cache = NULL;
 	}
 
 	if (index->modifylog != NULL) {
@@ -206,9 +204,6 @@
 	for (i = 0; i < sizeof(fsync_fds)/sizeof(fsync_fds[0]); i++)
 		fsync_fds[i] = -1;
 
-	if (!mail_index_data_sync_file(index->data, &fsync_fds[0]))
-		return FALSE;
-
 	if (msync(index->mmap_base, index->mmap_used_length, MS_SYNC) < 0)
 		return index_set_syscall_error(index, "msync()");
 
@@ -261,11 +256,6 @@
 		index->header->flags |= index->set_flags;
 		index->set_flags = 0;
 	}
-
-	if (index->set_cache_fields != 0) {
-		index->header->cache_fields = index->set_cache_fields;
-		index->set_cache_fields = 0;
-	}
 }
 
 static int mail_index_write_header_changes(struct mail_index *index)
@@ -285,8 +275,7 @@
 	mail_index_update_header_changes(index);
 
 	if (!index->anon_mmap) {
-		if (msync(index->mmap_base,
-			  sizeof(struct mail_index_header), MS_SYNC) < 0) {
+		if (msync(index->mmap_base, index->header_size, MS_SYNC) < 0) {
 			index_set_syscall_error(index, "msync()");
 			failed = TRUE;
 		}
@@ -305,6 +294,13 @@
 static int mail_index_lock_remove(struct mail_index *index)
 {
 	enum mail_lock_type old_lock_type;
+	int ret = TRUE;
+
+	while (index->cache_later_locks > 0) {
+		if (!mail_cache_unlock(index->cache))
+			ret = FALSE;
+		index->cache_later_locks--;
+	}
 
 	if (!mail_index_wait_lock(index, F_UNLCK))
 		return FALSE;
@@ -316,18 +312,15 @@
 		/* releasing shared lock. we may need to update some
 		   flags in header. */
 		unsigned int old_flags;
-		enum mail_data_field old_cache;
 
 		old_flags = index->header->flags;
-		old_cache = index->header->cache_fields;
 
-		if ((old_flags | index->set_flags) != old_flags ||
-		    (old_cache | index->set_cache_fields) != old_cache)
+		if ((old_flags | index->set_flags) != old_flags)
 			return mail_index_write_header_changes(index);
 	}
 
         debug_mprotect(index->mmap_base, index->mmap_full_length, index);
-	return TRUE;
+	return ret;
 }
 
 static int mail_index_lock_change(struct mail_index *index,
@@ -335,10 +328,14 @@
 {
 	int ret, fd_lock_type;
 
-	/* shared -> exclusive isn't allowed without try_lock */
+	/* shared -> exclusive can deadlock */
 	i_assert(try_lock || lock_type != MAIL_LOCK_EXCLUSIVE ||
 		 index->lock_type != MAIL_LOCK_SHARED);
 
+	/* locking index when cache is locked can deadlock */
+	i_assert(try_lock || index->lock_type == MAIL_LOCK_EXCLUSIVE ||
+		 !mail_cache_is_locked(index->cache));
+
 	if (index->inconsistent) {
 		/* index is in inconsistent state and nothing else than
 		   free() is allowed for it. */
@@ -379,7 +376,7 @@
 		return FALSE;
 	}
 
-	if (index->header->flags & MAIL_INDEX_FLAG_FSCK) {
+	if (index->header->flags & MAIL_INDEX_HDR_FLAG_FSCK) {
 		/* someone just partially updated the index, need to fsck it */
 		if (lock_type == MAIL_LOCK_SHARED) {
 			/* we need exclusive lock so fsck()'s set_lock() won't
@@ -397,7 +394,7 @@
 
 		/* check again, in case it was already fscked while we had
 		   it unlocked for a while */
-		if (index->header->flags & MAIL_INDEX_FLAG_FSCK) {
+		if (index->header->flags & MAIL_INDEX_HDR_FLAG_FSCK) {
 			if (!index->fsck(index))
 				return FALSE;
 		}
@@ -413,9 +410,8 @@
 		   when the lock is released, the FSCK flag will also be
 		   removed. */
 		index->excl_lock_counter++;
-		index->header->flags |= MAIL_INDEX_FLAG_FSCK;
-		if (!mail_index_fmdatasync(index,
-					   sizeof(struct mail_index_header))) {
+		index->header->flags |= MAIL_INDEX_HDR_FLAG_FSCK;
+		if (!mail_index_fmdatasync(index, index->header_size)) {
 			(void)index->set_lock(index, MAIL_LOCK_UNLOCK);
 			return FALSE;
 		}
@@ -452,15 +448,14 @@
 			mail_modifylog_notify_lock_drop(index->modifylog);
 
 		/* dropping exclusive lock (either unlock or to shared) */
-		keep_fsck = (index->set_flags & MAIL_INDEX_FLAG_FSCK) != 0;
+		keep_fsck = (index->set_flags & MAIL_INDEX_HDR_FLAG_FSCK) != 0;
 		mail_index_update_header_changes(index);
 
 		/* remove the FSCK flag only after successful fsync() */
 		if (mail_index_sync_file(index) && !keep_fsck) {
-			index->header->flags &= ~MAIL_INDEX_FLAG_FSCK;
+			index->header->flags &= ~MAIL_INDEX_HDR_FLAG_FSCK;
 			if (!index->anon_mmap &&
-			    msync(index->mmap_base,
-				  sizeof(struct mail_index_header),
+			    msync(index->mmap_base, index->header_size,
 				  MS_SYNC) < 0) {
 				/* we only failed to remove the fsck flag,
 				   so this isn't fatal. */
@@ -502,115 +497,6 @@
 	return index->header;
 }
 
-const char *mail_index_lookup_field(struct mail_index *index,
-				    struct mail_index_record *rec,
-				    enum mail_data_field field)
-{
-	struct mail_index_data_record *datarec;
-
-	datarec = (rec->data_fields & field) == 0 ? NULL :
-		mail_index_data_lookup(index->data, rec, field);
-	if (datarec == NULL)
-		return NULL;
-
-	if (!mail_index_data_record_verify(index->data, datarec)) {
-		/* index is corrupted, it will be rebuilt */
-		return NULL;
-	}
-
-	return datarec->data;
-}
-
-const void *mail_index_lookup_field_raw(struct mail_index *index,
-					struct mail_index_record *rec,
-					enum mail_data_field field,
-					size_t *size)
-{
-	struct mail_index_data_record_header *datahdr;
-	struct mail_index_data_record *datarec;
-
-	if ((rec->data_fields & field) == 0) {
-		*size = 0;
-		return NULL;
-	}
-
-	if (field < DATA_FIELD_LAST) {
-		/* read data field */
-		datarec = mail_index_data_lookup(index->data, rec, field);
-		if (datarec == NULL) {
-			*size = 0;
-			return NULL;
-		}
-
-		*size = datarec->full_field_size;
-		return datarec->data;
-	}
-
-	/* read header field */
-	datahdr = mail_index_data_lookup_header(index->data, rec);
-	if (datahdr == NULL) {
-		*size = 0;
-		return NULL;
-	}
-
-	switch (field) {
-	case DATA_HDR_INTERNAL_DATE:
-		*size = sizeof(datahdr->internal_date);
-		return &datahdr->internal_date;
-	case DATA_HDR_VIRTUAL_SIZE:
-		*size = sizeof(datahdr->virtual_size);
-		return &datahdr->virtual_size;
-	case DATA_HDR_HEADER_SIZE:
-		*size = sizeof(datahdr->header_size);
-		return &datahdr->header_size;
-	case DATA_HDR_BODY_SIZE:
-		*size = sizeof(datahdr->body_size);
-		return &datahdr->body_size;
-	default:
-		*size = 0;
-		return NULL;
-	}
-}
-
-void mail_index_cache_fields_later(struct mail_index *index,
-				   enum mail_data_field field)
-{
-	i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
-
-	field &= ~index->never_cache_fields;
-
-	/* first check if the field even could be in the file */
-	if ((index->set_cache_fields & field) != field) {
-		if ((index->header->cache_fields & field) == 0) {
-			/* no, but make sure the future records will have it.
-			   we don't immediately mark the index to cache this
-			   field for old messages as some clients never ask
-			   the info again */
-			index->set_cache_fields |= field;
-		} else {
-			/* this is at least the second time it's being asked,
-			   make sure it'll be cached soon. */
-			index->set_flags |= MAIL_INDEX_FLAG_CACHE_FIELDS;
-		}
-	}
-}
-
-time_t mail_get_internal_date(struct mail_index *index,
-			      struct mail_index_record *rec)
-{
-	const time_t *date;
-	size_t size;
-
-	date = index->lookup_field_raw(index, rec,
-				       DATA_HDR_INTERNAL_DATE, &size);
-	if (date == NULL)
-		return (time_t)-1;
-	else {
-		i_assert(size == sizeof(*date));
-		return *date;
-	}
-}
-
 void mail_index_mark_flag_changes(struct mail_index *index,
 				  struct mail_index_record *rec,
 				  enum mail_flags old_flags,
@@ -691,8 +577,8 @@
 	}
 
 	if (index->header->messages_count == 0) {
-		/* all mail was deleted, truncate data file */
-		if (!mail_index_data_reset(index->data))
+		/* all mail was deleted, truncate cache file */
+		if (!mail_cache_truncate(index->cache))
 			return FALSE;
 	}
 
@@ -759,12 +645,19 @@
 	return TRUE;
 }
 
-struct mail_index_record *mail_index_append_begin(struct mail_index *index)
+struct mail_index_record *mail_index_append(struct mail_index *index)
 {
 	struct mail_index_record *rec;
 
 	i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
 
+	if (index->header->next_uid == MAX_ALLOWED_UID) {
+		index->set_flags |= MAIL_INDEX_HDR_FLAG_REBUILD;
+		index_set_error(index, "Reached maximum UID in mailbox %s, "
+				"rebuilding index", index->filepath);
+		return NULL;
+	}
+
 	if (index->mmap_used_length == index->mmap_full_length) {
 		if (!mail_index_grow(index))
 			return NULL;
@@ -774,48 +667,17 @@
 	i_assert(index->mmap_used_length + sizeof(struct mail_index_record) <=
 		 index->mmap_full_length);
 
+	index->header->messages_count++;
+
 	rec = (struct mail_index_record *) ((char *) index->mmap_base +
 					    index->mmap_used_length);
-	memset(rec, 0, sizeof(struct mail_index_record));
-
-	index->header->used_file_size += sizeof(struct mail_index_record);
-	index->mmap_used_length += sizeof(struct mail_index_record);
-
-	return rec;
-}
-
-int mail_index_append_end(struct mail_index *index,
-			  struct mail_index_record *rec)
-{
-	i_assert(rec->uid == 0);
-
-	if (index->header->next_uid == MAX_ALLOWED_UID) {
-		index->set_flags |= MAIL_INDEX_FLAG_REBUILD;
-		index_set_error(index, "Reached maximum UID in mailbox %s, "
-				"rebuilding index", index->filepath);
-		return FALSE;
-	}
-
-	index->header->messages_count++;
 	rec->uid = index->header->next_uid++;
+	rec->msg_flags = 0;
 
-	return TRUE;
-}
-
-void mail_index_append_abort(struct mail_index *index,
-			     struct mail_index_record *rec)
-{
-	i_assert(rec->uid == 0);
+	index->header->used_file_size += sizeof(*rec);
+	index->mmap_used_length += sizeof(*rec);
 
-	if (INDEX_FILE_POSITION(index, rec) ==
-	    index->header->used_file_size - sizeof(*rec)) {
-		/* we can just rollback */
-		index->header->used_file_size -= sizeof(*rec);
-		index->mmap_used_length -= sizeof(*rec);
-	} else {
-		/* mark it deleted */
-		(void)mail_index_expunge_record_range(index, rec, rec);
-	}
+	return rec;
 }
 
 enum mail_index_error mail_index_get_last_error(struct mail_index *index)

Index: mail-index.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index.h,v
retrieving revision 1.84
retrieving revision 1.85
diff -u -d -r1.84 -r1.85
--- mail-index.h	26 Jul 2003 16:33:22 -0000	1.84
+++ mail-index.h	6 Aug 2003 20:15:31 -0000	1.85
@@ -1,11 +1,13 @@
 #ifndef __MAIL_INDEX_H
 #define __MAIL_INDEX_H
 
+#include "byteorder.h"
 #include "file-dotlock.h"
 #include "message-parser.h"
 #include "imap-util.h"
 
-#define MAIL_INDEX_VERSION 3
+#define MAIL_INDEX_MAJOR_VERSION 3
+#define MAIL_INDEX_MINOR_VERSION 0
 
 #define INDEX_FILE_PREFIX ".imap.index"
 
@@ -31,57 +33,34 @@
 	/* Rebuild flag is set while index is being rebuilt or when
 	   some error is noticed in the index file. If this flag is set,
 	   the index shouldn't be used before rebuilding it. */
-	MAIL_INDEX_FLAG_REBUILD			= 0x0001,
-	MAIL_INDEX_FLAG_FSCK			= 0x0002,
-	MAIL_INDEX_FLAG_CACHE_FIELDS		= 0x0004,
-	MAIL_INDEX_FLAG_COMPRESS		= 0x0008,
-	MAIL_INDEX_FLAG_COMPRESS_DATA		= 0x0010,
-	MAIL_INDEX_FLAG_DIRTY_MESSAGES		= 0x0040,
-	MAIL_INDEX_FLAG_DIRTY_CUSTOMFLAGS	= 0x0080,
-	MAIL_INDEX_FLAG_MAILDIR_NEW		= 0x0100
-};
-
-enum mail_data_field {
-	DATA_FIELD_LOCATION		= 0x00000001,
-	DATA_FIELD_ENVELOPE		= 0x00000002,
-	DATA_FIELD_BODY			= 0x00000004,
-	DATA_FIELD_BODYSTRUCTURE	= 0x00000008,
-	DATA_FIELD_MD5			= 0x00000010,
-	DATA_FIELD_MESSAGEPART		= 0x00000020,
-
-	DATA_FIELD_LAST			= 0x00000040,
-	DATA_FIELD_MAX_BITS		= 6,
-
-	/* separate from above, but in same bitmask */
-	DATA_HDR_INTERNAL_DATE		= 0x40000000,
-	DATA_HDR_VIRTUAL_SIZE		= 0x20000000,
-	DATA_HDR_HEADER_SIZE		= 0x10000000,
-	DATA_HDR_BODY_SIZE		= 0x08000000
+	MAIL_INDEX_HDR_FLAG_FSCK		= NBO32_BIT0,
+	MAIL_INDEX_HDR_FLAG_REBUILD		= NBO32_BIT1,
+	MAIL_INDEX_HDR_FLAG_COMPRESS		= NBO32_BIT2,
+	MAIL_INDEX_HDR_FLAG_COMPRESS_CACHE	= NBO32_BIT3,
+	MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES	= NBO32_BIT4,
+	MAIL_INDEX_HDR_FLAG_DIRTY_CUSTOMFLAGS	= NBO32_BIT5,
+	MAIL_INDEX_HDR_FLAG_MAILDIR_NEW		= NBO32_BIT6
 };
 
-#define IS_BODYSTRUCTURE_FIELD(field) \
-	(((field) & (DATA_FIELD_BODY | DATA_FIELD_BODYSTRUCTURE | \
-		     DATA_FIELD_MESSAGEPART)) != 0)
-
-enum mail_index_mail_flag {
+enum mail_index_record_flag {
 	/* If binary flags are set, it's not checked whether mail is
 	   missing CRs. So this flag may be set as an optimization for
 	   regular non-binary mails as well if it's known that it contains
 	   valid CR+LF line breaks. */
-	INDEX_MAIL_FLAG_BINARY_HEADER	= 0x0001,
-	INDEX_MAIL_FLAG_BINARY_BODY	= 0x0002,
+	MAIL_INDEX_FLAG_BINARY_HEADER	= NBO32_BIT0,
+	MAIL_INDEX_FLAG_BINARY_BODY	= NBO32_BIT1,
 
 	/* Mail flags have been changed in index, but not written into
 	   actual mailbox yet. */
-	INDEX_MAIL_FLAG_DIRTY		= 0x0004,
+	MAIL_INDEX_FLAG_DIRTY		= NBO32_BIT2,
 
 	/* Maildir: Mail file is in new/ dir instead of cur/ */
-	INDEX_MAIL_FLAG_MAILDIR_NEW	= 0x0008,
+	MAIL_INDEX_FLAG_MAILDIR_NEW	= NBO32_BIT3,
 
 	/* Mail header or body is known to contain NUL characters. */
-	INDEX_MAIL_FLAG_HAS_NULS	= 0x0010,
+	MAIL_INDEX_FLAG_HAS_NULS	= NBO32_BIT4,
 	/* Mail header or body is known to not contain NUL characters. */
-	INDEX_MAIL_FLAG_HAS_NO_NULS	= 0x0020
+	MAIL_INDEX_FLAG_HAS_NO_NULS	= NBO32_BIT5
 };
 
 enum mail_lock_type {
@@ -122,75 +101,41 @@
 					 unsigned int secs_left, void *context);
 
 struct mail_index_header {
-	unsigned char compat_data[8];
-	/* 0 = version
-	   1 = flags,
-	   2 = sizeof(unsigned int),
-	   3 = sizeof(time_t),
-	   4 = sizeof(uoff_t),
-	   5 = INDEX_ALIGN_SIZE */
+	/* major version is increased only when you can't have backwards
+	   compatibility. minor version is increased when header size is
+	   increased to contain new non-critical fields. */
+	uint8_t major_version;
+	uint8_t minor_version;
+	uint8_t header_size;
+	uint8_t reserved;
 
-	unsigned int indexid;
-	unsigned int sync_id; /* re-mmap() when changed, required only
-	                         if file size is changed */
+	uint32_t indexid;
 
-	unsigned int flags;
-	unsigned int cache_fields;
+	uint32_t used_file_size;
+	uint32_t sync_id; /* re-mmap() when changed, required only
+	                     if file size is shrinked */
 
-	uoff_t used_file_size;
+	uint32_t flags;
 
-	unsigned int uid_validity;
-	unsigned int next_uid;
+	uint32_t uid_validity;
+	uint32_t next_uid;
 
-	unsigned int messages_count;
-	unsigned int seen_messages_count;
-	unsigned int deleted_messages_count;
-	unsigned int last_nonrecent_uid;
+	uint32_t messages_count;
+	uint32_t seen_messages_count;
+	uint32_t deleted_messages_count;
+	uint32_t last_nonrecent_uid;
 
 	/* these UIDs may not exist and may not even be unseen */
-	unsigned int first_unseen_uid_lowwater;
-	unsigned int first_deleted_uid_lowwater;
-};
-
-struct mail_index_data_header {
-	unsigned int indexid;
-	unsigned int reserved; /* for alignment mostly */
-
-	uoff_t used_file_size;
-	uoff_t deleted_space;
+	uint32_t first_unseen_uid_lowwater;
+	uint32_t first_deleted_uid_lowwater;
 };
 
 struct mail_index_record {
-	unsigned int uid;
-	unsigned int msg_flags;
-	unsigned int data_position; /* first bit must be 0 */
-
-	unsigned int index_flags; /* enum mail_index_mail_flag */
-	unsigned int data_fields; /* enum mail_data_field */
-};
-
-struct mail_index_data_record_header {
-	unsigned int data_size; /* including this header */
-
-	time_t internal_date;
-	uoff_t virtual_size;
-
-	uoff_t header_size;
-	uoff_t body_size;
-};
-
-struct mail_index_data_record {
-	unsigned int field; /* enum mail_data_field */
-	unsigned int full_field_size;
-	char data[INDEX_ALIGN_SIZE]; /* variable size */
+	uint32_t uid;
+	uint32_t msg_flags;
+	uint32_t data_offset;
 };
 
-#define SIZEOF_MAIL_INDEX_DATA \
-	(sizeof(struct mail_index_data_record) - INDEX_ALIGN_SIZE)
-
-#define DATA_RECORD_SIZE(rec) \
-        (SIZEOF_MAIL_INDEX_DATA + (rec)->full_field_size)
-
 struct mail_index {
 	/* Note that opening same index twice in the same process is a bad
 	   idea since they share the same file locks. As soon one of the
@@ -274,34 +219,16 @@
 						      unsigned int last_uid,
 						      unsigned int *seq_r);
 
-	/* Find field from specified record, or NULL if it's not in index.
-	   Makes sure that the field ends with \0. */
-	const char *(*lookup_field)(struct mail_index *index,
-				    struct mail_index_record *rec,
-				    enum mail_data_field field);
-
-	/* Find field from specified record, or NULL if it's not in index. */
-	const void *(*lookup_field_raw)(struct mail_index *index,
-					struct mail_index_record *rec,
-					enum mail_data_field field,
-					size_t *size);
-
-	/* Mark the fields to be cached later. If any of them is already
-	   set in hdr->cache_fields, mark the caching to happen next time
-	   index is opened. */
-	void (*cache_fields_later)(struct mail_index *index,
-				   enum mail_data_field field);
-
 	/* Open mail file and return it as mmap()ed IStream. If we fail,
 	   we return NULL and set deleted = TRUE if failure was because the
-	   mail was just deleted (ie. not an error). internal_date is set
+	   mail was just deleted (ie. not an error). received_date is set
 	   if it's non-NULL. */
 	struct istream *(*open_mail)(struct mail_index *index,
 				     struct mail_index_record *rec,
-				     time_t *internal_date, int *deleted);
+				     time_t *received_date, int *deleted);
 
-	/* Returns internal date of message, or (time_t)-1 if error occured. */
-	time_t (*get_internal_date)(struct mail_index *index,
+	/* Returns received date of message, or (time_t)-1 if error occured. */
+	time_t (*get_received_date)(struct mail_index *index,
 				    struct mail_index_record *rec);
 
 	/* Expunge mails from index. Modifylog is also updated. The
@@ -327,41 +254,8 @@
 			    int external_change);
 
 	/* Append a new record to index. The index must be exclusively
-	   locked before calling this function. rec->uid is updated in
-	   append_end(). */
-	struct mail_index_record *(*append_begin)(struct mail_index *index);
-	int (*append_end)(struct mail_index *index,
-			  struct mail_index_record *rec);
-	void (*append_abort)(struct mail_index *index,
-			     struct mail_index_record *rec);
-
-	/* Updating fields happens by calling update_begin(), one or more
-	   update_field()s and finally update_end() which does the actual
-	   updating. The index must be exclusively locked all this time.
-	   update_begin() and update_field() functions cannot fail.
-
-	   The extra_space parameter for update_field() specifies the amount
-	   of extra empty space we should leave after the value, so that if
-	   the field grows in future it could be expanded without copying it
-	   to end of file. When the field already exists, the extra_space
-	   is ignored.
-
-	   The files may not actually be updated until after you've unlocked
-	   the file. */
-	struct mail_index_update *
-		(*update_begin)(struct mail_index *index,
-				struct mail_index_record *rec);
-	int (*update_end)(struct mail_index_update *update);
-	void (*update_abort)(struct mail_index_update *update);
-
-	void (*update_field)(struct mail_index_update *update,
-			     enum mail_data_field field,
-			     const char *value, size_t extra_space);
-	/* Just remember that full_field_size will be INDEX_ALIGNed, so
-	   it may differer from the given size parameter. */
-	void (*update_field_raw)(struct mail_index_update *update,
-				 enum mail_data_field field,
-				 const void *value, size_t size);
+	   locked before calling this function. */
+	struct mail_index_record *(*append)(struct mail_index *index);
 
 	/* Returns the last error code. */
 	enum mail_index_error (*get_last_error)(struct mail_index *index);
@@ -371,7 +265,7 @@
 	const char *(*get_last_error_text)(struct mail_index *index);
 
 /* private: */
-	struct mail_index_data *data;
+	struct mail_cache *cache;
 	struct mail_modify_log *modifylog;
 	struct mail_custom_flags *custom_flags;
 
@@ -379,7 +273,6 @@
 	char *filepath; /* index file path */
 	char *mailbox_path; /* file/directory for mailbox location */
 	char *control_dir; /* destination for control files */
-	enum mail_data_field default_cache_fields, never_cache_fields;
 	unsigned int indexid;
 	unsigned int sync_id;
 
@@ -418,6 +311,7 @@
 	size_t mmap_full_length;
 
 	struct mail_index_header *header;
+	size_t header_size;
 
         enum mail_lock_type lock_type;
 	time_t file_sync_stamp;
@@ -429,7 +323,7 @@
 	/* these fields are OR'ed to the fields in index header once we
 	   get around grabbing exclusive lock */
 	unsigned int set_flags;
-	enum mail_data_field set_cache_fields;
+	unsigned int cache_later_locks;
 
 	unsigned int anon_mmap:1;
 	unsigned int mmap_invalidate:1;
@@ -444,6 +338,7 @@
 	unsigned int mailbox_lock_timeout:1;
 	unsigned int maildir_keep_new:1;
 	unsigned int maildir_have_new:1;
+	unsigned int maildir_synced_once:1;
 };
 
 #ifdef DEV_T_STRUCT
@@ -456,7 +351,7 @@
    members.. */
 #define MAIL_INDEX_PRIVATE_FILL \
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-	0, 0, 0, 0, 0, 0, { 0, 0, 0 }, 0, \
+	0, 0, 0, 0, { 0, 0, 0 }, 0, 0, 0, \
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
@@ -481,15 +376,6 @@
 struct mail_index_record *
 mail_index_lookup_uid_range(struct mail_index *index, unsigned int first_uid,
 			    unsigned int last_uid, unsigned int *seq_r);
-const char *mail_index_lookup_field(struct mail_index *index,
-				    struct mail_index_record *rec,
-				    enum mail_data_field field);
-const void *mail_index_lookup_field_raw(struct mail_index *index,
-					struct mail_index_record *rec,
-					enum mail_data_field field,
-					size_t *size);
-void mail_index_cache_fields_later(struct mail_index *index,
-				   enum mail_data_field field);
 int mail_index_expunge(struct mail_index *index,
 		       struct mail_index_record *first_rec,
 		       struct mail_index_record *last_rec,
@@ -499,46 +385,22 @@
 			    struct mail_index_record *rec,
 			    unsigned int seq, enum mail_flags flags,
 			    int external_change);
-struct mail_index_record *mail_index_append_begin(struct mail_index *index);
-int mail_index_append_end(struct mail_index *index,
-			  struct mail_index_record *rec);
-void mail_index_append_abort(struct mail_index *index,
-			     struct mail_index_record *rec);
-struct mail_index_update *
-mail_index_update_begin(struct mail_index *index,
-			struct mail_index_record *rec);
-int mail_index_update_end(struct mail_index_update *update);
-void mail_index_update_abort(struct mail_index_update *update);
-void mail_index_update_field(struct mail_index_update *update,
-			     enum mail_data_field field,
-			     const char *value, size_t extra_space);
-void mail_index_update_field_raw(struct mail_index_update *update,
-				 enum mail_data_field field,
-				 const void *value, size_t size);
-time_t mail_get_internal_date(struct mail_index *index,
-			      struct mail_index_record *rec);
+struct mail_index_record *mail_index_append(struct mail_index *index);
 enum mail_index_error mail_index_get_last_error(struct mail_index *index);
 const char *mail_index_get_last_error_text(struct mail_index *index);
 
 /* INTERNAL: */
 void mail_index_init(struct mail_index *index, const char *dir);
 int mail_index_mmap_update(struct mail_index *index);
-void mail_index_init_header(struct mail_index *index,
-			    struct mail_index_header *hdr);
+void mail_index_init_header(struct mail_index_header *hdr);
 void mail_index_close(struct mail_index *index);
 int mail_index_fmdatasync(struct mail_index *index, size_t size);
 void mail_index_mark_flag_changes(struct mail_index *index,
 				  struct mail_index_record *rec,
 				  enum mail_flags old_flags,
 				  enum mail_flags new_flags);
-void mail_index_update_headers(struct mail_index_update *update,
-			       struct istream *input,
-                               enum mail_data_field cache_fields,
-			       message_header_callback_t *header_cb,
-			       void *context);
-int mail_index_update_cache(struct mail_index *index);
+int mail_index_rebuild(struct mail_index *index);
 int mail_index_compress(struct mail_index *index);
-int mail_index_compress_data(struct mail_index *index);
 int mail_index_truncate(struct mail_index *index);
 int mail_index_expunge_record_range(struct mail_index *index,
 				    struct mail_index_record *first_rec,
@@ -577,7 +439,7 @@
 /* record for given index */
 #define INDEX_RECORD_AT(index, idx) \
 	((struct mail_index_record *) \
-	 ((char *) index->mmap_base + sizeof(struct mail_index_header)) + (idx))
+	 ((char *) index->mmap_base + (index)->header_size) + (idx))
 
 /* returns the next record after last one */
 #define INDEX_END_RECORD(index) \
@@ -585,26 +447,28 @@
 	 ((char *) (index)->mmap_base + (index)->mmap_used_length))
 
 /* index number for uoff_t position */
-#define INDEX_POSITION_INDEX(pos) \
-	(((pos) - sizeof(struct mail_index_header)) / \
+#define INDEX_POSITION_INDEX(index, pos) \
+	(((pos) - (index)->header_size) / \
 	 sizeof(struct mail_index_record))
 
 /* index number for given record */
 #define INDEX_RECORD_INDEX(index, ptr) \
-	INDEX_POSITION_INDEX(INDEX_FILE_POSITION(index, ptr))
+	INDEX_POSITION_INDEX(index, INDEX_FILE_POSITION(index, ptr))
 
 /* mark the index corrupted */
 #define INDEX_MARK_CORRUPTED(index) \
-	STMT_START { (index)->set_flags |= MAIL_INDEX_FLAG_REBUILD; } STMT_END
+	STMT_START { \
+		(index)->set_flags |= MAIL_INDEX_HDR_FLAG_REBUILD; \
+	} STMT_END
 
 /* get number of records in mmaped index */
 #define MAIL_INDEX_RECORD_COUNT(index) \
-	((index->mmap_used_length - sizeof(struct mail_index_header)) / \
+	((index->mmap_used_length - (index)->header_size) / \
 	 sizeof(struct mail_index_record))
 
 /* minimum size for index file */
-#define INDEX_FILE_MIN_SIZE \
-	(sizeof(struct mail_index_header) + \
+#define INDEX_FILE_MIN_SIZE(index) \
+	((index)->header_size + \
 	 INDEX_MIN_RECORDS_COUNT * sizeof(struct mail_index_record))
 
 /* enum mail_lock_type to fcntl() lock type */

--- mail-index-data.c DELETED ---

--- mail-index-data.h DELETED ---

--- mail-index-update-cache.c DELETED ---

--- mail-index-update.c DELETED ---



More information about the dovecot-cvs mailing list