From 6bf1b8c3a8af299c04d9be0d59b42c3a6d7c9127 Mon Sep 17 00:00:00 2001 From: Jose Bollo Date: Fri, 27 Sep 2019 18:29:22 +0200 Subject: Change agent interface Instead of using callbacks, create the query to allow processing subqueries in response to agent queries. Signed-off-by: Jose Bollo --- src/agent-at.c | 31 ++++++----- src/cyn.c | 163 ++++++++++++++++++++++++++++++--------------------------- src/cyn.h | 27 +++++++++- 3 files changed, 129 insertions(+), 92 deletions(-) diff --git a/src/agent-at.c b/src/agent-at.c index 0ae8d13..e646ab7 100644 --- a/src/agent-at.c +++ b/src/agent-at.c @@ -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 */ diff --git a/src/cyn.c b/src/cyn.c index cedf3e2..6978251 100644 --- 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( diff --git a/src/cyn.h b/src/cyn.h index 5b4c76f..5772608 100644 --- 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( -- cgit 1.2.3-korg