dovecot-2.0: dict: Added dict_iterate_init_multiple().

dovecot at dovecot.org dovecot at dovecot.org
Thu Feb 18 08:43:38 EET 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/6aa76d89195d
changeset: 10752:6aa76d89195d
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Feb 18 08:43:35 2010 +0200
description:
dict: Added dict_iterate_init_multiple().

diffstat:

 src/dict/dict-commands.c    |   5 +++--
 src/lib-dict/dict-client.c  |  15 ++++++++++-----
 src/lib-dict/dict-file.c    |  48 ++++++++++++++++++++++++++++++++++++++----------
 src/lib-dict/dict-private.h |   2 +-
 src/lib-dict/dict-sql.c     |  42 ++++++++++++++++++++++++++++++------------
 src/lib-dict/dict.c         |  19 +++++++++++++++++--
 src/lib-dict/dict.h         |   3 +++
 7 files changed, 102 insertions(+), 32 deletions(-)

diffs (truncated from 310 to 300 lines):

diff -r 5ec28d7a5d13 -r 6aa76d89195d src/dict/dict-commands.c
--- a/src/dict/dict-commands.c	Thu Feb 18 08:20:22 2010 +0200
+++ b/src/dict/dict-commands.c	Thu Feb 18 08:43:35 2010 +0200
@@ -91,13 +91,14 @@
 	}
 
 	args = t_strsplit(line, "\t");
-	if (str_array_length(args) != 2) {
+	if (str_array_length(args) < 2) {
 		i_error("dict client: ITERATE: broken input");
 		return -1;
 	}
 
 	/* <flags> <path> */
-	conn->iter_ctx = dict_iterate_init(conn->dict, args[1], atoi(args[0]));
+	conn->iter_ctx = dict_iterate_init_multiple(conn->dict, args+1,
+						    atoi(args[0]));
 
 	o_stream_set_flush_callback(conn->output, cmd_iterate_flush, conn);
 	cmd_iterate_flush(conn);
diff -r 5ec28d7a5d13 -r 6aa76d89195d src/lib-dict/dict-client.c
--- a/src/lib-dict/dict-client.c	Thu Feb 18 08:20:22 2010 +0200
+++ b/src/lib-dict/dict-client.c	Thu Feb 18 08:43:35 2010 +0200
@@ -468,7 +468,7 @@
 }
 
 static struct dict_iterate_context *
-client_dict_iterate_init(struct dict *_dict, const char *path, 
+client_dict_iterate_init(struct dict *_dict, const char *const *paths,
 			 enum dict_iterate_flags flags)
 {
 	struct client_dict *dict = (struct client_dict *)_dict;
@@ -483,11 +483,16 @@
 	ctx->pool = pool_alloconly_create("client dict iteration", 512);
 
 	T_BEGIN {
-		const char *query;
+		string_t *query = t_str_new(256);
+		unsigned int i;
 
-		query = t_strdup_printf("%c%d\t%s\n", DICT_PROTOCOL_CMD_ITERATE,
-					flags, dict_client_escape(path));
-		if (client_dict_send_query(dict, query) < 0)
+		str_printfa(query, "%c%d", DICT_PROTOCOL_CMD_ITERATE, flags);
+		for (i = 0; paths[i] != NULL; i++) {
+			str_append_c(query, '\t');
+			str_append(query, dict_client_escape(paths[i]));
+		}
+		str_append_c(query, '\n');
+		if (client_dict_send_query(dict, str_c(query)) < 0)
 			ctx->failed = TRUE;
 	} T_END;
 	return &ctx->ctx;
diff -r 5ec28d7a5d13 -r 6aa76d89195d src/lib-dict/dict-file.c
--- a/src/lib-dict/dict-file.c	Thu Feb 18 08:20:22 2010 +0200
+++ b/src/lib-dict/dict-file.c	Thu Feb 18 08:43:35 2010 +0200
@@ -23,12 +23,17 @@
 	int fd;
 };
 
+struct file_dict_iterate_path {
+	const char *path;
+	unsigned int len;
+};
+
 struct file_dict_iterate_context {
 	struct dict_iterate_context ctx;
+	pool_t pool;
 
 	struct hash_iterate_context *iter;
-	char *path;
-	unsigned int path_len;
+	struct file_dict_iterate_path *paths;
 
 	enum dict_iterate_flags flags;
 	unsigned int failed:1;
@@ -163,16 +168,25 @@
 }
 
 static struct dict_iterate_context *
-file_dict_iterate_init(struct dict *_dict, const char *path,
+file_dict_iterate_init(struct dict *_dict, const char *const *paths,
 		       enum dict_iterate_flags flags)
 {
         struct file_dict_iterate_context *ctx;
 	struct file_dict *dict = (struct file_dict *)_dict;
+	unsigned int i, path_count;
+	pool_t pool;
 
-	ctx = i_new(struct file_dict_iterate_context, 1);
+	pool = pool_alloconly_create("file dict iterate", 256);
+	ctx = p_new(pool, struct file_dict_iterate_context, 1);
 	ctx->ctx.dict = _dict;
-	ctx->path = i_strdup(path);
-	ctx->path_len = strlen(path);
+	ctx->pool = pool;
+
+	for (path_count = 0; paths[path_count] != NULL; path_count++) ;
+	ctx->paths = p_new(pool, struct file_dict_iterate_path, path_count + 1);
+	for (i = 0; i < path_count; i++) {
+		ctx->paths[i].path = p_strdup(pool, paths[i]);
+		ctx->paths[i].len = strlen(paths[i]);
+	}
 	ctx->flags = flags;
 	ctx->iter = hash_table_iterate_init(dict->hash);
 
@@ -181,19 +195,34 @@
 	return &ctx->ctx;
 }
 
+static const struct file_dict_iterate_path *
+file_dict_iterate_find_path(struct file_dict_iterate_context *ctx,
+			    const char *key)
+{
+	unsigned int i;
+
+	for (i = 0; ctx->paths[i].path != NULL; i++) {
+		if (strncmp(ctx->paths[i].path, key, ctx->paths[i].len) == 0)
+			return &ctx->paths[i];
+	}
+	return NULL;
+}
+
 static bool file_dict_iterate(struct dict_iterate_context *_ctx,
 			      const char **key_r, const char **value_r)
 {
 	struct file_dict_iterate_context *ctx =
 		(struct file_dict_iterate_context *)_ctx;
+	const struct file_dict_iterate_path *path;
 	void *key, *value;
 
 	while (hash_table_iterate(ctx->iter, &key, &value)) {
-		if (strncmp(ctx->path, key, ctx->path_len) != 0)
+		path = file_dict_iterate_find_path(ctx, key);
+		if (path == NULL)
 			continue;
 
 		if ((ctx->flags & DICT_ITERATE_FLAG_RECURSE) == 0 &&
-		    strchr((char *)key + ctx->path_len, '/') != NULL)
+		    strchr((char *)key + path->len, '/') != NULL)
 			continue;
 
 		*key_r = key;
@@ -210,8 +239,7 @@
 	int ret = ctx->failed ? -1 : 0;
 
 	hash_table_iterate_deinit(&ctx->iter);
-	i_free(ctx->path);
-	i_free(ctx);
+	pool_unref(&ctx->pool);
 	return ret;
 }
 
diff -r 5ec28d7a5d13 -r 6aa76d89195d src/lib-dict/dict-private.h
--- a/src/lib-dict/dict-private.h	Thu Feb 18 08:20:22 2010 +0200
+++ b/src/lib-dict/dict-private.h	Thu Feb 18 08:43:35 2010 +0200
@@ -14,7 +14,7 @@
 		      const char *key, const char **value_r);
 
 	struct dict_iterate_context *
-		(*iterate_init)(struct dict *dict, const char *path,
+		(*iterate_init)(struct dict *dict, const char *const *paths,
 				enum dict_iterate_flags flags);
 	bool (*iterate)(struct dict_iterate_context *ctx,
 			const char **key_r, const char **value_r);
diff -r 5ec28d7a5d13 -r 6aa76d89195d src/lib-dict/dict-sql.c
--- a/src/lib-dict/dict-sql.c	Thu Feb 18 08:20:22 2010 +0200
+++ b/src/lib-dict/dict-sql.c	Thu Feb 18 08:43:35 2010 +0200
@@ -35,13 +35,16 @@
 
 struct sql_dict_iterate_context {
 	struct dict_iterate_context ctx;
+	pool_t pool;
+
 	enum dict_iterate_flags flags;
-	char *path;
+	const char **paths;
 
 	struct sql_result *result;
 	string_t *key;
 	const struct dict_sql_map *map;
 	unsigned int key_prefix_len, pattern_prefix_len, next_map_idx;
+	unsigned int path_idx;
 	bool failed;
 };
 
@@ -313,16 +316,24 @@
 	t_array_init(values, dict->set->max_field_count);
 	maps = array_get(&dict->set->maps, &count);
 	for (i = ctx->next_map_idx; i < count; i++) {
-		if (dict_sql_map_match(&maps[i], ctx->path,
+		if (dict_sql_map_match(&maps[i], ctx->paths[ctx->path_idx],
 				       values, &pat_len, &path_len, TRUE) &&
 		    ((ctx->flags & DICT_ITERATE_FLAG_RECURSE) != 0 ||
 		     array_count(values)+1 >= array_count(&maps[i].sql_fields))) {
 			ctx->key_prefix_len = path_len;
 			ctx->pattern_prefix_len = pat_len;
 			ctx->next_map_idx = i + 1;
+
+			str_truncate(ctx->key, 0);
+			str_append(ctx->key, ctx->paths[ctx->path_idx]);
 			return &maps[i];
 		}
 	}
+
+	/* try the next path, if there is any */
+	ctx->path_idx++;
+	if (ctx->paths[ctx->path_idx] != NULL)
+		return sql_dict_iterate_find_next_map(ctx, values);
 	return NULL;
 }
 
@@ -358,7 +369,8 @@
 
 		recurse_type = (ctx->flags & DICT_ITERATE_FLAG_RECURSE) == 0 ?
 			SQL_DICT_RECURSE_ONE : SQL_DICT_RECURSE_FULL;
-		sql_dict_where_build(dict, map, &values, ctx->path[0],
+		sql_dict_where_build(dict, map, &values,
+				     ctx->paths[ctx->path_idx][0],
 				     recurse_type, query);
 
 		if ((ctx->flags & DICT_ITERATE_FLAG_SORT_BY_KEY) != 0) {
@@ -378,20 +390,28 @@
 }
 
 static struct dict_iterate_context *
-sql_dict_iterate_init(struct dict *_dict, const char *path, 
+sql_dict_iterate_init(struct dict *_dict, const char *const *paths,
 		      enum dict_iterate_flags flags)
 {
 	struct sql_dict_iterate_context *ctx;
+	unsigned int i, path_count;
+	pool_t pool;
 
-	ctx = i_new(struct sql_dict_iterate_context, 1);
+	pool = pool_alloconly_create("sql dict iterate", 512);
+	ctx = p_new(pool, struct sql_dict_iterate_context, 1);
 	ctx->ctx.dict = _dict;
-	ctx->path = i_strdup(path);
+	ctx->pool = pool;
 	ctx->flags = flags;
-	ctx->key = str_new(default_pool, 256);
-	str_append(ctx->key, ctx->path);
 
+	for (path_count = 0; paths[path_count] != NULL; path_count++) ;
+	ctx->paths = p_new(pool, const char *, path_count + 1);
+	for (i = 0; i < path_count; i++)
+		ctx->paths[i] = p_strdup(pool, paths[i]);
+
+	ctx->key = str_new(pool, 256);
 	if (!sql_dict_iterate_next_query(ctx)) {
-		i_error("sql dict iterate: Invalid/unmapped path: %s", path);
+		i_error("sql dict iterate: Invalid/unmapped path: %s",
+			paths[0]);
 		ctx->result = NULL;
 		return &ctx->ctx;
 	}
@@ -457,9 +477,7 @@
 
 	if (ctx->result != NULL)
 		sql_result_unref(ctx->result);
-	str_free(&ctx->key);
-	i_free(ctx->path);
-	i_free(ctx);
+	pool_unref(&ctx->pool);
 	return ret;
 }
 
diff -r 5ec28d7a5d13 -r 6aa76d89195d src/lib-dict/dict.c
--- a/src/lib-dict/dict.c	Thu Feb 18 08:20:22 2010 +0200
+++ b/src/lib-dict/dict.c	Thu Feb 18 08:43:35 2010 +0200
@@ -118,8 +118,23 @@
 dict_iterate_init(struct dict *dict, const char *path, 
 		  enum dict_iterate_flags flags)
 {
-	i_assert(dict_key_prefix_is_valid(path));
-	return dict->v.iterate_init(dict, path, flags);
+	const char *paths[2];
+
+	paths[0] = path;
+	paths[1] = NULL;
+	return dict_iterate_init_multiple(dict, paths, flags);
+}
+
+struct dict_iterate_context *
+dict_iterate_init_multiple(struct dict *dict, const char *const *paths,
+			   enum dict_iterate_flags flags)
+{
+	unsigned int i;
+
+	i_assert(paths[0] != NULL);
+	for (i = 0; paths[i] != NULL; i++)
+		i_assert(dict_key_prefix_is_valid(paths[i]));
+	return dict->v.iterate_init(dict, paths, flags);
 }
 
 bool dict_iterate(struct dict_iterate_context *ctx,
diff -r 5ec28d7a5d13 -r 6aa76d89195d src/lib-dict/dict.h
--- a/src/lib-dict/dict.h	Thu Feb 18 08:20:22 2010 +0200
+++ b/src/lib-dict/dict.h	Thu Feb 18 08:43:35 2010 +0200


More information about the dovecot-cvs mailing list