From: Timo Sirainen Date: Wed, 2 Sep 2015 14:34:43 +0000 (+0300) Subject: lib-dict: Added async API for lookup and iteration. X-Git-Tag: 2.2.19.rc1~130 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d694b6009574ee6e3cfaee3834cbdbcd431affb0;p=thirdparty%2Fdovecot%2Fcore.git lib-dict: Added async API for lookup and iteration. --- diff --git a/src/lib-dict/dict-client.c b/src/lib-dict/dict-client.c index 15a8ed5148..027937a9e0 100644 --- a/src/lib-dict/dict-client.c +++ b/src/lib-dict/dict-client.c @@ -852,6 +852,7 @@ struct dict dict_driver_client = { client_dict_set, client_dict_unset, client_dict_append, - client_dict_atomic_inc + client_dict_atomic_inc, + NULL } }; diff --git a/src/lib-dict/dict-file.c b/src/lib-dict/dict-file.c index c6f933afdb..6ab70eae52 100644 --- a/src/lib-dict/dict-file.c +++ b/src/lib-dict/dict-file.c @@ -650,6 +650,7 @@ struct dict dict_driver_file = { dict_transaction_memory_set, dict_transaction_memory_unset, dict_transaction_memory_append, - dict_transaction_memory_atomic_inc + dict_transaction_memory_atomic_inc, + NULL } }; diff --git a/src/lib-dict/dict-fs.c b/src/lib-dict/dict-fs.c index 22cb1b314e..a4518d322e 100644 --- a/src/lib-dict/dict-fs.c +++ b/src/lib-dict/dict-fs.c @@ -284,6 +284,7 @@ struct dict dict_driver_fs = { dict_transaction_memory_set, dict_transaction_memory_unset, NULL, + NULL, NULL } }; diff --git a/src/lib-dict/dict-memcached-ascii.c b/src/lib-dict/dict-memcached-ascii.c index 3e7ed65d8d..ed8d72c3ca 100644 --- a/src/lib-dict/dict-memcached-ascii.c +++ b/src/lib-dict/dict-memcached-ascii.c @@ -663,6 +663,7 @@ struct dict dict_driver_memcached_ascii = { dict_transaction_memory_set, dict_transaction_memory_unset, dict_transaction_memory_append, - dict_transaction_memory_atomic_inc + dict_transaction_memory_atomic_inc, + NULL } }; diff --git a/src/lib-dict/dict-memcached.c b/src/lib-dict/dict-memcached.c index f7f98d5685..6177b4eea4 100644 --- a/src/lib-dict/dict-memcached.c +++ b/src/lib-dict/dict-memcached.c @@ -390,6 +390,7 @@ struct dict dict_driver_memcached = { NULL, NULL, NULL, + NULL, NULL } }; diff --git a/src/lib-dict/dict-private.h b/src/lib-dict/dict-private.h index 5cafaf33c8..7fc0f00d2c 100644 --- a/src/lib-dict/dict-private.h +++ b/src/lib-dict/dict-private.h @@ -35,6 +35,9 @@ struct dict_vfuncs { const char *key, const char *value); void (*atomic_inc)(struct dict_transaction_context *ctx, const char *key, long long diff); + + void (*lookup_async)(struct dict *dict, const char *key, + dict_lookup_callback_t *callback, void *context); }; struct dict { @@ -45,6 +48,11 @@ struct dict { struct dict_iterate_context { struct dict *dict; + + dict_iterate_callback_t *async_callback; + void *async_context; + + unsigned int has_more:1; }; struct dict_transaction_context { diff --git a/src/lib-dict/dict-redis.c b/src/lib-dict/dict-redis.c index f1fabdc0b3..5de41c7f2a 100644 --- a/src/lib-dict/dict-redis.c +++ b/src/lib-dict/dict-redis.c @@ -801,6 +801,7 @@ struct dict dict_driver_redis = { redis_set, redis_unset, redis_append, - redis_atomic_inc + redis_atomic_inc, + NULL } }; diff --git a/src/lib-dict/dict-sql.c b/src/lib-dict/dict-sql.c index 1a0359aa7d..3a0b7b00b0 100644 --- a/src/lib-dict/dict-sql.c +++ b/src/lib-dict/dict-sql.c @@ -946,7 +946,8 @@ static struct dict sql_dict = { sql_dict_set, sql_dict_unset, sql_dict_append, - sql_dict_atomic_inc + sql_dict_atomic_inc, + NULL } }; diff --git a/src/lib-dict/dict.c b/src/lib-dict/dict.c index 66e581d881..ffc8c603be 100644 --- a/src/lib-dict/dict.c +++ b/src/lib-dict/dict.c @@ -119,6 +119,23 @@ int dict_lookup(struct dict *dict, pool_t pool, const char *key, return dict->v.lookup(dict, pool, key, value_r); } +void dict_lookup_async(struct dict *dict, const char *key, + dict_lookup_callback_t *callback, void *context) +{ + if (dict->v.lookup_async == NULL) { + struct dict_lookup_result result; + + memset(&result, 0, sizeof(result)); + result.ret = dict_lookup(dict, pool_datastack_create(), + key, &result.value); + if (result.ret < 0) + result.error = "Lookup failed"; + callback(&result, context); + return; + } + return dict->v.lookup_async(dict, key, callback, context); +} + struct dict_iterate_context * dict_iterate_init(struct dict *dict, const char *path, enum dict_iterate_flags flags) @@ -154,6 +171,19 @@ bool dict_iterate(struct dict_iterate_context *ctx, ctx->dict->v.iterate(ctx, key_r, value_r); } +void dict_iterate_set_async_callback(struct dict_iterate_context *ctx, + dict_iterate_callback_t *callback, + void *context) +{ + ctx->async_callback = callback; + ctx->async_context = context; +} + +bool dict_iterate_has_more(struct dict_iterate_context *ctx) +{ + return ctx->has_more; +} + int dict_iterate_deinit(struct dict_iterate_context **_ctx) { struct dict_iterate_context *ctx = *_ctx; diff --git a/src/lib-dict/dict.h b/src/lib-dict/dict.h index 66759fe63a..ed661a9ac1 100644 --- a/src/lib-dict/dict.h +++ b/src/lib-dict/dict.h @@ -5,6 +5,7 @@ #define DICT_PATH_SHARED "shared/" struct dict; +struct dict_iterate_context; enum dict_iterate_flags { /* Recurse to all the sub-hierarchies (e.g. iterating "foo/" will @@ -18,7 +19,9 @@ enum dict_iterate_flags { DICT_ITERATE_FLAG_NO_VALUE = 0x08, /* Don't recurse at all. This is basically the same as dict_lookup(), but it'll return all the rows instead of only the first one. */ - DICT_ITERATE_FLAG_EXACT_KEY = 0x10 + DICT_ITERATE_FLAG_EXACT_KEY = 0x10, + /* Perform iteration asynchronously. */ + DICT_ITERATE_FLAG_ASYNC = 0x20 }; enum dict_data_type { @@ -35,6 +38,15 @@ struct dict_settings { const char *home_dir; }; +struct dict_lookup_result { + int ret; + const char *value; + const char *error; +}; + +typedef void dict_lookup_callback_t(const struct dict_lookup_result *result, + void *context); +typedef void dict_iterate_callback_t(void *context); typedef void dict_transaction_commit_callback_t(int ret, void *context); void dict_driver_register(struct dict *driver); @@ -55,7 +67,7 @@ int dict_init_full(const char *uri, const struct dict_settings *set, struct dict **dict_r, const char **error_r); /* Close dictionary. */ void dict_deinit(struct dict **dict); -/* Wait for all pending asynchronous transaction commits to finish. +/* Wait for all pending asynchronous operations to finish. Returns 0 if ok, -1 if error. */ int dict_wait(struct dict *dict); @@ -63,6 +75,8 @@ int dict_wait(struct dict *dict); Returns 1 if found, 0 if not found and -1 if lookup failed. */ int dict_lookup(struct dict *dict, pool_t pool, const char *key, const char **value_r); +void dict_lookup_async(struct dict *dict, const char *key, + dict_lookup_callback_t *callback, void *context); /* Iterate through all values in a path. flag indicates how iteration is carried out */ @@ -72,6 +86,17 @@ dict_iterate_init(struct dict *dict, const char *path, struct dict_iterate_context * dict_iterate_init_multiple(struct dict *dict, const char *const *paths, enum dict_iterate_flags flags); +/* Set async callback. Note that if dict_iterate_init() already did all the + work, this callback may never be called. So after dict_iterate_init() you + should call dict_iterate() in any case to see if all the results are + already available. */ +void dict_iterate_set_async_callback(struct dict_iterate_context *ctx, + dict_iterate_callback_t *callback, + void *context); +/* If dict_iterate() returns FALSE, the iteration may be finished or if this + is an async iteration it may be waiting for more data. If this function + returns TRUE, the dict callback is called again with more data. */ +bool dict_iterate_has_more(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 */