str = t_str_new(256);
o_stream_cork(conn->output);
- while ((ret = dict_iterate(conn->iter_ctx, &key, &value)) > 0) {
+ while (dict_iterate(conn->iter_ctx, &key, &value)) {
str_truncate(str, 0);
str_printfa(str, "%c%s\t%s\n", DICT_PROTOCOL_REPLY_OK,
key, value);
if (o_stream_get_buffer_used_size(conn->output) >
DICT_OUTPUT_OPTIMAL_SIZE) {
- if (o_stream_flush(conn->output) <= 0)
- break;
+ if (o_stream_flush(conn->output) <= 0) {
+ /* continue later */
+ o_stream_uncork(conn->output);
+ return 0;
+ }
/* flushed everything, continue */
}
}
- if (ret <= 0) {
- /* finished iterating */
- o_stream_unset_flush_callback(conn->output);
- dict_iterate_deinit(&conn->iter_ctx);
+ /* finished iterating */
+ o_stream_unset_flush_callback(conn->output);
- str_truncate(str, 0);
- if (ret < 0)
- str_append_c(str, DICT_PROTOCOL_REPLY_FAIL);
- str_append_c(str, '\n');
- o_stream_send(conn->output, str_data(str), str_len(str));
- }
+ str_truncate(str, 0);
+ if ((ret = dict_iterate_deinit(&conn->iter_ctx)) < 0)
+ str_append_c(str, DICT_PROTOCOL_REPLY_FAIL);
+ str_append_c(str, '\n');
+ o_stream_send(conn->output, str_data(str), str_len(str));
o_stream_uncork(conn->output);
- return ret <= 0 ? 1 : 0;
+ return 1;
}
static int cmd_iterate(struct dict_connection *conn, const char *line)
}
if (conn->iter_ctx != NULL)
- dict_iterate_deinit(&conn->iter_ctx);
+ (void)dict_iterate_deinit(&conn->iter_ctx);
io_remove(&conn->io);
i_stream_destroy(&conn->input);
return &ctx->ctx;
}
-static int client_dict_iterate(struct dict_iterate_context *_ctx,
- const char **key_r, const char **value_r)
+static bool client_dict_iterate(struct dict_iterate_context *_ctx,
+ const char **key_r, const char **value_r)
{
struct client_dict_iterate_context *ctx =
(struct client_dict_iterate_context *)_ctx;
char *line, *value;
if (ctx->failed)
- return -1;
+ return FALSE;
/* read next reply */
line = client_dict_read_line(dict);
- if (line == NULL)
- return -1;
+ if (line == NULL) {
+ ctx->failed = TRUE;
+ return FALSE;
+ }
if (*line == '\0') {
/* end of iteration */
- return 0;
+ return FALSE;
}
/* line contains key \t value */
value = strchr(++line, '\t');
break;
case DICT_PROTOCOL_REPLY_FAIL:
- return -1;
+ ctx->failed = TRUE;
+ return FALSE;
default:
value = NULL;
break;
if (value == NULL) {
/* broken protocol */
i_error("dict client (%s) sent broken reply", dict->path);
- return -1;
+ ctx->failed = TRUE;
+ return FALSE;
}
*value++ = '\0';
*key_r = p_strdup(ctx->pool, dict_client_unescape(line));
*value_r = p_strdup(ctx->pool, dict_client_unescape(value));
- return 1;
+ return TRUE;
}
-static void client_dict_iterate_deinit(struct dict_iterate_context *_ctx)
+static int client_dict_iterate_deinit(struct dict_iterate_context *_ctx)
{
struct client_dict *dict = (struct client_dict *)_ctx->dict;
struct client_dict_iterate_context *ctx =
(struct client_dict_iterate_context *)_ctx;
+ int ret = ctx->failed ? -1 : 0;
pool_unref(&ctx->pool);
i_free(ctx);
dict->in_iteration = FALSE;
+ return ret;
}
static struct dict_transaction_context *
const char **key_r, const char **value_r);
enum dict_iterate_flags flags;
+ bool failed;
};
struct db_dict_transaction_context {
return &ctx->ctx;
}
-static int db_dict_iterate(struct dict_iterate_context *_ctx,
- const char **key_r, const char **value_r)
+static bool db_dict_iterate(struct dict_iterate_context *_ctx,
+ const char **key_r, const char **value_r)
{
struct db_dict_iterate_context *ctx =
(struct db_dict_iterate_context *)_ctx;
+ int ret;
- return ctx->iterate_next(ctx, key_r, value_r);
+ ret = ctx->iterate_next(ctx, key_r, value_r);
+ if (ret < 0)
+ ctx->failed = TRUE;
+ return ret > 0;
}
-static void db_dict_iterate_deinit(struct dict_iterate_context *_ctx)
+static int db_dict_iterate_deinit(struct dict_iterate_context *_ctx)
{
struct db_dict_iterate_context *ctx =
(struct db_dict_iterate_context *)_ctx;
+ int ret = ctx->failed ? -1 : 0;
ctx->cursor->c_close(ctx->cursor);
pool_unref(&ctx->pool);
i_free(ctx->path);
i_free(ctx);
+ return ret;
}
static struct dict_transaction_context *
return &ctx->ctx;
}
-static int file_dict_iterate(struct dict_iterate_context *_ctx,
- const char **key_r, const char **value_r)
+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;
*key_r = key;
*value_r = value;
- return 1;
+ return TRUE;
}
- return ctx->failed ? -1 : 0;
+ return FALSE;
}
-static void file_dict_iterate_deinit(struct dict_iterate_context *_ctx)
+static int file_dict_iterate_deinit(struct dict_iterate_context *_ctx)
{
struct file_dict_iterate_context *ctx =
(struct file_dict_iterate_context *)_ctx;
+ int ret = ctx->failed ? -1 : 0;
hash_table_iterate_deinit(&ctx->iter);
i_free(ctx->path);
i_free(ctx);
+ return ret;
}
static struct dict_transaction_context *
struct dict_iterate_context *
(*iterate_init)(struct dict *dict, const char *path,
enum dict_iterate_flags flags);
- int (*iterate)(struct dict_iterate_context *ctx,
- const char **key_r, const char **value_r);
- void (*iterate_deinit)(struct dict_iterate_context *ctx);
+ bool (*iterate)(struct dict_iterate_context *ctx,
+ const char **key_r, const char **value_r);
+ int (*iterate_deinit)(struct dict_iterate_context *ctx);
struct dict_transaction_context *(*transaction_init)(struct dict *dict);
int (*transaction_commit)(struct dict_transaction_context *ctx,
string_t *key;
const struct dict_sql_map *map;
unsigned int key_prefix_len, pattern_prefix_len, next_map_idx;
+ bool failed;
};
struct sql_dict_inc_row {
return &ctx->ctx;
}
-static int sql_dict_iterate(struct dict_iterate_context *_ctx,
- const char **key_r, const char **value_r)
+static bool sql_dict_iterate(struct dict_iterate_context *_ctx,
+ const char **key_r, const char **value_r)
{
struct sql_dict_iterate_context *ctx =
(struct sql_dict_iterate_context *)_ctx;
unsigned int i, count;
int ret;
- if (ctx->result == NULL)
- return -1;
+ if (ctx->result == NULL) {
+ ctx->failed = TRUE;
+ return FALSE;
+ }
while ((ret = sql_result_next_row(ctx->result)) == 0) {
/* see if there are more results in the next map */
if (!sql_dict_iterate_next_query(ctx))
- return 0;
+ return FALSE;
}
if (ret < 0) {
+ ctx->failed = TRUE;
i_error("dict sql iterate failed: %s",
sql_result_get_error(ctx->result));
- return ret;
+ return FALSE;
}
/* convert fetched row to dict key */
*key_r = str_c(ctx->key);
*value_r = sql_result_get_field_value(ctx->result, 0);
- return 1;
+ return TRUE;
}
-static void sql_dict_iterate_deinit(struct dict_iterate_context *_ctx)
+static int sql_dict_iterate_deinit(struct dict_iterate_context *_ctx)
{
struct sql_dict_iterate_context *ctx =
(struct sql_dict_iterate_context *)_ctx;
+ int ret = ctx->failed ? -1 : 0;
if (ctx->result != NULL)
sql_result_unref(ctx->result);
str_free(&ctx->key);
i_free(ctx->path);
i_free(ctx);
+ return ret;
}
static struct dict_transaction_context *
return dict->v.iterate_init(dict, path, flags);
}
-int dict_iterate(struct dict_iterate_context *ctx,
- const char **key_r, const char **value_r)
+bool dict_iterate(struct dict_iterate_context *ctx,
+ const char **key_r, const char **value_r)
{
return ctx->dict->v.iterate(ctx, key_r, value_r);
}
-void dict_iterate_deinit(struct dict_iterate_context **_ctx)
+int dict_iterate_deinit(struct dict_iterate_context **_ctx)
{
struct dict_iterate_context *ctx = *_ctx;
*_ctx = NULL;
- ctx->dict->v.iterate_deinit(ctx);
+ return ctx->dict->v.iterate_deinit(ctx);
}
struct dict_transaction_context *dict_transaction_begin(struct dict *dict)
struct dict_iterate_context *
dict_iterate_init(struct dict *dict, const char *path,
enum dict_iterate_flags flags);
-/* Returns -1 = error, 0 = finished, 1 = key/value set */
-int dict_iterate(struct dict_iterate_context *ctx,
- const char **key_r, const char **value_r);
-void dict_iterate_deinit(struct dict_iterate_context **ctx);
+bool dict_iterate(struct dict_iterate_context *ctx,
+ const char **key_r, const char **value_r);
+/* Returns 0 = ok, -1 = iteration failed */
+int dict_iterate_deinit(struct dict_iterate_context **ctx);
/* Start a new dictionary transaction. */
struct dict_transaction_context *dict_transaction_begin(struct dict *dict);
prefix = DICT_PATH_SHARED DICT_SHARED_BOXES_PATH;
prefix_len = strlen(prefix);
iter = dict_iterate_init(dict->dict, prefix, DICT_ITERATE_FLAG_RECURSE);
- while ((ret = dict_iterate(iter, &key, &value)) > 0) {
+ while (dict_iterate(iter, &key, &value)) {
/* prefix/$dest/$source */
key += prefix_len;
p = strchr(key, '/');
array_append(&old_ids_arr, &key, 1);
}
}
- dict_iterate_deinit(&iter);
- if (ret < 0) {
+ if (dict_iterate_deinit(&iter) < 0) {
i_error("acl: dict iteration failed, can't update dict");
return -1;
}
acl_lookup_dict_iterate_visible_next(struct acl_lookup_dict_iter *iter)
{
const char *key, *value;
- int ret;
if (iter->dict_iter == NULL)
return 0;
- ret = dict_iterate(iter->dict_iter, &key, &value);
- if (ret > 0) {
+ if (dict_iterate(iter->dict_iter, &key, &value)) {
i_assert(iter->prefix_len < strlen(key));
return key + iter->prefix_len;
}
- if (ret < 0)
+ if (dict_iterate_deinit(&iter->dict_iter) < 0)
iter->failed = TRUE;
- dict_iterate_deinit(&iter->dict_iter);
if (iter->iter_idx < array_count(&iter->iter_ids)) {
/* get to the next iterator */
int ret = iter->failed ? -1 : 0;
*_iter = NULL;
- if (iter->dict_iter != NULL)
- dict_iterate_deinit(&iter->dict_iter);
+ if (iter->dict_iter != NULL) {
+ if (dict_iterate_deinit(&iter->dict_iter) < 0)
+ ret = -1;
+ }
pool_unref(&iter->pool);
return ret;
}
DICT_ITERATE_FLAG_SORT_BY_VALUE);
/* We'll get the oldest values (timestamps) first */
- while ((ret = dict_iterate(iter, &key, &value)) > 0) {
+ while (dict_iterate(iter, &key, &value)) {
/* key = DICT_EXPIRE_PREFIX<user>/<mailbox> */
userp = key + strlen(DICT_EXPIRE_PREFIX);
if (ret < 0) {
/* failed to update */
- ret = 0;
} else if (next_expire == 0) {
/* no more messages or mailbox deleted */
if (!testrun)
} T_END;
}
}
- if (ret < 0)
+ if (dict_iterate_deinit(&iter) < 0)
i_error("Dictionary iteration failed");
if (testrun && userp == NULL)
i_info("No entries in dictionary");
- dict_iterate_deinit(&iter);
if (!testrun)
dict_transaction_commit(&trans);
else