dovecot-2.2: mdbox: Added "mdbox_deleted" storage, which can be ...

dovecot at dovecot.org dovecot at dovecot.org
Tue Oct 29 21:08:20 EET 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/c238c55479c8
changeset: 16895:c238c55479c8
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Oct 29 21:08:07 2013 +0200
description:
mdbox: Added "mdbox_deleted" storage, which can be used to access messages with refcount=0
For example:
doveadm import mdbox_deleted:~/mdbox "" mailbox inbox subject oops

diffstat:

 src/lib-storage/index/dbox-multi/Makefile.am             |    1 +
 src/lib-storage/index/dbox-multi/mdbox-deleted-storage.c |  320 +++++++++++++++
 src/lib-storage/index/dbox-multi/mdbox-map.c             |   27 +-
 src/lib-storage/index/dbox-multi/mdbox-map.h             |    8 +
 src/lib-storage/index/dbox-multi/mdbox-storage.c         |   14 +-
 src/lib-storage/index/dbox-multi/mdbox-storage.h         |   10 +
 6 files changed, 369 insertions(+), 11 deletions(-)

diffs (truncated from 499 to 300 lines):

diff -r 2b3948fa4a09 -r c238c55479c8 src/lib-storage/index/dbox-multi/Makefile.am
--- a/src/lib-storage/index/dbox-multi/Makefile.am	Tue Oct 29 21:07:28 2013 +0200
+++ b/src/lib-storage/index/dbox-multi/Makefile.am	Tue Oct 29 21:08:07 2013 +0200
@@ -12,6 +12,7 @@
 	-I$(top_srcdir)/src/lib-storage/index/dbox-common
 
 libstorage_dbox_multi_la_SOURCES = \
+	mdbox-deleted-storage.c \
 	mdbox-file.c \
 	mdbox-mail.c \
 	mdbox-map.c \
diff -r 2b3948fa4a09 -r c238c55479c8 src/lib-storage/index/dbox-multi/mdbox-deleted-storage.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-storage/index/dbox-multi/mdbox-deleted-storage.c	Tue Oct 29 21:08:07 2013 +0200
@@ -0,0 +1,320 @@
+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "ioloop.h"
+#include "mkdir-parents.h"
+#include "master-service.h"
+#include "mail-index-modseq.h"
+#include "mail-index-alloc-cache.h"
+#include "mailbox-log.h"
+#include "mailbox-list-private.h"
+#include "mail-copy.h"
+#include "dbox-mail.h"
+#include "dbox-save.h"
+#include "mdbox-map.h"
+#include "mdbox-file.h"
+#include "mdbox-sync.h"
+#include "mdbox-storage-rebuild.h"
+#include "mdbox-storage.h"
+
+extern struct mail_storage mdbox_deleted_storage;
+extern struct mailbox mdbox_deleted_mailbox;
+extern struct dbox_storage_vfuncs mdbox_deleted_dbox_storage_vfuncs;
+
+static struct mail_storage *mdbox_deleted_storage_alloc(void)
+{
+	struct mdbox_storage *storage;
+	pool_t pool;
+
+	pool = pool_alloconly_create("mdbox deleted storage", 2048);
+	storage = p_new(pool, struct mdbox_storage, 1);
+	storage->storage.v = mdbox_dbox_storage_vfuncs;
+	storage->storage.storage = mdbox_deleted_storage;
+	storage->storage.storage.pool = pool;
+	return &storage->storage.storage;
+}
+
+static struct mailbox *
+mdbox_deleted_mailbox_alloc(struct mail_storage *storage,
+			    struct mailbox_list *list,
+			    const char *vname, enum mailbox_flags flags)
+{
+	struct mdbox_mailbox *mbox;
+	pool_t pool;
+
+	flags |= MAILBOX_FLAG_READONLY | MAILBOX_FLAG_NO_INDEX_FILES;
+
+	pool = pool_alloconly_create("mdbox deleted mailbox", 1024*3);
+	mbox = p_new(pool, struct mdbox_mailbox, 1);
+	mbox->box = mdbox_deleted_mailbox;
+	mbox->box.pool = pool;
+	mbox->box.storage = storage;
+	mbox->box.list = list;
+	mbox->box.mail_vfuncs = &mdbox_mail_vfuncs;
+
+	index_storage_mailbox_alloc(&mbox->box, vname, flags, MAIL_INDEX_PREFIX);
+
+	mbox->storage = (struct mdbox_storage *)storage;
+	return &mbox->box;
+}
+
+static int
+mdbox_deleted_mailbox_create_indexes(struct mailbox *box,
+				     const struct mailbox_update *update,
+				     struct mail_index_transaction *trans)
+{
+	struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
+	struct mail_index_transaction *new_trans = NULL;
+	uint32_t uid_validity = ioloop_time;
+	uint32_t uid_next = 1;
+
+	if (update != NULL && update->uid_validity != 0)
+		uid_validity = update->uid_validity;
+
+	if (trans == NULL) {
+		new_trans = mail_index_transaction_begin(box->view, 0);
+		trans = new_trans;
+	}
+
+	mail_index_update_header(trans,
+		offsetof(struct mail_index_header, uid_validity),
+		&uid_validity, sizeof(uid_validity), TRUE);
+	mail_index_update_header(trans,
+		offsetof(struct mail_index_header, next_uid),
+		&uid_next, sizeof(uid_next), TRUE);
+	mbox->creating = TRUE;
+	mdbox_update_header(mbox, trans, update);
+	mbox->creating = FALSE;
+
+	if (new_trans != NULL) {
+		if (mail_index_transaction_commit(&new_trans) < 0) {
+			mailbox_set_index_error(box);
+			return -1;
+		}
+	}
+	return 0;
+}
+
+static const char *
+mdbox_get_attachment_path_suffix(struct dbox_file *file ATTR_UNUSED)
+{
+	return "";
+}
+
+static int
+mdbox_deleted_mailbox_get_metadata(struct mailbox *box,
+				   enum mailbox_metadata_items items,
+				   struct mailbox_metadata *metadata_r)
+{
+	if (index_mailbox_get_metadata(box, items, metadata_r) < 0)
+		return -1;
+
+	if ((items & MAILBOX_METADATA_GUID) != 0)
+		guid_128_generate(metadata_r->guid);
+	return 0;
+}
+
+static struct mail_save_context *
+mdbox_deleted_save_alloc(struct mailbox_transaction_context *t)
+{
+	struct mail_save_context *ctx;
+
+	ctx = i_new(struct mail_save_context, 1);
+	ctx->transaction = t;
+	return ctx;
+}
+
+static int
+mdbox_deleted_save_begin(struct mail_save_context *ctx,
+			 struct istream *input ATTR_UNUSED)
+{
+	mail_storage_set_error(ctx->transaction->box->storage,
+		MAIL_ERROR_NOTPOSSIBLE, "mdbox_deleted doesn't support saving mails");
+	return -1;
+}
+
+static int
+mdbox_deleted_save_continue(struct mail_save_context *ctx ATTR_UNUSED)
+{
+	return -1;
+}
+
+static int mdbox_deleted_save_finish(struct mail_save_context *ctx)
+{
+	index_save_context_free(ctx);
+	return -1;
+}
+
+static void
+mdbox_deleted_save_cancel(struct mail_save_context *ctx)
+{
+	index_save_context_free(ctx);
+}
+
+static int mdbox_deleted_sync(struct mdbox_mailbox *mbox,
+			      enum mdbox_sync_flags flags)
+{
+        struct mail_index_sync_ctx *index_sync_ctx;
+	struct mail_index_view *sync_view;
+	struct mail_index_transaction *trans;
+	struct mdbox_mail_index_record rec;
+	struct mdbox_map_mail_index_record map_rec;
+	uint16_t refcount;
+	uint32_t map_seq, map_count, seq, uid = 0;
+	int ret = 0;
+
+	if (mbox->mdbox_deleted_synced) {
+		/* don't bother supporting incremental syncs */
+		return 0;
+	}
+	if (!mbox->box.inbox_user && mbox->box.name[0] != '\0') {
+		/* since mailbox list currently shows all the existing
+		   mailboxes, we don't want all of them to list the deleted
+		   messages. only show messages in user's INBOX or the
+		   namespace prefix. */
+		return 0;
+	}
+
+	if (mdbox_map_open(mbox->storage->map) < 0)
+		return -1;
+
+	if (mdbox_deleted_mailbox_create_indexes(&mbox->box, NULL, NULL) < 0)
+		return -1;
+
+	memset(&rec, 0, sizeof(rec));
+	rec.save_date = ioloop_time;
+
+	if (mail_index_sync_begin(mbox->box.index, &index_sync_ctx,
+				  &sync_view, &trans, flags) < 0) {
+		mailbox_set_index_error(&mbox->box);
+		return -1;
+	}
+
+	map_count = mdbox_map_get_messages_count(mbox->storage->map);
+	for (map_seq = 1; map_seq <= map_count; map_seq++) {
+		if (mdbox_map_lookup_seq_full(mbox->storage->map, map_seq,
+					      &map_rec, &refcount) < 0) {
+			ret = -1;
+			break;
+		}
+		if (refcount == 0) {
+			rec.map_uid = mdbox_map_lookup_uid(mbox->storage->map,
+							   map_seq);
+			mail_index_append(trans, ++uid, &seq);
+			mail_index_update_ext(trans, seq,
+					      mbox->ext_id, &rec, NULL);
+		}
+	}
+
+	if (ret < 0)
+		mail_index_sync_rollback(&index_sync_ctx);
+	else {
+		if (mail_index_sync_commit(&index_sync_ctx) < 0) {
+			mailbox_set_index_error(&mbox->box);
+			ret = -1;
+		} else {
+			mbox->mdbox_deleted_synced = TRUE;
+		}
+	}
+	return ret;
+}
+
+static struct mailbox_sync_context *
+mdbox_deleted_storage_sync_init(struct mailbox *box,
+				enum mailbox_sync_flags flags)
+{
+	struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
+	enum mdbox_sync_flags mdbox_sync_flags = 0;
+	int ret = 0;
+
+	if (!box->opened) {
+		if (mailbox_open(box) < 0)
+			ret = -1;
+	}
+
+	if (ret == 0 && (index_mailbox_want_full_sync(&mbox->box, flags) ||
+			 mbox->storage->corrupted))
+		ret = mdbox_deleted_sync(mbox, mdbox_sync_flags);
+
+	return index_mailbox_sync_init(box, flags, ret < 0);
+}
+
+struct mail_storage mdbox_deleted_storage = {
+	.name = MDBOX_DELETED_STORAGE_NAME,
+	.class_flags = MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT |
+		MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_GUIDS |
+		MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_SAVE_GUIDS |
+		MAIL_STORAGE_CLASS_FLAG_BINARY_DATA,
+
+	.v = {
+                mdbox_get_setting_parser_info,
+		mdbox_deleted_storage_alloc,
+		mdbox_storage_create,
+		mdbox_storage_destroy,
+		NULL,
+		dbox_storage_get_list_settings,
+		NULL,
+		mdbox_deleted_mailbox_alloc,
+		NULL
+	}
+};
+
+struct mailbox mdbox_deleted_mailbox = {
+	.v = {
+		index_storage_is_readonly,
+		index_storage_mailbox_enable,
+		index_storage_mailbox_exists,
+		mdbox_mailbox_open,
+		index_storage_mailbox_close,
+		index_storage_mailbox_free,
+		dbox_mailbox_create,
+		index_storage_mailbox_update,
+		index_storage_mailbox_delete,
+		index_storage_mailbox_rename,
+		index_storage_get_status,
+		mdbox_deleted_mailbox_get_metadata,
+		index_storage_set_subscribed,
+		index_storage_attribute_set,
+		index_storage_attribute_get,
+		index_storage_attribute_iter_init,
+		index_storage_attribute_iter_next,
+		index_storage_attribute_iter_deinit,
+		index_storage_list_index_has_changed,
+		index_storage_list_index_update_sync,
+		mdbox_deleted_storage_sync_init,


More information about the dovecot-cvs mailing list