Change agent interface
authorJose Bollo <jose.bollo@iot.bzh>
Fri, 27 Sep 2019 16:29:22 +0000 (18:29 +0200)
committerJose Bollo <jose.bollo@iot.bzh>
Mon, 30 Sep 2019 09:52:27 +0000 (11:52 +0200)
Instead of using callbacks, create the query
to allow processing subqueries in response to
agent queries.

Signed-off-by: Jose Bollo <jose.bollo@iot.bzh>
src/agent-at.c
src/cyn.c
src/cyn.h

index 0ae8d13..e646ab7 100644 (file)
@@ -45,6 +45,7 @@ parse(
 ) {
        size_t iout, ikey, inf;
        const char *val;
+       int sub;
 
        iout = 0;
        for (ikey = 0 ; ikey < KeyIdx_Count ; ikey++) {
@@ -66,29 +67,26 @@ parse(
                                switch(spec[1]) {
                                case 'c':
                                        val = rkey->client;
+                                       sub = 1;
                                        break;
                                case 's':
                                        val = rkey->session;
+                                       sub = 1;
                                        break;
                                case 'u':
                                        val = rkey->user;
+                                       sub = 1;
                                        break;
                                case 'p':
                                        val = rkey->permission;
+                                       sub = 1;
                                        break;
                                default:
                                        /* none */
-                                       val = 0;
+                                       sub = 0;
+                                       break;
                                }
-                               if (val) {
-                                       /* substitution of the value */
-                                       while (*val) {
-                                               if (iout < szbuf)
-                                                       buffer[iout] = *val;
-                                               iout++;
-                                               val++;
-                                       }
-                               } else {
+                               if (!sub) {
                                        /* no substitution */
                                        if (spec[1] != ':' && spec[1] != '%') {
                                                /* only escape % and : */
@@ -99,6 +97,14 @@ parse(
                                        if (iout < szbuf)
                                                buffer[iout] = spec[1];
                                        iout++;
+                               } else if (val) {
+                                       /* substitution of the value */
+                                       while (*val) {
+                                               if (iout < szbuf)
+                                                       buffer[iout] = *val;
+                                               iout++;
+                                               val++;
+                                       }
                                }
                                spec += 2;
                        }
@@ -136,8 +142,7 @@ agent_at_cb(
        void *agent_closure,
        const data_key_t *key,
        const char *value,
-       on_result_cb_t *on_result_cb,
-       void *on_result_closure
+       cyn_query_t *query
 ) {
        data_key_t atkey;
        char *block;
@@ -150,7 +155,7 @@ agent_at_cb(
        /* initialize the derived key */
        parse(value, key, &atkey, block, size);
        /* ask for the derived key */
-       return cyn_test_async(on_result_cb, on_result_closure, &atkey);
+       return cyn_subquery_async(query, (on_result_cb_t*)cyn_reply_query, query, &atkey);
 }
 
 /* see agent-at.h */
index cedf3e2..6978251 100644 (file)
--- a/src/cyn.c
+++ b/src/cyn.c
@@ -75,7 +75,7 @@ struct agent
 /**
  * structure handling an asynchronous check
  */
-struct async_check
+struct cyn_query
 {
        /** callback for handling result of the check */
        on_result_cb_t *on_result_cb;
@@ -380,58 +380,81 @@ required_agent(
        return 0;
 }
 
-
-static
-void
-async_reply(
-       struct async_check *achk
-) {
-       achk->on_result_cb(achk->closure, &achk->value);
-       free(achk);
-}
-
-static
-void
-async_on_result(
-       void *closure,
-       const data_value_t *value
-);
-
 static
 void
 async_call_agent(
        struct agent *agent,
-       struct async_check *achk
+       cyn_query_t *query,
+       const data_value_t *value
 ) {
        int rc = agent->agent_cb(
                        agent->name,
                        agent->closure,
-                       &achk->key,
-                       &achk->value.value[agent->len + 1],
-                       async_on_result,
-                       achk);
+                       &query->key,
+                       &value->value[agent->len + 1],
+                       query);
        if (rc < 0)
-               async_reply(achk);
+               cyn_reply_query(query, value);
 }
 
 static
-void
-async_on_result(
+cyn_query_t *
+alloc_query(
+       on_result_cb_t *on_result_cb,
        void *closure,
-       const data_value_t *value
+       const data_key_t *key,
+       int maxdepth
 ) {
-       struct async_check *achk = closure;
-       struct agent *agent;
+       size_t szcli, szses, szuse, szper;
+       cyn_query_t *query;
+       void *ptr;
 
-       achk->value = *value;
-       agent = required_agent(value->value);
-       if (agent && achk->decount) {
-               achk->decount--;
-               async_call_agent(agent, achk);
-       } else
-               async_reply(achk);
+       /* allocate asynchronous query */
+       szcli = key->client ? 1 + strlen(key->client) : 0;
+       szses = key->session ? 1 + strlen(key->session) : 0;
+       szuse = key->user ? 1 + strlen(key->user) : 0;
+       szper = key->permission ? 1 + strlen(key->permission) : 0;
+       query = malloc(szcli + szses + szuse + szper + sizeof *query);
+       if (query) {
+               /* init the structure */
+               ptr = &query[1];
+               query->on_result_cb = on_result_cb;
+               query->closure = closure;
+               if (!key->client)
+                       query->key.client = 0;
+               else {
+                       query->key.client = ptr;
+                       ptr = mempcpy(ptr, key->client, szcli);
+               }
+               if (!key->session)
+                       query->key.session = 0;
+               else {
+                       query->key.session = ptr;
+                       ptr = mempcpy(ptr, key->session, szses);
+               }
+               if (!key->user)
+                       query->key.user = 0;
+               else {
+                       query->key.user = ptr;
+                       ptr = mempcpy(ptr, key->user, szuse);
+               }
+               if (!key->permission)
+                       query->key.permission = 0;
+               else {
+                       query->key.permission = ptr;
+                       ptr = mempcpy(ptr, key->permission, szper);
+               }
+               query->decount = maxdepth;
+       }
+       return query;
 }
 
+
+
+
+
+
+
 int
 cyn_query_async(
        on_result_cb_t *on_result_cb,
@@ -441,10 +464,8 @@ cyn_query_async(
 ) {
        int rc;
        data_value_t value;
-       size_t szcli, szses, szuse, szper;
-       struct async_check *achk;
+       cyn_query_t *query;
        struct agent *agent;
-       void *ptr;
 
        /* get the direct value */
        rc = db_test(key, &value);
@@ -464,49 +485,14 @@ cyn_query_async(
        }
 
        /* allocate asynchronous query */
-       szcli = key->client ? 1 + strlen(key->client) : 0;
-       szses = key->session ? 1 + strlen(key->session) : 0;
-       szuse = key->user ? 1 + strlen(key->user) : 0;
-       szper = key->permission ? 1 + strlen(key->permission) : 0;
-       achk = malloc(szcli + szses + szuse + szper + sizeof *achk);
-       if (!achk) {
+       query = alloc_query(on_result_cb, closure, key, maxdepth);
+       if (!query) {
                on_result_cb(closure, &value);
                return -ENOMEM;
        }
 
-       /* init the structure */
-       ptr = &achk[1];
-       achk->on_result_cb = on_result_cb;
-       achk->closure = closure;
-       if (!key->client)
-               achk->key.client = 0;
-       else {
-               achk->key.client = ptr;
-               ptr = mempcpy(ptr, key->client, szcli);
-       }
-       if (!key->session)
-               achk->key.session = 0;
-       else {
-               achk->key.session = ptr;
-               ptr = mempcpy(ptr, key->session, szses);
-       }
-       if (!key->user)
-               achk->key.user = 0;
-       else {
-               achk->key.user = ptr;
-               ptr = mempcpy(ptr, key->user, szuse);
-       }
-       if (!key->permission)
-               achk->key.permission = 0;
-       else {
-               achk->key.permission = ptr;
-               ptr = mempcpy(ptr, key->permission, szper);
-       }
-       achk->value = value;
-       achk->decount = maxdepth;
-
        /* call the agent */
-       async_call_agent(agent, achk);
+       async_call_agent(agent, query, &value);
        return 0;
 }
 
@@ -530,6 +516,29 @@ cyn_check_async(
        return cyn_query_async(on_result_cb, closure, key, CYN_SEARCH_DEEP_MAX);
 }
 
+int
+cyn_subquery_async(
+       cyn_query_t *query,
+       on_result_cb_t *on_result_cb,
+       void *closure,
+       const data_key_t *key
+) {
+       return cyn_query_async(on_result_cb, closure, key, query->decount - 1);
+}
+
+void
+cyn_reply_query(
+       cyn_query_t *query,
+       const data_value_t *value
+) {
+       query->on_result_cb(query->closure, value);
+       free(query);
+}
+
+
+
+
+
 /* see cyn.h */
 int
 cyn_agent_add(
index 5b4c76f..5772608 100644 (file)
--- a/src/cyn.h
+++ b/src/cyn.h
@@ -18,6 +18,8 @@
 
 #pragma once
 
+#define CYN_VERSION 99
+
 /**
  * Callback for entering asynchronousely the critical section
  * When called it receives the 'magic' argument given when
@@ -49,6 +51,12 @@ typedef void (list_cb_t)(
                const data_key_t *key,
                const data_value_t *value);
 
+/**
+ * Opaque structure for agent subqueries and responses.
+ */
+typedef struct cyn_query cyn_query_t;
+
+
 /**
  * Callback for querying agents
  */
@@ -57,8 +65,7 @@ typedef int (agent_cb_t)(
                void *agent_closure,
                const data_key_t *key,
                const char *value,
-               on_result_cb_t *on_result_cb,
-               void *on_result_closure);
+               cyn_query_t *query);
 
 /**
  * Enter in the critical recoverable section if possible
@@ -224,6 +231,22 @@ cyn_check_async(
        const data_key_t *key
 );
 
+extern
+int
+cyn_subquery_async(
+       cyn_query_t *query,
+       on_result_cb_t *on_result_cb,
+       void *closure,
+       const data_key_t *key
+);
+
+extern
+void
+cyn_reply_query(
+       cyn_query_t *query,
+       const data_value_t *value
+);
+
 extern
 int
 cyn_agent_add(