Mercurial > dovecot > core-2.2
diff src/lib-dict/dict-fs.c @ 17824:979e5a007248
lib-dict: dict-fs implements now minimal iteration support.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 18 Sep 2014 17:46:18 +0200 |
parents | 77e71a45a475 |
children | 3009a1a6f6d5 |
line wrap: on
line diff
--- a/src/lib-dict/dict-fs.c Thu Sep 18 17:39:49 2014 +0200 +++ b/src/lib-dict/dict-fs.c Thu Sep 18 17:46:18 2014 +0200 @@ -14,6 +14,16 @@ char *username; }; +struct fs_dict_iterate_context { + struct dict_iterate_context ctx; + const char **paths; + unsigned int path_idx; + enum dict_iterate_flags flags; + pool_t value_pool; + struct fs_iter *fs_iter; + bool failed; +}; + static int fs_dict_init(struct dict *driver, const char *uri, const struct dict_settings *set, @@ -106,6 +116,84 @@ return ret; } +static struct dict_iterate_context * +fs_dict_iterate_init(struct dict *_dict, const char *const *paths, + enum dict_iterate_flags flags) +{ + struct fs_dict *dict = (struct fs_dict *)_dict; + struct fs_dict_iterate_context *iter; + + /* these flags are not supported for now */ + i_assert((flags & DICT_ITERATE_FLAG_RECURSE) == 0); + i_assert((flags & (DICT_ITERATE_FLAG_SORT_BY_KEY | + DICT_ITERATE_FLAG_SORT_BY_VALUE)) == 0); + + iter = i_new(struct fs_dict_iterate_context, 1); + iter->ctx.dict = _dict; + iter->paths = p_strarray_dup(default_pool, paths); + iter->flags = flags; + iter->value_pool = pool_alloconly_create("iterate value pool", 128); + iter->fs_iter = fs_iter_init(dict->fs, + fs_dict_get_full_key(dict, paths[0]), 0); + return &iter->ctx; +} + +static bool fs_dict_iterate(struct dict_iterate_context *ctx, + const char **key_r, const char **value_r) +{ + struct fs_dict_iterate_context *iter = + (struct fs_dict_iterate_context *)ctx; + struct fs_dict *dict = (struct fs_dict *)ctx->dict; + const char *path; + int ret; + + *key_r = fs_iter_next(iter->fs_iter); + if (*key_r == NULL) { + if (fs_iter_deinit(&iter->fs_iter) < 0) { + iter->failed = TRUE; + return FALSE; + } + if (iter->paths[++iter->path_idx] == NULL) + return FALSE; + path = fs_dict_get_full_key(dict, iter->paths[iter->path_idx]); + iter->fs_iter = fs_iter_init(dict->fs, path, 0); + return fs_dict_iterate(ctx, key_r, value_r); + } + if ((iter->flags & DICT_ITERATE_FLAG_NO_VALUE) != 0) { + *value_r = NULL; + return TRUE; + } + p_clear(iter->value_pool); + path = t_strconcat(iter->paths[iter->path_idx], *key_r, NULL); + if ((ret = fs_dict_lookup(ctx->dict, iter->value_pool, path, value_r)) < 0) { + /* I/O error */ + iter->failed = TRUE; + return FALSE; + } else if (ret == 0) { + /* file was just deleted, just skip to next one */ + return fs_dict_iterate(ctx, key_r, value_r); + } + return TRUE; +} + +static int fs_dict_iterate_deinit(struct dict_iterate_context *ctx) +{ + struct fs_dict_iterate_context *iter = + (struct fs_dict_iterate_context *)ctx; + int ret; + + if (iter->fs_iter != NULL) { + if (fs_iter_deinit(&iter->fs_iter) < 0) + iter->failed = TRUE; + } + ret = iter->failed ? -1 : 0; + + pool_unref(&iter->value_pool); + i_free(iter->paths); + i_free(iter); + return ret; +} + static struct dict_transaction_context * fs_dict_transaction_init(struct dict *_dict) { @@ -186,9 +274,9 @@ fs_dict_deinit, NULL, fs_dict_lookup, - NULL, - NULL, - NULL, + fs_dict_iterate_init, + fs_dict_iterate, + fs_dict_iterate_deinit, fs_dict_transaction_init, fs_dict_transaction_commit, dict_transaction_memory_rollback,