{
const char *const *args;
unsigned int flags;
+ uint64_t max_rows;
args = t_strsplit_tabescaped(line);
- if (str_array_length(args) < 2 ||
- str_to_uint(args[0], &flags) < 0) {
+ if (str_array_length(args) < 3 ||
+ str_to_uint(args[0], &flags) < 0 ||
+ str_to_uint64(args[1], &max_rows) < 0) {
i_error("dict client: ITERATE: broken input");
return -1;
}
- /* <flags> <path> */
+ /* <flags> <max_rows> <path> */
flags |= DICT_ITERATE_FLAG_ASYNC;
- cmd->iter = dict_iterate_init_multiple(cmd->conn->dict, args+1, flags);
+ cmd->iter = dict_iterate_init_multiple(cmd->conn->dict, args+2, flags);
cmd->iter_flags = flags;
+ if (max_rows > 0)
+ dict_iterate_set_limit(cmd->iter, max_rows);
dict_iterate_set_async_callback(cmd->iter, cmd_iterate_callback, cmd);
dict_connection_cmd_output_more(cmd);
return 1;
struct client_dict_iterate_context {
struct dict_iterate_context ctx;
char *error;
+ const char **paths;
enum dict_iterate_flags flags;
pool_t results_pool;
ARRAY(struct client_dict_iter_result) results;
unsigned int result_idx;
+ bool cmd_sent;
bool seen_results;
bool finished;
bool deinit;
client_dict_iterate_init(struct dict *_dict, const char *const *paths,
enum dict_iterate_flags flags)
{
- struct client_dict *dict = (struct client_dict *)_dict;
struct client_dict_iterate_context *ctx;
- struct client_dict_cmd *cmd;
- string_t *query = t_str_new(256);
- unsigned int i;
ctx = i_new(struct client_dict_iterate_context, 1);
ctx->ctx.dict = _dict;
ctx->results_pool = pool_alloconly_create("client dict iteration", 512);
ctx->flags = flags;
+ ctx->paths = p_strarray_dup(system_pool, paths);
i_array_init(&ctx->results, 64);
+ return &ctx->ctx;
+}
+
+static void
+client_dict_iterate_cmd_send(struct client_dict_iterate_context *ctx)
+{
+ struct client_dict *dict = (struct client_dict *)ctx->ctx.dict;
+ struct client_dict_cmd *cmd;
+ unsigned int i;
+ string_t *query = t_str_new(256);
- str_printfa(query, "%c%d", DICT_PROTOCOL_CMD_ITERATE, flags);
- for (i = 0; paths[i] != NULL; i++) {
+ /* we can't do this query in _iterate_init(), because
+ _set_limit() hasn't been called yet at that point. */
+ str_printfa(query, "%c%d\t%llu", DICT_PROTOCOL_CMD_ITERATE, ctx->flags,
+ (unsigned long long)ctx->ctx.max_rows);
+ for (i = 0; ctx->paths[i] != NULL; i++) {
str_append_c(query, '\t');
- str_append(query, str_tabescape(paths[i]));
+ str_append(query, str_tabescape(ctx->paths[i]));
}
cmd = client_dict_cmd_init(dict, str_c(query));
cmd->retry_errors = TRUE;
client_dict_cmd_send(dict, &cmd, NULL);
- return &ctx->ctx;
}
static bool client_dict_iterate(struct dict_iterate_context *_ctx,
ctx->seen_results = TRUE;
return TRUE;
}
+ if (!ctx->cmd_sent) {
+ ctx->cmd_sent = TRUE;
+ client_dict_iterate_cmd_send(ctx);
+ return client_dict_iterate(_ctx, key_r, value_r);
+ }
ctx->ctx.has_more = !ctx->finished;
ctx->result_idx = 0;
array_clear(&ctx->results);
*error_r = t_strdup(ctx->error);
array_free(&ctx->results);
pool_unref(&ctx->results_pool);
+ i_free(ctx->paths);
client_dict_iterate_free(ctx);
client_dict_add_timeout(dict);