[dovecot-cvs] dovecot/src/lib-index mail-index-file.c,NONE,1.1 Makefile.am,1.11,1.12 mail-index-compress.c,1.25,1.26 mail-index-data.c,1.45,1.46 mail-index-fsck.c,1.12,1.13 mail-index-open.c,1.39,1.40 mail-index.c,1.91,1.92 mail-index.h,1.82,1.83 mail-modifylog.c,1.49,1.50 mail-modifylog.h,1.7,1.8 mail-tree-redblack.c,1.22,NONE mail-tree.c,1.20,NONE mail-tree.h,1.9,NONE

cras at procontrol.fi cras at procontrol.fi
Mon Jul 21 18:35:41 EEST 2003


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

Modified Files:
	Makefile.am mail-index-compress.c mail-index-data.c 
	mail-index-fsck.c mail-index-open.c mail-index.c mail-index.h 
	mail-modifylog.c mail-modifylog.h 
Added Files:
	mail-index-file.c 
Removed Files:
	mail-tree-redblack.c mail-tree.c mail-tree.h 
Log Message:
Removed .imap.index.tree file. For now we'll just rewrite .imap.index file
whenever there's expunges. "Expunge binary tree" might be added later, but
it's not really useful until you have thousands of messages in mailbox and
you're deleting old messages from it.



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

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

struct mail_index_record *mail_index_next(struct mail_index *index,
					  struct mail_index_record *rec)
{
	i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
	i_assert(rec >= INDEX_RECORD_AT(index, 0));

	return rec+1 == INDEX_END_RECORD(index) ? NULL : rec+1;
}

static int compress(struct mail_index *index, unsigned int remove_first_idx,
		    unsigned int remove_last_idx)
{
	struct mail_index_record *rec = INDEX_RECORD_AT(index, 0);
	unsigned int idx_limit, count;

	idx_limit = MAIL_INDEX_RECORD_COUNT(index);
	count = remove_last_idx - remove_first_idx + 1;

	memmove(rec + remove_first_idx, rec + remove_last_idx + 1,
		(idx_limit - remove_last_idx - 1) * sizeof(*rec));

	index->header->used_file_size -= sizeof(*rec) * count;
	index->mmap_used_length -= sizeof(*rec) * count;

	return mail_index_truncate(index);
}

int mail_index_expunge_record_range(struct mail_index *index,
				    struct mail_index_record *first_rec,
				    struct mail_index_record *last_rec)
{
	struct mail_index_record *rec;
	unsigned int first_idx, last_idx, idx_limit;

        i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);

	first_idx = INDEX_RECORD_INDEX(index, first_rec);
	last_idx = INDEX_RECORD_INDEX(index, last_rec);
	idx_limit = MAIL_INDEX_RECORD_COUNT(index);

	i_assert(first_idx <= last_idx);
	i_assert(last_idx < idx_limit);

	index->header->messages_count -= last_idx - first_idx + 1;
	for (rec = first_rec; rec <= last_rec; rec++)
		mail_index_mark_flag_changes(index, rec, rec->msg_flags, 0);

	return compress(index, first_idx, last_idx);
}

struct mail_index_record *mail_index_lookup(struct mail_index *index,
					    unsigned int seq)
{
	i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
	i_assert(seq > 0);

	if (seq > index->header->messages_count)
		return NULL;

	return INDEX_RECORD_AT(index, seq-1);
}

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)
{
	struct mail_index_record *rec_p;
	unsigned int idx_limit, idx, left_idx, right_idx;

	i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
	i_assert(first_uid > 0);
	i_assert(first_uid <= last_uid);

	rec_p = INDEX_RECORD_AT(index, 0);
	idx_limit = MAIL_INDEX_RECORD_COUNT(index);

	idx = 0;
	left_idx = 0;
	right_idx = idx_limit;

	while (left_idx < right_idx) {
		idx = (left_idx + right_idx) / 2;

		if (rec_p[idx].uid < first_uid)
			left_idx = idx+1;
		else if (rec_p[idx].uid > first_uid)
			right_idx = idx;
		else
			break;
	}

	if (rec_p[idx].uid < first_uid || rec_p[idx].uid > last_uid) {
		/* could still be the next one */
		idx++;
		if (idx == idx_limit ||
		    rec_p[idx].uid < first_uid || rec_p[idx].uid > last_uid) {
			if (seq_r != NULL) *seq_r = 0;
			return NULL;
		}
	}

	if (seq_r != NULL)
		*seq_r = idx + 1;
	return rec_p + idx;
}

int mail_index_compress(struct mail_index *index __attr_unused__)
{
	return TRUE;
}

Index: Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/Makefile.am,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- Makefile.am	27 Apr 2003 20:02:07 -0000	1.11
+++ Makefile.am	21 Jul 2003 14:35:39 -0000	1.12
@@ -11,15 +11,14 @@
 	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-util.c \
-	mail-modifylog.c \
-	mail-tree.c \
-	mail-tree-redblack.c
+	mail-modifylog.c
 
 noinst_HEADERS = \
 	mail-custom-flags.h \

Index: mail-index-compress.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index-compress.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- mail-index-compress.c	30 Mar 2003 12:48:37 -0000	1.25
+++ mail-index-compress.c	21 Jul 2003 14:35:39 -0000	1.26
@@ -5,7 +5,6 @@
 #include "mail-index.h"
 #include "mail-index-data.h"
 #include "mail-index-util.h"
-#include "mail-tree.h"
 
 #include <stdio.h>
 #include <unistd.h>
@@ -42,75 +41,6 @@
 		index->header->sync_id++;
 	}
 
-	return TRUE;
-}
-
-int mail_index_compress(struct mail_index *index)
-{
-	struct mail_index_record *rec, *hole_rec, *end_rec;
-	unsigned int idx;
-	int tree_fd;
-
-	if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
-		return FALSE;
-
-	if (index->header->first_hole_records == 0) {
-		/* we don't need to compress after all. shouldn't happen.. */
-		index->header->flags &= ~MAIL_INDEX_FLAG_COMPRESS;
-		return TRUE;
-	}
-
-	if (!mail_index_verify_hole_range(index))
-		return FALSE;
-
-	/* if we get interrupted, the whole index is probably corrupted.
-	   so keep rebuild-flag on while doing this */
-	index->header->flags |= MAIL_INDEX_FLAG_REBUILD;
-	if (!mail_index_fmdatasync(index, sizeof(struct mail_index_header)))
-		return FALSE;
-
-	/* first actually compress the data */
-	hole_rec = INDEX_RECORD_AT(index, index->header->first_hole_index);
-	end_rec = INDEX_END_RECORD(index);
-	rec = hole_rec + index->header->first_hole_records;
-	while (rec < end_rec) {
-		if (rec->uid != 0) {
-			memcpy(hole_rec, rec, sizeof(struct mail_index_record));
-			idx = INDEX_RECORD_INDEX(index, hole_rec);
-			if (!mail_tree_update(index->tree, rec->uid, idx))
-				return FALSE;
-			hole_rec++;
-		}
-		rec++;
-	}
-
-	/* truncate the file to get rid of the extra records */
-	index->mmap_used_length = (size_t) ((char *) hole_rec -
-					    (char *) index->mmap_base);
-	index->header->used_file_size = index->mmap_used_length;
-
-	if (!mail_index_truncate(index))
-		return FALSE;
-
-	/* update headers */
-	index->header->first_hole_index = 0;
-	index->header->first_hole_records = 0;
-
-	/* make sure the whole file is synced before removing rebuild-flag */
-	if (!mail_tree_sync_file(index->tree, &tree_fd))
-		return FALSE;
-
-	if (fdatasync(tree_fd) < 0) {
-		index_file_set_syscall_error(index, index->tree->filepath,
-					     "fdatasync()");
-		return FALSE;
-	}
-
-	if (!mail_index_fmdatasync(index, index->mmap_used_length))
-		return FALSE;
-
-	index->header->flags &= ~(MAIL_INDEX_FLAG_COMPRESS |
-				  MAIL_INDEX_FLAG_REBUILD);
 	return TRUE;
 }
 

Index: mail-index-data.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index-data.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- mail-index-data.c	15 Jul 2003 18:26:42 -0000	1.45
+++ mail-index-data.c	21 Jul 2003 14:35:39 -0000	1.46
@@ -216,6 +216,13 @@
 		return FALSE;
 	}
 
+	if ((hdr->used_file_size & (INDEX_ALIGN_SIZE-1)) != 0) {
+		index_data_set_corrupted(data,
+			"used_file_size not aligned (%"PRIuUOFF_T")",
+			hdr->used_file_size);
+		return FALSE;
+	}
+
 	data->mmap_used_length = hdr->used_file_size;
 	data->header = hdr;
 	debug_mprotect(data->mmap_base, data->mmap_full_length, data->index);
@@ -593,7 +600,7 @@
 	    (data->mmap_used_length - pos < rec_hdr->data_size)) {
 		index_data_set_corrupted(data,
 			"Given data size larger than file size "
-			"(%"PRIuUOFF_T" + %u > %"PRIuSIZE_T") for record %u",
+			"(%u + %u > %"PRIuSIZE_T") for record %u",
 			index_rec->data_position, rec_hdr->data_size,
 			data->mmap_used_length, index_rec->uid);
 		return NULL;

Index: mail-index-fsck.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index-fsck.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- mail-index-fsck.c	5 Jan 2003 13:09:52 -0000	1.12
+++ mail-index-fsck.c	21 Jul 2003 14:35:39 -0000	1.13
@@ -14,14 +14,6 @@
 			      struct mail_index_header *old_hdr,
 			      struct mail_index_header *new_hdr)
 {
-	if (old_hdr->first_hole_index != new_hdr->first_hole_index) {
-		i_warning("fsck %s: first_hole_position %u != %u",
-			  index->filepath,
-			  old_hdr->first_hole_index,
-			  new_hdr->first_hole_index);
-	}
-	CHECK(first_hole_records);
-
 	CHECK(next_uid);
 
 	CHECK(messages_count);
@@ -48,23 +40,21 @@
 
 int mail_index_fsck(struct mail_index *index)
 {
-	/* we verify only the fields in the header. other problems will be
-	   noticed and fixed while reading the messages. */
 	struct mail_index_header old_hdr, *hdr;
 	struct mail_index_record *rec, *end_rec;
-	unsigned int max_uid, pos;
+	unsigned int max_uid;
 
 	i_assert(index->lock_type != MAIL_LOCK_SHARED);
 
-	if (!mail_index_set_lock(index, MAIL_LOCK_EXCLUSIVE))
+	/* Expunge tree can get easily corrupted, compress it away first. */
+	if (!mail_index_compress(index))
 		return FALSE;
 
+	/* then we verify only the fields in the header. other problems will
+	   be noticed and fixed while reading the messages. */
 	hdr = index->header;
 	memcpy(&old_hdr, hdr, sizeof(struct mail_index_header));
 
-	hdr->first_hole_index = 0;
-	hdr->first_hole_records = 0;
-
 	hdr->messages_count = 0;
 	hdr->seen_messages_count = 0;
 	hdr->deleted_messages_count = 0;
@@ -77,20 +67,6 @@
 
 	max_uid = 0;
 	for (; rec < end_rec; rec++) {
-		if (rec->uid == 0) {
-			/* expunged message */
-			pos = INDEX_RECORD_INDEX(index, rec);
-			if (hdr->first_hole_records == 0) {
-				hdr->first_hole_index = pos;
-				hdr->first_hole_records = 1;
-			} else if (hdr->first_hole_index +
-				   hdr->first_hole_records == pos) {
-				/* hole continues */
-				hdr->first_hole_records++;
-			}
-			continue;
-		}
-
 		if (rec->uid < max_uid) {
 			index_set_corrupted(index, "UIDs are not ordered "
 					    "(%u < %u)", rec->uid, max_uid);

Index: mail-index-open.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index-open.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- mail-index-open.c	5 Jul 2003 20:33:18 -0000	1.39
+++ mail-index-open.c	21 Jul 2003 14:35:39 -0000	1.40
@@ -11,7 +11,6 @@
 #include "mail-index.h"
 #include "mail-index-data.h"
 #include "mail-index-util.h"
-#include "mail-tree.h"
 #include "mail-modifylog.h"
 #include "mail-custom-flags.h"
 
@@ -111,13 +110,9 @@
 	}
 
 	if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) == 0) {
-		if (!mail_tree_open_or_create(index))
-			return FALSE;
 		if (!mail_modifylog_open_or_create(index))
 			return FALSE;
 	} else {
-		if (!mail_tree_create(index))
-			return FALSE;
 		if (!mail_modifylog_create(index))
 			return FALSE;
 	}
@@ -125,11 +120,6 @@
 	if (index->header->flags & MAIL_INDEX_FLAG_FSCK) {
 		/* index needs fscking */
 		if (!index->fsck(index))
-			return FALSE;
-	}
-
-	if ((index->header->flags & MAIL_INDEX_FLAG_REBUILD_TREE) != 0) {
-		if (!mail_tree_rebuild(index->tree))
 			return FALSE;
 	}
 

Index: mail-index.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index.c,v
retrieving revision 1.91
retrieving revision 1.92
diff -u -d -r1.91 -r1.92
--- mail-index.c	15 Jul 2003 18:26:42 -0000	1.91
+++ mail-index.c	21 Jul 2003 14:35:39 -0000	1.92
@@ -8,7 +8,6 @@
 #include "mail-index.h"
 #include "mail-index-data.h"
 #include "mail-index-util.h"
-#include "mail-tree.h"
 #include "mail-modifylog.h"
 #include "mail-custom-flags.h"
 
@@ -180,11 +179,6 @@
 		index->data = NULL;
 	}
 
-	if (index->tree != NULL) {
-                mail_tree_free(index->tree);
-		index->tree = NULL;
-	}
-
 	if (index->modifylog != NULL) {
                 mail_modifylog_free(index->modifylog);
 		index->modifylog = NULL;
@@ -220,11 +214,6 @@
 
 	failed = FALSE;
 
-	if (index->tree != NULL) {
-		if (!mail_tree_sync_file(index->tree, &fsync_fds[1]))
-			failed = TRUE;
-	}
-
 	if (index->modifylog != NULL) {
 		if (!mail_modifylog_sync_file(index->modifylog, &fsync_fds[2]))
 			failed = TRUE;
@@ -506,32 +495,6 @@
 	index->lock_notify_context = context;
 }
 
-int mail_index_verify_hole_range(struct mail_index *index)
-{
-	struct mail_index_header *hdr;
-	unsigned int max_records;
-
-	hdr = index->header;
-	if (hdr->first_hole_records == 0)
-		return TRUE;
-
-	max_records = MAIL_INDEX_RECORD_COUNT(index);
-	if (hdr->first_hole_index >= max_records) {
-		index_set_corrupted(index,
-				    "first_hole_index points outside file");
-		return FALSE;
-	}
-
-	/* check that first_hole_records is in valid range */
-	if (max_records - hdr->first_hole_index < hdr->first_hole_records) {
-		index_set_corrupted(index,
-				    "first_hole_records points outside file");
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
 struct mail_index_header *mail_index_get_header(struct mail_index *index)
 {
 	i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
@@ -539,126 +502,6 @@
 	return index->header;
 }
 
-struct mail_index_record *mail_index_lookup(struct mail_index *index,
-					    unsigned int seq)
-{
-	struct mail_index_header *hdr;
-	struct mail_index_record *rec;
-	const char *error;
-	unsigned int idx;
-
-	i_assert(seq > 0);
-	i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
-
-	hdr = index->header;
-	if (seq > hdr->messages_count) {
-		/* out of range */
-		return NULL;
-	}
-
-	if (!mail_index_verify_hole_range(index))
-		return NULL;
-
-	idx = seq-1;
-	if (hdr->first_hole_records == 0 || hdr->first_hole_index > idx) {
-		/* easy, it's just at the expected index */
-		error = t_strdup_printf("Invalid first_hole_index in header: "
-					"%u", idx);
-	} else if (hdr->first_hole_records ==
-		   MAIL_INDEX_RECORD_COUNT(index) - hdr->messages_count) {
-		/* only one hole in file, skip it and we're at
-		   correct position */
-		idx += hdr->first_hole_records;
-		error = t_strdup_printf("Invalid hole locations in header: %u",
-					idx);
-	} else {
-		/* find from binary tree */
-		idx = mail_tree_lookup_sequence(index->tree, seq);
-		if (idx == (unsigned int)-1) {
-			index_set_corrupted(index,
-				"Sequence %u not found from binary tree "
-				"(%u msgs says header)",
-				seq, hdr->messages_count);
-			return NULL;
-		}
-
-		error = t_strdup_printf("Invalid offset returned by "
-					"binary tree: %u", idx);
-	}
-
-	if (idx >= MAIL_INDEX_RECORD_COUNT(index)) {
-		index_set_corrupted(index, "%s", error);
-		return NULL;
-	}
-
-	rec = INDEX_RECORD_AT(index, idx);
-	if (rec->uid == 0) {
-		index_set_corrupted(index, "%s", error);
-		return NULL;
-	}
-
-	return rec;
-}
-
-struct mail_index_record *mail_index_next(struct mail_index *index,
-					  struct mail_index_record *rec)
-{
-	struct mail_index_record *end_rec;
-
-	i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
-	i_assert(rec >= (struct mail_index_record *) index->mmap_base);
-
-	if (rec == NULL)
-		return NULL;
-
-	/* go to the next non-deleted record */
-	end_rec = INDEX_END_RECORD(index);
-	while (++rec < end_rec) {
-		if (rec->uid != 0)
-			return rec;
-	}
-
-	return NULL;
-}
-
-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)
-{
-	struct mail_index_record *rec;
-	unsigned int idx;
-
-	i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
-	i_assert(first_uid > 0 && last_uid > 0);
-	i_assert(first_uid <= last_uid);
-
-	idx = mail_tree_lookup_uid_range(index->tree, seq_r,
-					 first_uid, last_uid);
-	if (idx == (unsigned int)-1)
-		return NULL;
-
-	if (idx >= MAIL_INDEX_RECORD_COUNT(index)) {
-		index_set_error(index, "Corrupted binary tree for index %s: "
-				"lookup returned index outside range "
-				"(%u >= %"PRIuSIZE_T")", index->filepath, idx,
-				MAIL_INDEX_RECORD_COUNT(index));
-		index->set_flags |= MAIL_INDEX_FLAG_REBUILD_TREE;
-		return NULL;
-	}
-
-	rec = INDEX_RECORD_AT(index, idx);
-	if (rec->uid < first_uid || rec->uid > last_uid) {
-		index_set_error(index, "Corrupted binary tree for index %s: "
-				"lookup returned offset to wrong UID "
-				"(%u vs %u..%u)", index->filepath,
-				rec->uid, first_uid, last_uid);
-		index->set_flags |= MAIL_INDEX_FLAG_REBUILD_TREE;
-		return NULL;
-	}
-
-	return rec;
-}
-
 const char *mail_index_lookup_field(struct mail_index *index,
 				    struct mail_index_record *rec,
 				    enum mail_data_field field)
@@ -814,20 +657,7 @@
 	}
 }
 
-static void update_first_hole_records(struct mail_index *index)
-{
-        struct mail_index_record *rec, *end_rec;
-
-	/* see if first_hole_records can be grown */
-	rec = INDEX_RECORD_AT(index, index->header->first_hole_index +
-			      index->header->first_hole_records);
-	end_rec = INDEX_END_RECORD(index);
-	while (rec < end_rec && rec->uid == 0) {
-		index->header->first_hole_records++;
-		rec++;
-	}
-}
-
+#if 0
 static int mail_index_truncate_hole(struct mail_index *index)
 {
 	index->header->used_file_size = sizeof(struct mail_index_header) +
@@ -848,96 +678,36 @@
 
 	return TRUE;
 }
-
-static void update_first_hole(struct mail_index *index,
-			      struct mail_index_record *rec)
-{
-	struct mail_index_header *hdr = index->header;
-	unsigned int idx;
-
-	idx = INDEX_RECORD_INDEX(index, rec);
-	if (hdr->first_hole_records == 0) {
-		/* first deleted message in index */
-		hdr->first_hole_index = idx;
-		hdr->first_hole_records = 1;
-	} else if (idx+1 == hdr->first_hole_index) {
-		/* deleted the previous record before hole */
-		hdr->first_hole_index--;
-		hdr->first_hole_records++;
-	} else if (idx == hdr->first_hole_index + hdr->first_hole_records) {
-		/* deleted the next record after hole */
-		hdr->first_hole_records++;
-		update_first_hole_records(index);
-	} else {
-		/* second hole coming to index file */
-		if (idx < hdr->first_hole_index) {
-			/* new hole before the old hole */
-			hdr->first_hole_index = idx;
-			hdr->first_hole_records = 1;
-		}
-	}
-}
+#endif
 
 #define INDEX_NEED_COMPRESS(records, hdr) \
 	((records) > INDEX_MIN_RECORDS_COUNT && \
 	 (records) * (100-INDEX_COMPRESS_PERCENTAGE) / 100 > \
 	 	(hdr)->messages_count)
 
-int mail_index_expunge(struct mail_index *index, struct mail_index_record *rec,
-		       unsigned int seq, int external_change)
+int mail_index_expunge(struct mail_index *index,
+		       struct mail_index_record *first_rec,
+		       struct mail_index_record *last_rec,
+		       unsigned int first_seq, unsigned int last_seq,
+		       int external_change)
 {
-	struct mail_index_header *hdr;
-	unsigned int records, uid;
+	unsigned int first_uid, last_uid;
 
 	i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
-	i_assert(seq != 0);
-	i_assert(rec->uid != 0);
-
-	if (!mail_index_verify_hole_range(index))
-		return FALSE;
-
-	hdr = index->header;
-
-	/* setting UID to 0 is enough for deleting the mail from index */
-	uid = rec->uid;
-	rec->uid = 0;
+	i_assert(first_seq != 0);
+	i_assert(first_seq <= last_seq);
 
-	update_first_hole(index, rec);
+	first_uid = first_rec->uid;
+	last_uid = last_rec->uid;
 
-	/* update message counts */
-	if (hdr->messages_count == 0) {
-		/* corrupted */
-		index_set_corrupted(index,
-			"Header says there's no mail while expunging");
+	if (!mail_index_expunge_record_range(index, first_rec, last_rec))
 		return FALSE;
-	}
-
-	hdr->messages_count--;
-	mail_index_mark_flag_changes(index, rec, rec->msg_flags, 0);
-
-	(void)mail_index_data_delete(index->data, rec);
-
-	records = MAIL_INDEX_RECORD_COUNT(index);
-	if (hdr->first_hole_index + hdr->first_hole_records == records) {
-		/* the hole reaches end of file, truncate it */
-		(void)mail_index_truncate_hole(index);
-	} else {
-		if (INDEX_NEED_COMPRESS(records, hdr))
-			hdr->flags |= MAIL_INDEX_FLAG_COMPRESS;
-	}
-
-	/* expunge() may be called while index is being rebuilt and when
-	   tree file hasn't been opened yet */
-	if (index->tree != NULL)
-		mail_tree_delete(index->tree, uid);
-	else {
-		/* make sure it also gets updated */
-		index->header->flags |= MAIL_INDEX_FLAG_REBUILD_TREE;
-	}
 
-	if (seq != 0 && index->modifylog != NULL) {
-		if (!mail_modifylog_add_expunge(index->modifylog, seq,
-						uid, external_change))
+	if (index->modifylog != NULL) {
+		if (!mail_modifylog_add_expunges(index->modifylog,
+						 first_seq, last_seq,
+						 first_uid, last_uid,
+						 external_change))
 			return FALSE;
 	}
 
@@ -1044,11 +814,6 @@
 	index->header->messages_count++;
 	rec->uid = index->header->next_uid++;
 
-	if (index->tree != NULL) {
-		mail_tree_insert(index->tree, rec->uid,
-				 INDEX_RECORD_INDEX(index, rec));
-	}
-
 	return TRUE;
 }
 
@@ -1064,7 +829,7 @@
 		index->mmap_used_length -= sizeof(*rec);
 	} else {
 		/* mark it deleted */
-		update_first_hole(index, rec);
+		(void)mail_index_expunge_record_range(index, rec, rec);
 	}
 }
 

Index: mail-index.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-index.h,v
retrieving revision 1.82
retrieving revision 1.83
diff -u -d -r1.82 -r1.83
--- mail-index.h	15 Jul 2003 18:26:42 -0000	1.82
+++ mail-index.h	21 Jul 2003 14:35:39 -0000	1.83
@@ -5,7 +5,7 @@
 #include "message-parser.h"
 #include "imap-util.h"
 
-#define MAIL_INDEX_VERSION 2
+#define MAIL_INDEX_VERSION 3
 
 #define INDEX_FILE_PREFIX ".imap.index"
 
@@ -36,7 +36,6 @@
 	MAIL_INDEX_FLAG_CACHE_FIELDS		= 0x0004,
 	MAIL_INDEX_FLAG_COMPRESS		= 0x0008,
 	MAIL_INDEX_FLAG_COMPRESS_DATA		= 0x0010,
-	MAIL_INDEX_FLAG_REBUILD_TREE		= 0x0020,
 	MAIL_INDEX_FLAG_DIRTY_MESSAGES		= 0x0040,
 	MAIL_INDEX_FLAG_DIRTY_CUSTOMFLAGS	= 0x0080,
 	MAIL_INDEX_FLAG_MAILDIR_NEW		= 0x0100
@@ -140,9 +139,6 @@
 
 	uoff_t used_file_size;
 
-	unsigned int first_hole_index;
-	unsigned int first_hole_records;
-
 	unsigned int uid_validity;
 	unsigned int next_uid;
 
@@ -166,12 +162,11 @@
 
 struct mail_index_record {
 	unsigned int uid;
-	unsigned int msg_flags; /* enum mail_flags */
+	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 */
-
-	uoff_t data_position;
 };
 
 struct mail_index_data_record_header {
@@ -268,7 +263,7 @@
 
 	/* Return the next record after specified record, or NULL if it was
 	   last record. The index must be locked all the time between
-	   lookup() and last next() call. */
+	   lookup() and last next() call. rec must not have been expunged. */
 	struct mail_index_record *(*next)(struct mail_index *index,
 					  struct mail_index_record *rec);
 
@@ -309,18 +304,19 @@
 	time_t (*get_internal_date)(struct mail_index *index,
 				    struct mail_index_record *rec);
 
-	/* Expunge a mail from index. Tree and modifylog is also updated. The
+	/* Expunge mails from index. Modifylog is also updated. The
 	   index must be exclusively locked before calling this function.
-	   If seq is 0, the modify log isn't updated. This is useful if
-	   after append() something goes wrong and you wish to delete the
-	   mail immediately. If external_change is TRUE, the modify log is
-	   always written.
 
-	   Note that the sequence numbers also update immediately after this
-	   call, so if you want to delete messages 1..4 just call this
-	   function 4 times with seq being 1. */
-	int (*expunge)(struct mail_index *index, struct mail_index_record *rec,
-		       unsigned int seq, int external_change);
+	   first_rec+1 .. last_rec-1 range may contain already expunged
+	   records.
+
+	   Note that all record pointers are invalidated after this call as
+	   expunging may radically modify the file. */
+	int (*expunge)(struct mail_index *index,
+		       struct mail_index_record *first_rec,
+		       struct mail_index_record *last_rec,
+		       unsigned int first_seq, unsigned int last_seq,
+		       int external_change);
 
 	/* Update mail flags. The index must be exclusively locked before
 	   calling this function. This shouldn't be called in the middle of
@@ -376,7 +372,6 @@
 
 /* private: */
 	struct mail_index_data *data;
-	struct mail_tree *tree;
 	struct mail_modify_log *modifylog;
 	struct mail_custom_flags *custom_flags;
 
@@ -459,7 +454,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, 0, \
@@ -493,8 +488,11 @@
 					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 *rec,
-		       unsigned int seq, int external_change);
+int mail_index_expunge(struct mail_index *index,
+		       struct mail_index_record *first_rec,
+		       struct mail_index_record *last_rec,
+		       unsigned int first_seq, unsigned int last_seq,
+		       int external_change);
 int mail_index_update_flags(struct mail_index *index,
 			    struct mail_index_record *rec,
 			    unsigned int seq, enum mail_flags flags,
@@ -527,7 +525,6 @@
 			    struct mail_index_header *hdr);
 void mail_index_close(struct mail_index *index);
 int mail_index_fmdatasync(struct mail_index *index, size_t size);
-int mail_index_verify_hole_range(struct mail_index *index);
 void mail_index_mark_flag_changes(struct mail_index *index,
 				  struct mail_index_record *rec,
 				  enum mail_flags old_flags,
@@ -541,6 +538,9 @@
 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,
+				    struct mail_index_record *last_rec);
 
 /* Maximum allowed UID number. */
 #define MAX_ALLOWED_UID 4294967295U /* 2^32 - 1 */
@@ -565,6 +565,8 @@
 #define INDEX_TRUNCATE_KEEP_PERCENTAGE 10
 /* Compress the file when deleted space reaches n% of total size */
 #define INDEX_COMPRESS_PERCENTAGE 50
+/* Compress the file when searching deleted records tree has to go this deep */
+#define INDEX_COMPRESS_DEPTH 10
 
 /* uoff_t to index file for given record */
 #define INDEX_FILE_POSITION(index, ptr) \

Index: mail-modifylog.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-modifylog.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -d -r1.49 -r1.50
--- mail-modifylog.c	15 Jul 2003 18:26:42 -0000	1.49
+++ mail-modifylog.c	21 Jul 2003 14:35:39 -0000	1.50
@@ -770,8 +770,10 @@
 	return TRUE;
 }
 
-int mail_modifylog_add_expunge(struct mail_modify_log *log, unsigned int seq,
-			       unsigned int uid, int external_change)
+int mail_modifylog_add_expunges(struct mail_modify_log *log,
+				unsigned int first_seq, unsigned int last_seq,
+				unsigned int first_uid, unsigned int last_uid,
+				int external_change)
 {
 	struct modify_log_file *file;
 	struct modify_log_record rec, *recp;
@@ -786,24 +788,24 @@
 
 	if (file->last_expunge != NULL &&
 	    file->last_expunge_external == external_change) {
-		if (seq+1 == file->last_expunge->seq1) {
-			i_assert(uid < file->last_expunge->uid1);
-			file->last_expunge->seq1 = seq;
-			file->last_expunge->uid1 = uid;
+		if (last_seq+1 == file->last_expunge->seq1) {
+			i_assert(last_uid < file->last_expunge->uid1);
+			file->last_expunge->seq1 = first_seq;
+			file->last_expunge->uid1 = first_uid;
 			return TRUE;
-		} else if (seq == file->last_expunge->seq1) {
-			/* note the different weirder logic than with
-			   flag changing, because of reordered seq numbers. */
-			i_assert(uid > file->last_expunge->uid2);
-			file->last_expunge->seq2++;
-			file->last_expunge->uid2 = uid;
+		} else if (first_seq == file->last_expunge->seq1) {
+			/* note that the weird looking logic above is correct.
+			   it's because of reordered seq numbers. */
+			i_assert(first_uid > file->last_expunge->uid2);
+			file->last_expunge->seq2 = last_seq;
+			file->last_expunge->uid2 = last_uid;
 			return TRUE;
 		}
 	}
 
 	rec.type = RECORD_TYPE_EXPUNGE;
-	rec.seq1 = rec.seq2 = seq;
-	rec.uid1 = rec.uid2 = uid;
+	rec.seq1 = first_seq; rec.seq2 = last_seq;
+	rec.uid1 = first_uid; rec.uid2 = last_uid;
 
 	recp = &rec;
 	if (!mail_modifylog_append(file, &recp, external_change))

Index: mail-modifylog.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mail-modifylog.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- mail-modifylog.h	5 Jan 2003 13:09:52 -0000	1.7
+++ mail-modifylog.h	21 Jul 2003 14:35:39 -0000	1.8
@@ -37,8 +37,10 @@
 /* Append EXPUGE or FLAGS entry to modify log. Index must be exclusively
    locked before calling these functions, and modifylog must have been
    marked synced within the same lock. */
-int mail_modifylog_add_expunge(struct mail_modify_log *log, unsigned int seq,
-			       unsigned int uid, int external_change);
+int mail_modifylog_add_expunges(struct mail_modify_log *log,
+				unsigned int first_seq, unsigned int last_seq,
+				unsigned int first_uid, unsigned int last_uid,
+				int external_change);
 int mail_modifylog_add_flags(struct mail_modify_log *log, unsigned int seq,
 			     unsigned int uid, int external_change);
 

--- mail-tree-redblack.c DELETED ---

--- mail-tree.c DELETED ---

--- mail-tree.h DELETED ---



More information about the dovecot-cvs mailing list