Mercurial > dovecot > core-2.2
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