[dovecot-cvs] dovecot/src/lib-index mail-hash.c, 1.29, 1.30 mail-hash.h, 1.14, 1.15

tss at dovecot.org tss at dovecot.org
Wed Dec 20 05:54:15 UTC 2006


Update of /var/lib/cvs/dovecot/src/lib-index
In directory talvi:/tmp/cvs-serv3262/lib-index

Modified Files:
	mail-hash.c mail-hash.h 
Log Message:
Fixes to hash compression and 1:n search.



Index: mail-hash.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-hash.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- mail-hash.c	20 Dec 2006 03:38:40 -0000	1.29
+++ mail-hash.c	20 Dec 2006 05:54:13 -0000	1.30
@@ -720,6 +720,11 @@
 			*value_r = rec;
 			return 1;
 		}
+
+		if (idx == rec->next_idx) {
+			mail_hash_set_corrupted(hash, "next_idx loops");
+			return -1;
+		}
 		idx = rec->next_idx;
 	}
 	return 0;
@@ -842,6 +847,8 @@
 	}
 
 	memcpy(rec, value, hash->record_size);
+	rec->next_idx = 0;
+
 	if (mail_hash_update_header(hash, rec, FALSE) < 0)
 		return -1;
 
@@ -849,6 +856,10 @@
 		idx_p = &hash->hash_base[hash_key % hash->hdr->hash_size];
 		while (*idx_p != 0) {
 			rec = HASH_RECORD_IDX(hash, *idx_p);
+			if (*idx_p == rec->next_idx) {
+				mail_hash_set_corrupted(hash, "next_idx loops");
+				return -1;
+			}
 			idx_p = &rec->next_idx;
 		}
 
@@ -1004,13 +1015,16 @@
 	return mail_hash_update_header(hash, rec, had_uid);
 }
 
-int mail_hash_resize_if_needed(struct mail_hash *hash, unsigned int grow_count)
+int mail_hash_resize_if_needed(struct mail_hash *hash, unsigned int grow_count,
+			       mail_hash_resize_callback_t *callback,
+			       void *context)
 {
 	struct mail_hash *tmp_hash;
 	const struct mail_hash_record *rec;
 	const char *tmp_filename;
-	uint32_t hash_key, idx, new_idx;
+	uint32_t hash_key, idx, new_idx, first_changed_idx, *map;
 	float nodes_per_list;
+	unsigned int map_size;
 	int ret = 0;
 
 	if (MAIL_HASH_IS_IN_MEMORY(hash))
@@ -1018,12 +1032,13 @@
 
 	i_assert(hash->locked);
 
+#if 0
 	nodes_per_list = (float)(hash->hdr->hashed_count + grow_count) /
 		(float)hash->hdr->hash_size;
 	if ((nodes_per_list > 0.3 && nodes_per_list < 2.0) ||
 	    hash->hdr->hash_size <= MAIL_HASH_MIN_SIZE)
 		return 0;
-
+#endif
 	/* create a temporary hash */
 	tmp_hash = mail_hash_open(hash->index,
 				  t_strconcat(hash->suffix, ".tmp", NULL),
@@ -1038,17 +1053,34 @@
 		return -1;
 
 	/* populate */
+	first_changed_idx = 0;
+	map_size = hash->hdr->record_count + 1;
+	map = i_new(uint32_t, map_size);
 	for (idx = 1; idx <= hash->hdr->record_count; idx++) {
 		rec = HASH_RECORD_IDX(hash, idx);
 		hash_key = hash->rec_hash_cb(rec);
 
+		if (MAIL_HASH_RECORD_IS_DELETED(rec))
+			continue;
+
 		if (mail_hash_insert_with_hash(tmp_hash, rec, hash_key,
 					       &new_idx) < 0) {
 			ret = -1;
 			break;
 		}
-		i_assert(idx == new_idx);
+
+		if (first_changed_idx == 0 && idx != new_idx)
+			first_changed_idx = idx;
+
+		/* @UNSAFE: keep old -> new idx mapping */
+		map[idx] = new_idx;
+	}
+	if (ret == 0 && first_changed_idx != 0) {
+		if (callback(tmp_hash, first_changed_idx,
+			     map, map_size, context) < 0)
+			ret = -1;
 	}
+	i_free(map);
 	(void)mail_hash_file_write_changes(tmp_hash);
 
 	tmp_filename = t_strdup(tmp_hash->filepath);

Index: mail-hash.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-hash.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- mail-hash.h	20 Dec 2006 03:38:40 -0000	1.14
+++ mail-hash.h	20 Dec 2006 05:54:13 -0000	1.15
@@ -5,6 +5,8 @@
 
 #define MAIL_HASH_VERSION 1
 
+struct mail_hash;
+
 /* File format:
 
    [header]
@@ -64,6 +66,11 @@
 /* Returns 0 if the pointers are equal. */
 typedef bool hash_ctx_cmp_callback_t(const void *key, const void *data,
 				     void *context);
+/* map[] contains old -> new index mapping. */
+typedef int mail_hash_resize_callback_t(struct mail_hash *tmp_hash,
+					uint32_t first_changed_idx,
+					const uint32_t *map,
+					unsigned int map_size, void *context);
 
 struct mail_hash *
 mail_hash_open(struct mail_index *index, const char *suffix,
@@ -93,7 +100,9 @@
 /* If reset or resize fails, the hash file is closed and the hash is in
    unusable state until mail_hash_lock() succeeds. */
 int mail_hash_reset(struct mail_hash *hash, unsigned int initial_count);
-int mail_hash_resize_if_needed(struct mail_hash *hash, unsigned int grow_count);
+int mail_hash_resize_if_needed(struct mail_hash *hash, unsigned int grow_count,
+			       mail_hash_resize_callback_t *callback,
+			       void *context);
 
 /* Lock hash file. Returns 1 if we locked the file, 0 if timeouted or hash
    is in memory, -1 if error. */



More information about the dovecot-cvs mailing list