changeset 19938:6d82e2d02ef9

plugins: fts-expunge-log - subtraction from and dumping of a flattened log This permits you to read a whole expunge log, remove records from the in-memory copy of it, and write it back out to file. NOTE: Inefficiently implemented. The hash is effectively rebuilt, this time backed by a file, a record at a time, which implies O(n^2) possibilities. Signed-off-by: Phil Carmody <phil@dovecot.fi>
author Phil Carmody <phil@dovecot.fi>
date Mon, 29 Feb 2016 19:29:14 +0200
parents b032dac216fe
children d009614d609a
files src/plugins/fts/fts-expunge-log.c src/plugins/fts/fts-expunge-log.h
diffstat 2 files changed, 62 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/plugins/fts/fts-expunge-log.c	Sat Mar 12 01:56:55 2016 +0100
+++ b/src/plugins/fts/fts-expunge-log.c	Mon Feb 29 19:29:14 2016 +0200
@@ -253,6 +253,14 @@
 	array_foreach(&record->uids, range)
 		fts_expunge_log_append_range(ctx, record->mailbox_guid, range);
 }
+static void fts_expunge_log_append_mailbox_record(struct fts_expunge_log_append_ctx *ctx,
+						  struct fts_expunge_log_mailbox *mailbox)
+{
+	const struct seq_range *range;
+	/* FIXME: Optimise with a merge */
+	array_foreach(&mailbox->uids, range)
+		fts_expunge_log_append_range(ctx, mailbox->guid, range);
+}
 
 static void
 fts_expunge_log_export(struct fts_expunge_log_append_ctx *ctx,
@@ -556,3 +564,48 @@
 		return FALSE;
 	return seq_range_exists(&mailbox->uids, uid);	
 }
+void fts_expunge_log_append_remove(struct fts_expunge_log_append_ctx *from,
+				   const struct fts_expunge_log_read_record *record)
+{
+	const uint8_t *guid_p = record->mailbox_guid;
+	struct fts_expunge_log_mailbox *mailbox = hash_table_lookup(from->mailboxes, guid_p);
+	i_assert(mailbox != NULL); /* may only remove things that exist */
+	mailbox->uids_count -= seq_range_array_remove_seq_range(&mailbox->uids, &record->uids);
+}
+int fts_expunge_log_subtract(struct fts_expunge_log_append_ctx *from,
+			     struct fts_expunge_log *subtract)
+{
+	struct fts_expunge_log_read_ctx *read_ctx = fts_expunge_log_read_begin(subtract);
+	read_ctx->unlink = FALSE;
+
+	const struct fts_expunge_log_read_record *record;
+	while ((record = fts_expunge_log_read_next(read_ctx)) != NULL)
+		fts_expunge_log_append_remove(from, record);
+
+	return fts_expunge_log_read_end(&read_ctx);
+}
+/* It could be argued that somehow adding a log (file) to the append context
+   and then calling the _write() helper would be easier. But then there's the
+   _commit() vs. _abort() cleanup that would need to be addressed. Just creating
+   a copy is simpler. */
+int fts_expunge_log_flat_write(const struct fts_expunge_log_append_ctx *read_log,
+			       const char *path)
+{
+	int ret;
+	struct fts_expunge_log *nlog = fts_expunge_log_init(path);
+	struct fts_expunge_log_append_ctx *nappend = fts_expunge_log_append_begin(nlog);
+
+	struct hash_iterate_context *iter;
+	uint8_t *guid_p;
+	struct fts_expunge_log_mailbox *mailbox;
+
+	iter = hash_table_iterate_init(read_log->mailboxes);
+	while (hash_table_iterate(iter, read_log->mailboxes, &guid_p, &mailbox))
+		fts_expunge_log_append_mailbox_record(nappend, mailbox);
+
+	hash_table_iterate_deinit(&iter);
+	ret = fts_expunge_log_append_commit(&nappend);
+	fts_expunge_log_deinit(&nlog);
+
+	return ret;
+}
--- a/src/plugins/fts/fts-expunge-log.h	Sat Mar 12 01:56:55 2016 +0100
+++ b/src/plugins/fts/fts-expunge-log.h	Mon Feb 29 19:29:14 2016 +0200
@@ -22,6 +22,9 @@
 				  const struct seq_range *uids);
 void fts_expunge_log_append_record(struct fts_expunge_log_append_ctx *ctx,
 				   const struct fts_expunge_log_read_record *record);
+/* in-memory flattened structures may have records removed from them, file-backed ones may not */
+void fts_expunge_log_append_remove(struct fts_expunge_log_append_ctx *ctx,
+				   const struct fts_expunge_log_read_record *record);
 int fts_expunge_log_append_commit(struct fts_expunge_log_append_ctx **ctx);
 /* Do not commit non-backed structures, abort them after use. */
 int fts_expunge_log_append_abort(struct fts_expunge_log_append_ctx **ctx);
@@ -43,5 +46,10 @@
 			    struct fts_expunge_log_append_ctx **flattened_r);
 bool fts_expunge_log_contains(const struct fts_expunge_log_append_ctx *ctx,
 			      const guid_128_t mailbox_guid, uint32_t uid);
-
+/* Modify in-place a flattened log. */
+int fts_expunge_log_subtract(struct fts_expunge_log_append_ctx *from,
+			     struct fts_expunge_log *subtract);
+/* Write a modified flattened log as a new file. */
+int fts_expunge_log_flat_write(const struct fts_expunge_log_append_ctx *flattened,
+			       const char *path);
 #endif