view src/lib-storage/index/index-attribute.c @ 15272:ca10d2e8d8e3

lib-storage: Moved mail attribute dict to struct mail_storage. This also means that index_storage_destroy() must always be called, so removed now unnecessary mail_storage.destroy=NULL checks.
author Timo Sirainen <tss@iki.fi>
date Mon, 29 Oct 2012 14:50:11 +0200
parents a436e4a7503b
children 4c84efce3a94
line wrap: on
line source

/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "dict.h"
#include "index-storage.h"

struct index_storage_attribute_iter {
	struct mailbox_attribute_iter iter;
	struct dict_iterate_context *diter;
	char *prefix;
	unsigned int prefix_len;
	bool dict_disabled;
};

static int index_storage_get_dict(struct mailbox *box, struct dict **dict_r,
				  const char **mailbox_prefix_r)
{
	struct mail_storage *storage = box->storage;
	struct mailbox_metadata metadata;
	const char *error;

	if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0)
		return -1;
	*mailbox_prefix_r = guid_128_to_string(metadata.guid);

	if (storage->_attr_dict != NULL) {
		*dict_r = storage->_attr_dict;
		return 0;
	}
	if (*storage->set->mail_attribute_dict == '\0') {
		mail_storage_set_error(storage, MAIL_ERROR_NOTPOSSIBLE,
				       "Mailbox attributes not enabled");
		return -1;
	}
	if (storage->attr_dict_failed) {
		mail_storage_set_internal_error(storage);
		return -1;
	}

	if (dict_init(storage->set->mail_attribute_dict,
		      DICT_DATA_TYPE_STRING,
		      storage->user->username,
		      storage->user->set->base_dir,
		      &storage->_attr_dict, &error) < 0) {
		mail_storage_set_critical(storage,
			"mail_attribute_dict: dict_init(%s) failed: %s",
			storage->set->mail_attribute_dict, error);
		storage->attr_dict_failed = TRUE;
		return -1;
	}
	*dict_r = storage->_attr_dict;
	return 0;
}

static const char *
key_get_prefixed(enum mail_attribute_type type, const char *mailbox_prefix,
		 const char *key)
{
	switch (type) {
	case MAIL_ATTRIBUTE_TYPE_PRIVATE:
		return t_strconcat(DICT_PATH_PRIVATE, mailbox_prefix, "/",
				   key, NULL);
	case MAIL_ATTRIBUTE_TYPE_SHARED:
		return t_strconcat(DICT_PATH_SHARED, mailbox_prefix, "/",
				   key, NULL);
	}
	i_unreached();
}

int index_storage_attribute_set(struct mailbox *box,
				enum mail_attribute_type type,
				const char *key, const char *value)
{
	struct dict_transaction_context *dtrans;
	struct dict *dict;
	const char *mailbox_prefix;

	if (index_storage_get_dict(box, &dict, &mailbox_prefix) < 0)
		return -1;

	T_BEGIN {
		key = key_get_prefixed(type, mailbox_prefix, key);
		dtrans = dict_transaction_begin(dict);
		if (value != NULL)
			dict_set(dtrans, key, value);
		else
			dict_unset(dtrans, key);
	} T_END;
	if (dict_transaction_commit(&dtrans) < 0) {
		mail_storage_set_internal_error(box->storage);
		return -1;
	}
	return 0;
}

int index_storage_attribute_get(struct mailbox *box,
				enum mail_attribute_type type,
				const char *key, const char **value_r)
{
	struct dict *dict;
	const char *mailbox_prefix;
	int ret;

	if (index_storage_get_dict(box, &dict, &mailbox_prefix) < 0)
		return -1;

	ret = dict_lookup(dict, pool_datastack_create(),
			  key_get_prefixed(type, mailbox_prefix, key), value_r);
	if (ret < 0) {
		mail_storage_set_internal_error(box->storage);
		return -1;
	}
	if (ret == 0)
		*value_r = NULL;
	return ret;
}

struct mailbox_attribute_iter *
index_storage_attribute_iter_init(struct mailbox *box,
				  enum mail_attribute_type type,
				  const char *prefix)
{
	struct index_storage_attribute_iter *iter;
	struct dict *dict;
	const char *mailbox_prefix;

	iter = i_new(struct index_storage_attribute_iter, 1);
	iter->iter.box = box;
	if (index_storage_get_dict(box, &dict, &mailbox_prefix) < 0) {
		if (mailbox_get_last_mail_error(box) == MAIL_ERROR_NOTPOSSIBLE)
			iter->dict_disabled = TRUE;
	} else {
		iter->prefix = i_strdup(key_get_prefixed(type, mailbox_prefix,
							 prefix));
		iter->prefix_len = strlen(iter->prefix);
		iter->diter = dict_iterate_init(dict, iter->prefix,
						DICT_ITERATE_FLAG_RECURSE |
						DICT_ITERATE_FLAG_NO_VALUE);
	}
	return &iter->iter;
}

const char *
index_storage_attribute_iter_next(struct mailbox_attribute_iter *_iter)
{
	struct index_storage_attribute_iter *iter =
		(struct index_storage_attribute_iter *)_iter;
	const char *key, *value;

	if (iter->diter == NULL || !dict_iterate(iter->diter, &key, &value))
		return NULL;

	i_assert(strncmp(key, iter->prefix, iter->prefix_len) == 0);
	key += iter->prefix_len;
	return key;
}

int index_storage_attribute_iter_deinit(struct mailbox_attribute_iter *_iter)
{
	struct index_storage_attribute_iter *iter =
		(struct index_storage_attribute_iter *)_iter;
	int ret;

	if (iter->diter == NULL) {
		ret = iter->dict_disabled ? 0 : -1;
	} else {
		if ((ret = dict_iterate_deinit(&iter->diter)) < 0)
			mail_storage_set_internal_error(_iter->box->storage);
	}
	i_free(iter->prefix);
	i_free(iter);
	return ret;
}