]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
dict: Added dict_iterate_init_multiple().
authorTimo Sirainen <tss@iki.fi>
Thu, 18 Feb 2010 06:43:35 +0000 (08:43 +0200)
committerTimo Sirainen <tss@iki.fi>
Thu, 18 Feb 2010 06:43:35 +0000 (08:43 +0200)
--HG--
branch : HEAD

src/dict/dict-commands.c
src/lib-dict/dict-client.c
src/lib-dict/dict-file.c
src/lib-dict/dict-private.h
src/lib-dict/dict-sql.c
src/lib-dict/dict.c
src/lib-dict/dict.h

index ca523d63bc12258e778085368e6427788e113d1c..202fa7015e2096fcad5ff25eeeffe69b6e9cae07 100644 (file)
@@ -91,13 +91,14 @@ static int cmd_iterate(struct dict_connection *conn, const char *line)
        }
 
        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);
index 2e30f2a32bbc67312c3df6e9e251df4fc606de40..ebda4d9c1af057ef53c363cb3288314130bfe61d 100644 (file)
@@ -468,7 +468,7 @@ static int client_dict_lookup(struct dict *_dict, pool_t pool,
 }
 
 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 @@ client_dict_iterate_init(struct dict *_dict, const char *path,
        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;
index fea27c9965ba30996e26049c122f4d38a33ae111..cbd29a38a8c3aaf3ac1b77b8fcf057e4234e9504 100644 (file)
@@ -23,12 +23,17 @@ struct file_dict {
        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 int file_dict_lookup(struct dict *_dict, pool_t pool,
 }
 
 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 @@ file_dict_iterate_init(struct dict *_dict, const char *path,
        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 @@ static int file_dict_iterate_deinit(struct dict_iterate_context *_ctx)
        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;
 }
 
index 1ff040bd00523952fbf00937927dd9683499b266..98a3861adc51e6f72118bd9f5b439fe54e60ad91 100644 (file)
@@ -14,7 +14,7 @@ struct dict_vfuncs {
                      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);
index 686369354d16c6a3f1b1195bef215eaff5c9ee65..2fba8f9b3cfb0e7c8d951c8adc8fabef5d59cf27 100644 (file)
@@ -35,13 +35,16 @@ struct sql_dict {
 
 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 @@ sql_dict_iterate_find_next_map(struct sql_dict_iterate_context *ctx,
        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 @@ static bool sql_dict_iterate_next_query(struct sql_dict_iterate_context *ctx)
 
                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 bool sql_dict_iterate_next_query(struct sql_dict_iterate_context *ctx)
 }
 
 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 @@ static int sql_dict_iterate_deinit(struct dict_iterate_context *_ctx)
 
        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;
 }
 
index 6f52615a0911e195d6ab5be8fdb2e27e58db8c27..b82958ddf837134bccd8f3454fc44a89eaec7474 100644 (file)
@@ -118,8 +118,23 @@ struct dict_iterate_context *
 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,
index 3f8072dd4c28a11e8ee11f935d8ff9bb882bf677..684cac51157c20c054aed48f321f5224a4dac6a4 100644 (file)
@@ -48,6 +48,9 @@ int dict_lookup(struct dict *dict, pool_t pool,
 struct dict_iterate_context *
 dict_iterate_init(struct dict *dict, const char *path, 
                  enum dict_iterate_flags flags);
+struct dict_iterate_context *
+dict_iterate_init_multiple(struct dict *dict, const char *const *paths,
+                          enum dict_iterate_flags flags);
 bool dict_iterate(struct dict_iterate_context *ctx,
                  const char **key_r, const char **value_r);
 /* Returns 0 = ok, -1 = iteration failed */