dovecot-2.0: acl: Avoid opening two dict iterators at the same t...
dovecot at dovecot.org
dovecot at dovecot.org
Thu Sep 30 22:28:58 EEST 2010
details: http://hg.dovecot.org/dovecot-2.0/rev/ecc0bc80288c
changeset: 12215:ecc0bc80288c
user: Timo Sirainen <tss at iki.fi>
date: Thu Sep 30 20:28:54 2010 +0100
description:
acl: Avoid opening two dict iterators at the same time.
diffstat:
src/plugins/acl/acl-lookup-dict.c | 70 ++++++++++++++++++++--------------
1 files changed, 41 insertions(+), 29 deletions(-)
diffs (131 lines):
diff -r e3fbe13c0eab -r ecc0bc80288c src/plugins/acl/acl-lookup-dict.c
--- a/src/plugins/acl/acl-lookup-dict.c Thu Sep 30 19:18:13 2010 +0100
+++ b/src/plugins/acl/acl-lookup-dict.c Thu Sep 30 20:28:54 2010 +0100
@@ -24,12 +24,10 @@
pool_t pool;
struct acl_lookup_dict *dict;
+ pool_t iter_value_pool;
ARRAY_TYPE(const_string) iter_ids;
- struct dict_iterate_context *dict_iter;
- unsigned int iter_idx;
-
- const char *prefix;
- unsigned int prefix_len;
+ ARRAY_TYPE(const_string) iter_values;
+ unsigned int iter_idx, iter_value_idx;
unsigned int failed:1;
};
@@ -245,18 +243,35 @@
return ret;
}
-static void acl_lookup_dict_iterate_start(struct acl_lookup_dict_iter *iter)
+static void acl_lookup_dict_iterate_read(struct acl_lookup_dict_iter *iter)
{
- const char *const *idp;
+ struct dict_iterate_context *dict_iter;
+ const char *const *idp, *prefix, *key, *value;
+ unsigned int prefix_len;
idp = array_idx(&iter->iter_ids, iter->iter_idx);
iter->iter_idx++;
- iter->prefix = p_strconcat(iter->pool, DICT_PATH_SHARED
- DICT_SHARED_BOXES_PATH, *idp, "/", NULL);
- iter->prefix_len = strlen(iter->prefix);
+ iter->iter_value_idx = 0;
- iter->dict_iter = dict_iterate_init(iter->dict->dict, iter->prefix,
- DICT_ITERATE_FLAG_RECURSE);
+ prefix = t_strconcat(DICT_PATH_SHARED DICT_SHARED_BOXES_PATH,
+ *idp, "/", NULL);
+ prefix_len = strlen(prefix);
+
+ /* read all of it to memory. at least currently dict-proxy can support
+ only one iteration at a time, but the acl code can end up rebuilding
+ the dict, which opens another iteration. */
+ p_clear(iter->iter_value_pool);
+ array_clear(&iter->iter_values);
+ dict_iter = dict_iterate_init(iter->dict->dict, prefix,
+ DICT_ITERATE_FLAG_RECURSE);
+ while (dict_iterate(dict_iter, &key, &value)) {
+ i_assert(prefix_len < strlen(key));
+
+ key = p_strdup(iter->iter_value_pool, key + prefix_len);
+ array_append(&iter->iter_values, &key, 1);
+ }
+ if (dict_iterate_deinit(&dict_iter) < 0)
+ iter->failed = TRUE;
}
struct acl_lookup_dict_iter *
@@ -268,7 +283,7 @@
unsigned int i;
pool_t pool;
- pool = pool_alloconly_create("acl lookup dict iter", 512);
+ pool = pool_alloconly_create("acl lookup dict iter", 1024);
iter = p_new(pool, struct acl_lookup_dict_iter, 1);
iter->pool = pool;
iter->dict = dict;
@@ -279,6 +294,10 @@
id = p_strconcat(pool, "user/", dict->user->username, NULL);
array_append(&iter->iter_ids, &id, 1);
+ i_array_init(&iter->iter_values, 64);
+ iter->iter_value_pool =
+ pool_alloconly_create("acl lookup dict iter values", 1024);
+
/* get all groups we belong to */
if (auser->groups != NULL) {
for (i = 0; auser->groups[i] != NULL; i++) {
@@ -291,28 +310,23 @@
/* iterate through all identifiers that match us, start with the
first one */
if (dict->dict != NULL)
- acl_lookup_dict_iterate_start(iter);
+ acl_lookup_dict_iterate_read(iter);
return iter;
}
const char *
acl_lookup_dict_iterate_visible_next(struct acl_lookup_dict_iter *iter)
{
- const char *key, *value;
+ const char *const *keys;
+ unsigned int count;
- if (iter->dict_iter == NULL)
- return 0;
-
- if (dict_iterate(iter->dict_iter, &key, &value)) {
- i_assert(iter->prefix_len < strlen(key));
- return key + iter->prefix_len;
- }
- if (dict_iterate_deinit(&iter->dict_iter) < 0)
- iter->failed = TRUE;
+ keys = array_get(&iter->iter_values, &count);
+ if (iter->iter_value_idx < count)
+ return keys[iter->iter_value_idx++];
if (iter->iter_idx < array_count(&iter->iter_ids)) {
/* get to the next iterator */
- acl_lookup_dict_iterate_start(iter);
+ acl_lookup_dict_iterate_read(iter);
return acl_lookup_dict_iterate_visible_next(iter);
}
return NULL;
@@ -324,10 +338,8 @@
int ret = iter->failed ? -1 : 0;
*_iter = NULL;
- if (iter->dict_iter != NULL) {
- if (dict_iterate_deinit(&iter->dict_iter) < 0)
- ret = -1;
- }
+ array_free(&iter->iter_values);
+ pool_unref(&iter->iter_value_pool);
pool_unref(&iter->pool);
return ret;
}
More information about the dovecot-cvs
mailing list