]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-dict: Added async API for lookup and iteration.
authorTimo Sirainen <tss@iki.fi>
Wed, 2 Sep 2015 14:34:43 +0000 (17:34 +0300)
committerTimo Sirainen <tss@iki.fi>
Wed, 2 Sep 2015 14:34:43 +0000 (17:34 +0300)
src/lib-dict/dict-client.c
src/lib-dict/dict-file.c
src/lib-dict/dict-fs.c
src/lib-dict/dict-memcached-ascii.c
src/lib-dict/dict-memcached.c
src/lib-dict/dict-private.h
src/lib-dict/dict-redis.c
src/lib-dict/dict-sql.c
src/lib-dict/dict.c
src/lib-dict/dict.h

index 15a8ed5148cc8e610cee95084bda4ac7a629bc66..027937a9e04f4a0ef8d5fc54b0dbe4702bbc3906 100644 (file)
@@ -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
        }
 };
index c6f933afdb71a6bc89a7fbae7f31476c14fa215d..6ab70eae52c69a853b352a292e8c9cd1fe52cfe0 100644 (file)
@@ -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
        }
 };
index 22cb1b314e9150d8a1f2eda712e58a4bc8a8220d..a4518d322e97bb0905d80d5b46e9e8aefc2c9689 100644 (file)
@@ -284,6 +284,7 @@ struct dict dict_driver_fs = {
                dict_transaction_memory_set,
                dict_transaction_memory_unset,
                NULL,
+               NULL,
                NULL
        }
 };
index 3e7ed65d8dedd1d91489035e49eaea847823c481..ed8d72c3caeb4485a503e4bd135edab8eb3c4e4d 100644 (file)
@@ -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
        }
 };
index f7f98d568550aef92611f54225d732e835d1ba11..6177b4eea425bc3b73b4f0a3a36c0a3ec9a7de52 100644 (file)
@@ -390,6 +390,7 @@ struct dict dict_driver_memcached = {
                NULL,
                NULL,
                NULL,
+               NULL,
                NULL
        }
 };
index 5cafaf33c81b3ac5b14aeb795a1b3d3cb8316b61..7fc0f00d2cfccc81cab80070427b5e89e5fff146 100644 (file)
@@ -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 {
index f1fabdc0b31dfd8474686517ed581211a4f0dfd7..5de41c7f2aefb78a0c7a33fdeb7796f1b201a49c 100644 (file)
@@ -801,6 +801,7 @@ struct dict dict_driver_redis = {
                redis_set,
                redis_unset,
                redis_append,
-               redis_atomic_inc
+               redis_atomic_inc,
+               NULL
        }
 };
index 1a0359aa7d6740d19d3d0b6c420c8f469a8c09f6..3a0b7b00b0eb221cf9a6ac6b463839125f975db3 100644 (file)
@@ -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
        }
 };
 
index 66e581d881db5db44df01ce80f5c987322b90e5e..ffc8c603beef1adb1369a688ee81ec8aa0139698 100644 (file)
@@ -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;
index 66759fe63a25baff9f30bf94437193ca0f74308c..ed661a9ac1920f014dea440e84012a7e2eb2e532 100644 (file)
@@ -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 */