Skip to content

Commit

Permalink
plugins: fts-expunge-log - subtraction from and dumping of a flattene…
Browse files Browse the repository at this point in the history
…d 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>
  • Loading branch information
Phil Carmody authored and sirainen committed Mar 16, 2016
1 parent 652edd6 commit 96fbb1f
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 1 deletion.
53 changes: 53 additions & 0 deletions src/plugins/fts/fts-expunge-log.c
Expand Up @@ -253,6 +253,14 @@ void fts_expunge_log_append_record(struct fts_expunge_log_append_ctx *ctx,
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,
Expand Down Expand Up @@ -556,3 +564,48 @@ bool fts_expunge_log_contains(const struct fts_expunge_log_append_ctx *ctx,
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;
}
10 changes: 9 additions & 1 deletion src/plugins/fts/fts-expunge-log.h
Expand Up @@ -22,6 +22,9 @@ void fts_expunge_log_append_range(struct fts_expunge_log_append_ctx *ctx,
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);
Expand All @@ -43,5 +46,10 @@ int fts_expunge_log_flatten(const char *path,
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

0 comments on commit 96fbb1f

Please sign in to comment.