From: Timo Sirainen Date: Mon, 30 Jan 2023 23:39:23 +0000 (+0200) Subject: fts: Remove unused fts-expunge-log X-Git-Tag: 2.4.0~2990 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=49b51520cbb951f9baedffc6a09485f5302a1b0b;p=thirdparty%2Fdovecot%2Fcore.git fts: Remove unused fts-expunge-log --- diff --git a/src/plugins/fts/Makefile.am b/src/plugins/fts/Makefile.am index 759e35995c..d5ddb2c8e7 100644 --- a/src/plugins/fts/Makefile.am +++ b/src/plugins/fts/Makefile.am @@ -27,7 +27,6 @@ lib20_fts_plugin_la_LIBADD = ../../lib-fts/libfts.la lib20_fts_plugin_la_SOURCES = \ fts-api.c \ fts-build-mail.c \ - fts-expunge-log.c \ fts-indexer.c \ fts-parser.c \ fts-parser-html.c \ @@ -44,7 +43,6 @@ pkginc_libdir=$(pkgincludedir) pkginc_lib_HEADERS = \ fts-api.h \ fts-api-private.h \ - fts-expunge-log.h \ fts-indexer.h \ fts-parser.h \ fts-storage.h \ @@ -71,5 +69,4 @@ doveadm_module_LTLIBRARIES = \ lib20_doveadm_fts_plugin.la lib20_doveadm_fts_plugin_la_SOURCES = \ - doveadm-fts.c \ - doveadm-dump-fts-expunge-log.c + doveadm-fts.c diff --git a/src/plugins/fts/doveadm-dump-fts-expunge-log.c b/src/plugins/fts/doveadm-dump-fts-expunge-log.c deleted file mode 100644 index 2de2c75c38..0000000000 --- a/src/plugins/fts/doveadm-dump-fts-expunge-log.c +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "buffer.h" -#include "hex-binary.h" -#include "guid.h" -#include "doveadm-dump.h" -#include "doveadm-fts.h" - -#include -#include -#include - -struct fts_expunge_log_record { - uint32_t checksum; - uint32_t record_size; - guid_128_t guid; -}; - -static int dump_record(int fd, buffer_t *buf) -{ - struct fts_expunge_log_record rec; - off_t offset; - void *data; - const uint32_t *expunges, *uids; - ssize_t ret; - size_t data_size; - unsigned int i, uids_count; - - offset = lseek(fd, 0, SEEK_CUR); - - ret = read(fd, &rec, sizeof(rec)); - if (ret == 0) - return 0; - - if (ret != sizeof(rec)) - i_fatal("rec read() %d != %d", (int)ret, (int)sizeof(rec)); - - if (rec.record_size < sizeof(rec) + sizeof(uint32_t) || - rec.record_size > INT_MAX) { - i_fatal("Invalid record_size=%u at offset %"PRIuUOFF_T, - rec.record_size, offset); - } - data_size = rec.record_size - sizeof(rec); - buffer_set_used_size(buf, 0); - data = buffer_append_space_unsafe(buf, data_size); - ret = read(fd, data, data_size); - if (ret != (ssize_t)data_size) - i_fatal("rec read() %d != %d", (int)ret, (int)data_size); - - printf("#%"PRIuUOFF_T":\n", offset); - printf(" checksum = %8x\n", rec.checksum); - printf(" size .... = %u\n", rec.record_size); - printf(" mailbox . = %s\n", guid_128_to_string(rec.guid)); - - expunges = CONST_PTR_OFFSET(data, data_size - sizeof(uint32_t)); - printf(" expunges = %u\n", *expunges); - - printf(" uids .... = "); - - uids = data; - uids_count = (rec.record_size - sizeof(rec) - sizeof(uint32_t)) / - sizeof(uint32_t); - for (i = 0; i < uids_count; i += 2) { - if (i != 0) - printf(","); - if (uids[i] == uids[i+1]) - printf("%u", uids[i]); - else - printf("%u-%u", uids[i], uids[i+1]); - } - printf("\n"); - return 1; -} - -static void -cmd_dump_fts_expunge_log(struct doveadm_cmd_context *cctx ATTR_UNUSED, - const char *path, const char *const *args ATTR_UNUSED) -{ - buffer_t *buf; - int fd, ret; - - fd = open(path, O_RDONLY); - if (fd < 0) - i_fatal("open(%s) failed: %m", path); - - buf = buffer_create_dynamic(default_pool, 1024); - do { - T_BEGIN { - ret = dump_record(fd, buf); - } T_END; - } while (ret > 0); - buffer_free(&buf); - i_close_fd(&fd); -} - -static bool test_dump_fts_expunge_log(struct doveadm_cmd_context *cctx ATTR_UNUSED, - const char *path) -{ - const char *p; - - if ((p = strrchr(path, '/')) != NULL) - p++; - else - p = path; - return strcmp(p, "dovecot-expunges.log") == 0; -} - -static const struct doveadm_cmd_dump doveadm_cmd_dump_fts_expunge_log = { - "fts-expunge-log", - test_dump_fts_expunge_log, - cmd_dump_fts_expunge_log -}; - -void doveadm_dump_fts_expunge_log_init(void) -{ - doveadm_dump_register(&doveadm_cmd_dump_fts_expunge_log); -} diff --git a/src/plugins/fts/doveadm-fts.c b/src/plugins/fts/doveadm-fts.c index 2e1f8384d0..affe1439e1 100644 --- a/src/plugins/fts/doveadm-fts.c +++ b/src/plugins/fts/doveadm-fts.c @@ -476,7 +476,6 @@ void doveadm_fts_plugin_init(struct module *module ATTR_UNUSED) for (i = 0; i < N_ELEMENTS(fts_commands); i++) doveadm_cmd_register_ver2(&fts_commands[i]); - doveadm_dump_fts_expunge_log_init(); } void doveadm_fts_plugin_deinit(void) diff --git a/src/plugins/fts/doveadm-fts.h b/src/plugins/fts/doveadm-fts.h index d4307fe0c1..b09e0256ae 100644 --- a/src/plugins/fts/doveadm-fts.h +++ b/src/plugins/fts/doveadm-fts.h @@ -3,8 +3,6 @@ struct module; -void doveadm_dump_fts_expunge_log_init(void); - void doveadm_fts_plugin_init(struct module *module); void doveadm_fts_plugin_deinit(void); diff --git a/src/plugins/fts/fts-expunge-log.c b/src/plugins/fts/fts-expunge-log.c deleted file mode 100644 index c18f85ced3..0000000000 --- a/src/plugins/fts/fts-expunge-log.c +++ /dev/null @@ -1,629 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "array.h" -#include "crc32.h" -#include "hash.h" -#include "istream.h" -#include "write-full.h" -#include "seq-range-array.h" -#include "mail-storage.h" -#include "fts-expunge-log.h" -#include "fts-api-private.h" - -#include -#include -#include - -struct fts_expunge_log_record { - /* CRC32 of this entire record (except this checksum) */ - uint32_t checksum; - /* Size of this entire record */ - uint32_t record_size; - - /* Mailbox GUID */ - guid_128_t guid; - /* { uid1, uid2 } pairs */ - /* uint32_t expunge_uid_ranges[]; */ - - /* Total number of messages expunged so far in this log */ - /* uint32_t expunge_count; */ -}; - -struct fts_expunge_log { - char *path; - - int fd; - struct stat st; - struct event *event; -}; - -struct fts_expunge_log_mailbox { - guid_128_t guid; - ARRAY_TYPE(seq_range) uids; - unsigned int uids_count; -}; - -struct fts_expunge_log_append_ctx { - struct fts_expunge_log *log; - pool_t pool; - struct event *event; - - HASH_TABLE(uint8_t *, struct fts_expunge_log_mailbox *) mailboxes; - struct fts_expunge_log_mailbox *prev_mailbox; - - bool failed; -}; - -struct fts_expunge_log_read_ctx { - struct fts_expunge_log *log; - - struct istream *input; - buffer_t buffer; - struct fts_expunge_log_read_record read_rec; - - bool failed; - bool corrupted; - bool unlink; -}; - -struct fts_expunge_log * -fts_expunge_log_init(const char *path, struct event *event) -{ - struct fts_expunge_log *log; - - log = i_new(struct fts_expunge_log, 1); - log->event = event_create(event); - event_add_category(log->event, &event_category_fts); - log->path = i_strdup(path); - log->fd = -1; - return log; -} - -void fts_expunge_log_deinit(struct fts_expunge_log **_log) -{ - struct fts_expunge_log *log = *_log; - - *_log = NULL; - i_close_fd(&log->fd); - i_free(log->path); - event_unref(&log->event); - i_free(log); -} - -static int fts_expunge_log_open(struct fts_expunge_log *log, bool create) -{ - int fd; - - i_assert(log->fd == -1); - - /* FIXME: use proper permissions */ - fd = open(log->path, O_RDWR | O_APPEND | (create ? O_CREAT : 0), 0600); - if (fd == -1) { - if (errno == ENOENT && !create) - return 0; - - e_error(log->event, "open(%s) failed: %m", log->path); - return -1; - } - if (fstat(fd, &log->st) < 0) { - e_error(log->event, "fstat(%s) failed: %m", log->path); - i_close_fd(&fd); - return -1; - } - log->fd = fd; - return 1; -} - -static int -fts_expunge_log_reopen_if_needed(struct fts_expunge_log *log, bool create) -{ - struct stat st; - - if (log->fd == -1) - return fts_expunge_log_open(log, create); - - if (stat(log->path, &st) == 0) { - if (st.st_ino == log->st.st_ino && - CMP_DEV_T(st.st_dev, log->st.st_dev)) { - /* same file */ - return 0; - } - /* file changed */ - } else if (errno == ENOENT) { - /* recreate the file */ - } else { - e_error(log->event, "stat(%s) failed: %m", log->path); - return -1; - } - if (close(log->fd) < 0) - e_error(log->event, "close(%s) failed: %m", log->path); - log->fd = -1; - return fts_expunge_log_open(log, create); -} - -static int -fts_expunge_log_read_expunge_count(struct fts_expunge_log *log, - uint32_t *expunge_count_r) -{ - ssize_t ret; - - i_assert(log->fd != -1); - - if (fstat(log->fd, &log->st) < 0) { - e_error(log->event, "fstat(%s) failed: %m", log->path); - return -1; - } - if ((uoff_t)log->st.st_size < sizeof(*expunge_count_r)) { - *expunge_count_r = 0; - return 0; - } - /* we'll assume that write()s atomically grow the file size, as - O_APPEND almost guarantees. even if not, having a race condition - isn't the end of the world. the expunge count is simply read wrong - and fts optimize is performed earlier or later than intended. */ - ret = pread(log->fd, expunge_count_r, sizeof(*expunge_count_r), - log->st.st_size - 4); - if (ret < 0) { - e_error(log->event, "pread(%s) failed: %m", log->path); - return -1; - } - if (ret != sizeof(*expunge_count_r)) { - e_error(log->event, "pread(%s) read only %d of %d bytes", log->path, - (int)ret, (int)sizeof(*expunge_count_r)); - return -1; - } - return 0; -} - -struct fts_expunge_log_append_ctx * -fts_expunge_log_append_begin(struct fts_expunge_log *log, struct event *event) -{ - struct fts_expunge_log_append_ctx *ctx; - pool_t pool; - - pool = pool_alloconly_create("fts expunge log append", 1024); - ctx = p_new(pool, struct fts_expunge_log_append_ctx, 1); - ctx->log = log; - ctx->pool = pool; - ctx->event = event_create(event); - hash_table_create(&ctx->mailboxes, pool, 0, guid_128_hash, guid_128_cmp); - - if (log != NULL && fts_expunge_log_reopen_if_needed(log, TRUE) < 0) - ctx->failed = TRUE; - return ctx; -} - -static struct fts_expunge_log_mailbox * -fts_expunge_log_mailbox_alloc(struct fts_expunge_log_append_ctx *ctx, - const guid_128_t mailbox_guid) -{ - uint8_t *guid_p; - struct fts_expunge_log_mailbox *mailbox; - - mailbox = p_new(ctx->pool, struct fts_expunge_log_mailbox, 1); - guid_128_copy(mailbox->guid, mailbox_guid); - p_array_init(&mailbox->uids, ctx->pool, 16); - - guid_p = mailbox->guid; - hash_table_insert(ctx->mailboxes, guid_p, mailbox); - return mailbox; -} - -static struct fts_expunge_log_mailbox * -fts_expunge_log_append_mailbox(struct fts_expunge_log_append_ctx *ctx, - const guid_128_t mailbox_guid) -{ - const uint8_t *guid_p = mailbox_guid; - struct fts_expunge_log_mailbox *mailbox; - - if (ctx->prev_mailbox != NULL && - guid_128_equals(mailbox_guid, ctx->prev_mailbox->guid)) - mailbox = ctx->prev_mailbox; - else { - mailbox = hash_table_lookup(ctx->mailboxes, guid_p); - if (mailbox == NULL) - mailbox = fts_expunge_log_mailbox_alloc(ctx, mailbox_guid); - ctx->prev_mailbox = mailbox; - } - return mailbox; -} -void fts_expunge_log_append_next(struct fts_expunge_log_append_ctx *ctx, - const guid_128_t mailbox_guid, - uint32_t uid) -{ - struct fts_expunge_log_mailbox *mailbox; - - mailbox = fts_expunge_log_append_mailbox(ctx, mailbox_guid); - if (!seq_range_array_add(&mailbox->uids, uid)) - mailbox->uids_count++; -} -void fts_expunge_log_append_range(struct fts_expunge_log_append_ctx *ctx, - const guid_128_t mailbox_guid, - const struct seq_range *uids) -{ - struct fts_expunge_log_mailbox *mailbox; - - mailbox = fts_expunge_log_append_mailbox(ctx, mailbox_guid); - mailbox->uids_count += seq_range_array_add_range_count(&mailbox->uids, - uids->seq1, uids->seq2); - /* To be honest, an unbacked log doesn't need to maintain the uids_count, - but we don't know here if we're supporting an unbacked log or not, so we - have to maintain the value, just in case. - At the moment, the only caller of this function is for unbacked logs. */ -} -void fts_expunge_log_append_record(struct fts_expunge_log_append_ctx *ctx, - const struct fts_expunge_log_read_record *record) -{ - const struct seq_range *range; - /* FIXME: Optimise with a merge */ - 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, - uint32_t expunge_count, buffer_t *output) -{ - struct hash_iterate_context *iter; - uint8_t *guid_p; - struct fts_expunge_log_mailbox *mailbox; - struct fts_expunge_log_record *rec; - size_t rec_offset; - - iter = hash_table_iterate_init(ctx->mailboxes); - while (hash_table_iterate(iter, ctx->mailboxes, &guid_p, &mailbox)) { - rec_offset = output->used; - rec = buffer_append_space_unsafe(output, sizeof(*rec)); - memcpy(rec->guid, mailbox->guid, sizeof(rec->guid)); - - /* uint32_t expunge_uid_ranges[]; */ - buffer_append(output, array_front(&mailbox->uids), - array_count(&mailbox->uids) * - sizeof(struct seq_range)); - /* uint32_t expunge_count; */ - expunge_count += mailbox->uids_count; - buffer_append(output, &expunge_count, sizeof(expunge_count)); - - /* update the header now that we know the record contents */ - rec = buffer_get_space_unsafe(output, rec_offset, - output->used - rec_offset); - rec->record_size = output->used - rec_offset; - rec->checksum = crc32_data(&rec->record_size, - rec->record_size - - sizeof(rec->checksum)); - } - hash_table_iterate_deinit(&iter); -} - -static int -fts_expunge_log_write(struct fts_expunge_log_append_ctx *ctx) -{ - struct fts_expunge_log *log = ctx->log; - buffer_t *buf; - uint32_t expunge_count, *e; - int ret; - - /* Unbacked expunge logs cannot be written, by definition */ - i_assert(log != NULL); - - /* try to append to the latest file */ - if (fts_expunge_log_reopen_if_needed(log, TRUE) < 0) - return -1; - - if (fts_expunge_log_read_expunge_count(log, &expunge_count) < 0) - return -1; - - buf = buffer_create_dynamic(default_pool, 1024); - fts_expunge_log_export(ctx, expunge_count, buf); - /* the file was opened with O_APPEND, so this write() should be - appended atomically without any need for locking. */ - for (;;) { - if (write_full(log->fd, buf->data, buf->used) < 0) { - e_error(ctx->event, "write(%s) failed: %m", log->path); - if (ftruncate(log->fd, log->st.st_size) < 0) - e_error(ctx->event, "ftruncate(%s) failed: %m", log->path); - } - if ((ret = fts_expunge_log_reopen_if_needed(log, TRUE)) <= 0) - break; - /* the log was unlinked, so we'll need to write again to - the new file. the expunge_count needs to be reset to zero - from here. */ - e = buffer_get_space_unsafe(buf, buf->used - sizeof(uint32_t), - sizeof(uint32_t)); - i_assert(*e > expunge_count); - *e -= expunge_count; - expunge_count = 0; - } - buffer_free(&buf); - - if (ret == 0) { - /* finish by closing the log. this forces NFS to flush the - changes to disk without our having to explicitly play with - fsync() */ - if (close(log->fd) < 0) { - /* FIXME: we should ftruncate() in case there - were partial writes.. */ - e_error(ctx->event, "close(%s) failed: %m", log->path); - ret = -1; - } - log->fd = -1; - } - return ret; -} - -static int fts_expunge_log_append_finalize(struct fts_expunge_log_append_ctx **_ctx, - bool commit) -{ - struct fts_expunge_log_append_ctx *ctx = *_ctx; - int ret = ctx->failed ? -1 : 0; - - *_ctx = NULL; - if (commit && ret == 0) - ret = fts_expunge_log_write(ctx); - - hash_table_destroy(&ctx->mailboxes); - event_unref(&ctx->event); - pool_unref(&ctx->pool); - return ret; -} - -int fts_expunge_log_uid_count(struct fts_expunge_log *log, - unsigned int *expunges_r) -{ - int ret; - - if ((ret = fts_expunge_log_reopen_if_needed(log, FALSE)) <= 0) { - *expunges_r = 0; - return ret; - } - - return fts_expunge_log_read_expunge_count(log, expunges_r); -} - -int fts_expunge_log_append_commit(struct fts_expunge_log_append_ctx **_ctx) -{ - return fts_expunge_log_append_finalize(_ctx, TRUE); -} - -int fts_expunge_log_append_abort(struct fts_expunge_log_append_ctx **_ctx) -{ - return fts_expunge_log_append_finalize(_ctx, FALSE); -} - -struct fts_expunge_log_read_ctx * -fts_expunge_log_read_begin(struct fts_expunge_log *log) -{ - struct fts_expunge_log_read_ctx *ctx; - - ctx = i_new(struct fts_expunge_log_read_ctx, 1); - ctx->log = log; - if (fts_expunge_log_reopen_if_needed(log, FALSE) < 0) - ctx->failed = TRUE; - else if (log->fd != -1) - ctx->input = i_stream_create_fd(log->fd, SIZE_MAX); - ctx->unlink = TRUE; - return ctx; -} - -static bool -fts_expunge_log_record_size_is_valid(const struct fts_expunge_log_record *rec, - unsigned int *uids_size_r) -{ - if (rec->record_size < sizeof(*rec) + sizeof(uint32_t)*3) - return FALSE; - *uids_size_r = rec->record_size - sizeof(*rec) - sizeof(uint32_t); - return *uids_size_r % sizeof(uint32_t)*2 == 0; -} - -static void -fts_expunge_log_read_failure(struct fts_expunge_log_read_ctx *ctx, - unsigned int wanted_size) -{ - size_t size; - - if (ctx->input->stream_errno != 0) { - ctx->failed = TRUE; - e_error(ctx->log->event, "read(%s) failed: %s", ctx->log->path, - i_stream_get_error(ctx->input)); - } else { - size = i_stream_get_data_size(ctx->input); - ctx->corrupted = TRUE; - e_error(ctx->log->event, "Corrupted fts expunge log %s: " - "Unexpected EOF (read %zu / %u bytes)", - ctx->log->path, size, wanted_size); - } -} - -const struct fts_expunge_log_read_record * -fts_expunge_log_read_next(struct fts_expunge_log_read_ctx *ctx) -{ - const unsigned char *data; - const struct fts_expunge_log_record *rec; - unsigned int uids_size; - size_t size; - uint32_t checksum; - - if (ctx->input == NULL) - return NULL; - - /* initial read to try to get the record */ - (void)i_stream_read_bytes(ctx->input, &data, &size, IO_BLOCK_SIZE); - if (size == 0 && ctx->input->stream_errno == 0) { - /* expected EOF - mark the file as read by unlinking it */ - if (ctx->unlink) - i_unlink_if_exists(ctx->log->path); - - /* try reading again, in case something new was written */ - i_stream_sync(ctx->input); - (void)i_stream_read_bytes(ctx->input, &data, &size, - IO_BLOCK_SIZE); - } - if (size < sizeof(*rec)) { - if (size == 0 && ctx->input->stream_errno == 0) { - /* expected EOF */ - return NULL; - } - fts_expunge_log_read_failure(ctx, sizeof(*rec)); - return NULL; - } - rec = (const void *)data; - - if (!fts_expunge_log_record_size_is_valid(rec, &uids_size)) { - ctx->corrupted = TRUE; - e_error(ctx->log->event, "Corrupted fts expunge log %s: " - "Invalid record size: %u", - ctx->log->path, rec->record_size); - return NULL; - } - - /* read the entire record */ - while (size < rec->record_size) { - if (i_stream_read_bytes(ctx->input, &data, &size, rec->record_size) < 0) { - fts_expunge_log_read_failure(ctx, rec->record_size); - return NULL; - } - rec = (const void *)data; - } - - /* verify that the record checksum is valid */ - checksum = crc32_data(&rec->record_size, - rec->record_size - sizeof(rec->checksum)); - if (checksum != rec->checksum) { - ctx->corrupted = TRUE; - e_error(ctx->log->event, "Corrupted fts expunge log %s: " - "Record checksum mismatch: %u != %u", - ctx->log->path, checksum, rec->checksum); - return NULL; - } - - memcpy(ctx->read_rec.mailbox_guid, rec->guid, - sizeof(ctx->read_rec.mailbox_guid)); - /* create the UIDs array by pointing it directly into input - stream's buffer */ - buffer_create_from_const_data(&ctx->buffer, rec + 1, uids_size); - array_create_from_buffer(&ctx->read_rec.uids, &ctx->buffer, - sizeof(struct seq_range)); - - i_stream_skip(ctx->input, rec->record_size); - return &ctx->read_rec; -} - -int fts_expunge_log_read_end(struct fts_expunge_log_read_ctx **_ctx) -{ - struct fts_expunge_log_read_ctx *ctx = *_ctx; - int ret = ctx->failed ? -1 : (ctx->corrupted ? 0 : 1); - - *_ctx = NULL; - - if (ctx->corrupted) - i_unlink_if_exists(ctx->log->path); - - i_stream_unref(&ctx->input); - i_free(ctx); - return ret; -} - -int fts_expunge_log_flatten(const char *path, struct event *event, - struct fts_expunge_log_append_ctx **flattened_r) -{ - struct fts_expunge_log *read; - struct fts_expunge_log_read_ctx *read_ctx; - const struct fts_expunge_log_read_record *record; - struct fts_expunge_log_append_ctx *append; - int ret; - - i_assert(path != NULL && flattened_r != NULL); - read = fts_expunge_log_init(path, event); - - read_ctx = fts_expunge_log_read_begin(read); - read_ctx->unlink = FALSE; - - append = fts_expunge_log_append_begin(NULL, event); - while((record = fts_expunge_log_read_next(read_ctx)) != NULL) { - fts_expunge_log_append_record(append, record); - } - - if ((ret = fts_expunge_log_read_end(&read_ctx)) > 0) - *flattened_r = append; - else - fts_expunge_log_append_abort(&append); - fts_expunge_log_deinit(&read); - - return ret; -} -bool fts_expunge_log_contains(const struct fts_expunge_log_append_ctx *ctx, - const guid_128_t mailbox_guid, uint32_t uid) -{ - const struct fts_expunge_log_mailbox *mailbox; - const uint8_t *guid_p = mailbox_guid; - - mailbox = hash_table_lookup(ctx->mailboxes, guid_p); - if (mailbox == NULL) - return FALSE; - return seq_range_exists(&mailbox->uids, uid); -} -int 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); - if (mailbox == NULL) - return 0; /* may only remove things that exist */ - - mailbox->uids_count -= seq_range_array_remove_seq_range(&mailbox->uids, &record->uids); - return 1; -} -int fts_expunge_log_subtract(struct fts_expunge_log_append_ctx *from, - struct fts_expunge_log *subtract) -{ - unsigned int failures = 0; - 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) { - if (fts_expunge_log_append_remove(from, record) <= 0) - failures++; - } - if (failures > 0) - e_warning(from->event, - "Expunge log subtract ignored %u nonexistent mailbox GUIDs", - failures); - 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) -{ - /* NOTE: read_log->log may be NULL here */ - int ret; - struct fts_expunge_log *nlog = fts_expunge_log_init(path, read_log->event); - struct fts_expunge_log_append_ctx *nappend = - fts_expunge_log_append_begin(nlog, read_log->event); - - 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; -} diff --git a/src/plugins/fts/fts-expunge-log.h b/src/plugins/fts/fts-expunge-log.h deleted file mode 100644 index 418e3cf97f..0000000000 --- a/src/plugins/fts/fts-expunge-log.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef FTS_EXPUNGE_LOG -#define FTS_EXPUNGE_LOG - -#include "seq-range-array.h" -#include "guid.h" - -struct fts_expunge_log_read_record { - guid_128_t mailbox_guid; - ARRAY_TYPE(seq_range) uids; -}; - -struct fts_expunge_log *fts_expunge_log_init(const char *path, - struct event *event); -void fts_expunge_log_deinit(struct fts_expunge_log **log); - -struct fts_expunge_log_append_ctx * -fts_expunge_log_append_begin(struct fts_expunge_log *log, struct event *event); -void fts_expunge_log_append_next(struct fts_expunge_log_append_ctx *ctx, - const guid_128_t mailbox_guid, - uint32_t uid); -void fts_expunge_log_append_range(struct fts_expunge_log_append_ctx *ctx, - const guid_128_t mailbox_guid, - 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. Non-existence of UIDs is not an error, - non-existence of mailbox GUID causes an error return of 0. */ -int 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); - -int fts_expunge_log_uid_count(struct fts_expunge_log *log, - unsigned int *expunges_r); - -struct fts_expunge_log_read_ctx * -fts_expunge_log_read_begin(struct fts_expunge_log *log); -const struct fts_expunge_log_read_record * -fts_expunge_log_read_next(struct fts_expunge_log_read_ctx *ctx); -/* Returns 1 if all ok, 0 if there was corruption, -1 if I/O error. - If end() is called before reading all records, the log isn't unlinked. */ -int fts_expunge_log_read_end(struct fts_expunge_log_read_ctx **ctx); - -/* Read an entire log file, and flatten it into one hash of arrays. - The struct it returns cannot be written, as it has no backing store */ -int fts_expunge_log_flatten(const char *path, struct event *event, - 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. If non-existent mailbox GUIDs are - encountered, a warning will be logged. */ -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