dovecot-1.3: dbox: If enough bytes have been expunged, force a p...

dovecot at dovecot.org dovecot at dovecot.org
Sat Apr 11 01:27:07 EEST 2009


details:   http://hg.dovecot.org/dovecot-1.3/rev/53885f710b0b
changeset: 9067:53885f710b0b
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Apr 10 14:47:27 2009 -0400
description:
dbox: If enough bytes have been expunged, force a purge.

diffstat:

4 files changed, 67 insertions(+)
src/lib-storage/index/dbox/dbox-map.c  |   45 ++++++++++++++++++++++++++++++++
src/lib-storage/index/dbox/dbox-map.h  |    2 +
src/lib-storage/index/dbox/dbox-sync.c |   17 ++++++++++++
src/lib-storage/index/dbox/dbox-sync.h |    3 ++

diffs (128 lines):

diff -r 4f64d429985a -r 53885f710b0b src/lib-storage/index/dbox/dbox-map.c
--- a/src/lib-storage/index/dbox/dbox-map.c	Fri Apr 10 14:15:03 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-map.c	Fri Apr 10 14:47:27 2009 -0400
@@ -10,6 +10,9 @@
 #include "dbox-map-private.h"
 
 #define MAX_BACKWARDS_LOOKUPS 10
+
+#define DBOX_FORCE_PURGE_MIN_BYTES (1024*1024*10)
+#define DBOX_FORCE_PURGE_MIN_RATIO 0.5
 
 struct dbox_map_transaction_context {
 	struct dbox_map *map;
@@ -312,6 +315,48 @@ static void dbox_map_filter_zero_refs(st
 
 	hash_table_destroy(&hash);
 	pool_unref(&pool);
+}
+
+bool dbox_map_want_purge(struct dbox_map *map)
+{
+	const struct mail_index_header *hdr;
+	const struct dbox_mail_index_map_record *rec;
+	const uint16_t *ref16_p;
+	const void *data;
+	uoff_t ref0_size, total_size;
+	bool expunged;
+	uint32_t seq;
+
+	if (map->storage->set->dbox_purge_min_percentage >= 100) {
+		/* we never purge anything */
+		return FALSE;
+	}
+
+	ref0_size = total_size = 0;
+	hdr = mail_index_get_header(map->view);
+	for (seq = 1; seq <= hdr->messages_count; seq++) {
+		mail_index_lookup_ext(map->view, seq, map->map_ext_id,
+				      &data, &expunged);
+		if (data == NULL || expunged)
+			continue;
+		rec = data;
+
+		mail_index_lookup_ext(map->view, seq, map->ref_ext_id,
+				      &data, &expunged);
+		if (data == NULL || expunged)
+			continue;
+		ref16_p = data;
+
+		if (*ref16_p == 0)
+			ref0_size += rec->size;
+		total_size += rec->size;
+	}
+
+	if (ref0_size < DBOX_FORCE_PURGE_MIN_BYTES)
+		return FALSE;
+	if ((float)ref0_size / (float)total_size < DBOX_FORCE_PURGE_MIN_RATIO)
+		return FALSE;
+	return TRUE;
 }
 
 const ARRAY_TYPE(seq_range) *dbox_map_get_zero_ref_files(struct dbox_map *map)
diff -r 4f64d429985a -r 53885f710b0b src/lib-storage/index/dbox/dbox-map.h
--- a/src/lib-storage/index/dbox/dbox-map.h	Fri Apr 10 14:15:03 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-map.h	Fri Apr 10 14:47:27 2009 -0400
@@ -55,6 +55,8 @@ int dbox_map_update_refcounts(struct dbo
 			      const ARRAY_TYPE(uint32_t) *map_uids, int diff);
 int dbox_map_remove_file_id(struct dbox_map *map, uint32_t file_id);
 
+/* Returns TRUE if there's enough pressure to purge immediately. */
+bool dbox_map_want_purge(struct dbox_map *map);
 /* Return all files containing messages with zero refcount. */
 const ARRAY_TYPE(seq_range) *dbox_map_get_zero_ref_files(struct dbox_map *map);
 
diff -r 4f64d429985a -r 53885f710b0b src/lib-storage/index/dbox/dbox-sync.c
--- a/src/lib-storage/index/dbox/dbox-sync.c	Fri Apr 10 14:15:03 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-sync.c	Fri Apr 10 14:47:27 2009 -0400
@@ -83,6 +83,8 @@ static int dbox_sync_add_seq(struct dbox
 		}
 		seq_range_array_add(&entry->expunge_seqs, 0, seq);
 		array_append(&entry->expunge_map_uids, &map_uid, 1);
+		if (entry->file_id != 0)
+			ctx->have_storage_expunges = TRUE;
 	} else {
 		if ((sync_rec->add_flags & DBOX_INDEX_FLAG_ALT) != 0)
 			entry->move_to_alt = TRUE;
@@ -159,6 +161,18 @@ static int dbox_sync_index(struct dbox_s
 	}
 
 	if (ret > 0) {
+		if (ctx->have_storage_expunges) {
+			/* prevent a user from saving + expunging messages
+			   all the time and using lots of disk space.
+			   but avoid doing this in situations where a user
+			   simply expunges a lot of mail for the first time.
+			   that's why we do this calculation before current
+			   sync: the purging is triggered only after the
+			   second expunge. */
+			if (dbox_map_want_purge(ctx->mbox->storage->map))
+				ctx->purge = TRUE;
+		}
+
 		/* now sync each file separately */
 		iter = hash_table_iterate_init(ctx->syncs);
 		while (hash_table_iterate(iter, &key, &value)) {
@@ -319,6 +333,9 @@ int dbox_sync_finish(struct dbox_sync_co
 	}
 	if (ctx->path != NULL)
 		str_free(&ctx->path);
+
+	if (ctx->purge)
+		(void)dbox_sync_purge(&ctx->mbox->storage->storage);
 	i_free(ctx);
 	return ret;
 }
diff -r 4f64d429985a -r 53885f710b0b src/lib-storage/index/dbox/dbox-sync.h
--- a/src/lib-storage/index/dbox/dbox-sync.h	Fri Apr 10 14:15:03 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-sync.h	Fri Apr 10 14:47:27 2009 -0400
@@ -31,6 +31,9 @@ struct dbox_sync_context {
 
 	pool_t pool;
 	struct hash_table *syncs; /* struct dbox_sync_file_entry */
+
+	unsigned int have_storage_expunges:1;
+	unsigned int purge:1;
 };
 
 int dbox_sync_begin(struct dbox_mailbox *mbox, enum dbox_sync_flags flags,


More information about the dovecot-cvs mailing list