From e4d6dbdf10130b72fe4a898b105d3049a0cdf98a Mon Sep 17 00:00:00 2001 From: José Bollo Date: Tue, 10 Sep 2019 18:19:51 +0200 Subject: More comment for cyn.[ch] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ia3e6ca458f27ede690cfc6934dd9a6b320ed5d67 Signed-off-by: José Bollo --- src/agent-at.c | 6 +-- src/agent-at.h | 5 ++ src/cyn.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++---------- src/cyn.h | 120 ++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 251 insertions(+), 36 deletions(-) diff --git a/src/agent-at.c b/src/agent-at.c index 6a33bf6..0ae8d13 100644 --- a/src/agent-at.c +++ b/src/agent-at.c @@ -153,11 +153,7 @@ agent_at_cb( return cyn_test_async(on_result_cb, on_result_closure, &atkey); } -/** - * Activate the AT-agent - * - * @return 0 in case of success of a negative value in -errno style. - */ +/* see agent-at.h */ int agent_at_activate( ) { diff --git a/src/agent-at.h b/src/agent-at.h index 7bbffc0..60dd168 100644 --- a/src/agent-at.h +++ b/src/agent-at.h @@ -17,6 +17,11 @@ #pragma once +/** + * Activate the AT-agent + * + * @return 0 in case of success of a negative value in -errno style. + */ extern int agent_at_activate( diff --git a/src/cyn.c b/src/cyn.c index 6b6b17a..cedf3e2 100644 --- a/src/cyn.c +++ b/src/cyn.c @@ -28,35 +28,100 @@ #include "queue.h" #include "cyn.h" +#if !CYN_SEARCH_DEEP_MAX +# define CYN_SEARCH_DEEP_MAX 10 +#endif + +/** + * items of the list of observers or awaiters + */ struct callback { + /** link to the next item of the list */ struct callback *next; union { + /** any callback value */ void *any_cb; + /** awaiter callback */ on_enter_cb_t *on_enter_cb; + /** observer callback */ on_change_cb_t *on_change_cb; }; + /** closure of the callback */ void *closure; }; +/** + * items of the list of agents + */ struct agent { + /** link to the next item of the list */ struct agent *next; + + /** agent callback */ agent_cb_t *agent_cb; + + /** closure of the callback */ void *closure; + + /** length of the name */ uint8_t len; + + /** name of the agent */ char name[]; }; +/** + * structure handling an asynchronous check + */ +struct async_check +{ + /** callback for handling result of the check */ + on_result_cb_t *on_result_cb; + + /** closure of the callback */ + void *closure; + + /** key of the check */ + data_key_t key; + + /** value of the check */ + data_value_t value; + + /** down counter for recursivity limitation */ + int decount; +}; + /** locking critical section */ static const void *lock; + +/** head of the list of critical section awaiters */ static struct callback *awaiters; + +/** head of the list of change observers */ static struct callback *observers; + +/** head of the list of agents */ static struct agent *agents; + +/** last changeid */ static uint32_t last_changeid; + +/** changeid of the current 'changeid_string' */ static uint32_t last_changeid_string; + +/** string buffer for changeid */ static char changeid_string[12]; +/** + * Delete from the list represented by 'head' the entry for + * 'callback' and 'closure' + * @param callback + * @param closure + * @param head + * @return 0 if entry found and removed, -ENOENT if not found + */ static int delcb( @@ -70,13 +135,21 @@ delcb( if (c->any_cb == callback && c->closure == closure) { *head = c->next; free(c); - return 1; + return 0; } head = &c->next; } - return 0; + return -ENOENT; } +/** + * Adds at head of the list represented by 'head' the entry for + * 'callback' and 'closure' + * @param callback + * @param closure + * @param head + * @return 0 if correctly added or -ENOMEM in case of allocation failure + */ static int addcb( @@ -88,7 +161,7 @@ addcb( c = malloc(sizeof *c); if (c == NULL) - return -(errno = ENOMEM); + return -ENOMEM; c->any_cb = callback; c->closure = closure; c->next = *head; @@ -96,6 +169,10 @@ addcb( return 0; } +/** + * Call when database changed. + * Calls all observers to notify them the change + */ static void changed( @@ -107,30 +184,36 @@ changed( c->on_change_cb(c->closure); } -/** enter critical recoverable section */ +/* see cyn.h */ int cyn_enter( const void *magic ) { + if (!magic) + return -EINVAL; if (lock) return -EBUSY; lock = magic; return 0; } +/* see cyn.h */ int cyn_enter_async( on_enter_cb_t *enter_cb, - void *closure + void *magic ) { + if (!magic) + return -EINVAL; if (lock) - return addcb(enter_cb, closure, &awaiters); + return addcb(enter_cb, magic, &awaiters); - lock = closure; - enter_cb(closure); + lock = magic; + enter_cb(magic); return 0; } +/* see cyn.h */ int cyn_enter_async_cancel( on_enter_cb_t *enter_cb, @@ -139,6 +222,7 @@ cyn_enter_async_cancel( return delcb(enter_cb, closure, &awaiters); } +/* see cyn.h */ int cyn_on_change_add( on_change_cb_t *on_change_cb, @@ -147,6 +231,7 @@ cyn_on_change_add( return addcb(on_change_cb, closure, &observers); } +/* see cyn.h */ int cyn_on_change_remove( on_change_cb_t *on_change_cb, @@ -155,7 +240,7 @@ cyn_on_change_remove( return delcb(on_change_cb, closure, &observers); } -/** leave critical recoverable section */ +/* see cyn.h */ int cyn_leave( const void *magic, @@ -205,6 +290,7 @@ cyn_leave( return rc; } +/* see cyn.h */ int cyn_set( const data_key_t *key, @@ -215,6 +301,7 @@ cyn_set( return queue_set(key, value); } +/* see cyn.h */ int cyn_drop( const data_key_t *key @@ -224,6 +311,7 @@ cyn_drop( return queue_drop(key); } +/* see cyn.h */ void cyn_list( void *closure, @@ -233,6 +321,11 @@ cyn_list( db_for_all(closure, callback, key); } +/** + * initialize value to its default + * @param value to initialize + * @return the initialized value + */ static data_value_t * default_value( @@ -243,6 +336,13 @@ default_value( return value; } +/** + * Search the agent of name and return its item in the list + * @param name of the agent to find (optionally zero terminated) + * @param len length of the name + * @param ppprev for catching the pointer referencing the return item + * @return 0 if not found or the pointer to the item of the found agent + */ static struct agent * search_agent( @@ -260,6 +360,12 @@ search_agent( return it; } +/** + * Return the agent required by the value or 0 if no agent is required + * or if the agent is not found. + * @param value string where agent is the prefix followed by one colon + * @return the item of the required agent or 0 when no agent is required + */ static struct agent * required_agent( @@ -274,14 +380,6 @@ required_agent( return 0; } -struct async_check -{ - on_result_cb_t *on_result_cb; - void *closure; - data_key_t key; - data_value_t value; - int decount; -}; static void @@ -334,13 +432,12 @@ async_on_result( async_reply(achk); } -static int -async_check_or_test( +cyn_query_async( on_result_cb_t *on_result_cb, void *closure, const data_key_t *key, - int agentdeep + int maxdepth ) { int rc; data_value_t value; @@ -361,7 +458,7 @@ async_check_or_test( /* if not an agent or agent not required */ agent = required_agent(value.value); - if (!agent || !agentdeep) { + if (!agent || maxdepth <= 0) { on_result_cb(closure, &value); return rc; } @@ -406,31 +503,34 @@ async_check_or_test( ptr = mempcpy(ptr, key->permission, szper); } achk->value = value; - achk->decount = agentdeep; + achk->decount = maxdepth; /* call the agent */ async_call_agent(agent, achk); return 0; } +/* see cyn.h */ int cyn_test_async( on_result_cb_t *on_result_cb, void *closure, const data_key_t *key ) { - return async_check_or_test(on_result_cb, closure, key, 0); + return cyn_query_async(on_result_cb, closure, key, 0); } +/* see cyn.h */ int cyn_check_async( on_result_cb_t *on_result_cb, void *closure, const data_key_t *key ) { - return async_check_or_test(on_result_cb, closure, key, 10); + return cyn_query_async(on_result_cb, closure, key, CYN_SEARCH_DEEP_MAX); } +/* see cyn.h */ int cyn_agent_add( const char *name, @@ -464,6 +564,7 @@ cyn_agent_add( return 0; } +/* see cyn.h */ int cyn_agent_remove( const char *name @@ -486,25 +587,28 @@ cyn_agent_remove( return 0; } +/* see cyn.h */ void cyn_changeid_reset( ) { last_changeid = 1; } +/* see cyn.h */ uint32_t cyn_changeid( ) { return last_changeid; } -extern +/* see cyn.h */ const char * cyn_changeid_string( ) { + /* regenerate the string on need */ if (last_changeid != last_changeid_string) { last_changeid_string = last_changeid; snprintf(changeid_string, sizeof changeid_string, "%u", last_changeid); } return changeid_string; -} \ No newline at end of file +} diff --git a/src/cyn.h b/src/cyn.h index 810026a..5b4c76f 100644 --- a/src/cyn.h +++ b/src/cyn.h @@ -18,15 +18,40 @@ #pragma once -typedef void (on_enter_cb_t)(void *closure); +/** + * Callback for entering asynchronousely the critical section + * When called it receives the 'magic' argument given when + * 'cyn_enter_async' was called. + */ +typedef void (on_enter_cb_t)(void *magic); + +/** + * Callback for being notified of changes in database + * When called it receives the 'closure' argument given when + * 'cyn_on_change_add' was called. + */ typedef void (on_change_cb_t)(void *closure); + +/** + * Callback for receiving the result of a test or check + * When called, receives the result 'value' of the request and + * the 'closure' given when calling asynchronous query function. + */ typedef void (on_result_cb_t)(void *closure, const data_value_t *value); +/** + * Callback for listing data of the database. + * When call receives the 'closure' given when 'cyn_list' is called + * and the pair 'key', 'value' of the listed item. + */ typedef void (list_cb_t)( void *closure, const data_key_t *key, const data_value_t *value); +/** + * Callback for querying agents + */ typedef int (agent_cb_t)( const char *name, void *agent_closure, @@ -35,14 +60,38 @@ typedef int (agent_cb_t)( on_result_cb_t *on_result_cb, void *on_result_closure); -/** enter critical recoverable section */ +/** + * Enter in the critical recoverable section if possible + * + * @param magic a pointer not null that must be used in 'cyn_leave' + * @return 0 entered + * -EBUSY critical section already locked + * -EINVAL magic == NULL + * + * @see cyn_leave, cyn_enter_async + */ extern int cyn_enter( const void *magic ); -/** leave critical recoverable section */ +/** + * Leave the entered the critical recoverable section if possible + * + * @param magic a pointer not null that must be the one passed to + * 'cyn_enter' or 'cyn_enter_async' + * @param commit if true, the changes are committed to database, conversely + * if false, the changes made since entering the critical + * section are discarded + * @return 0 success + * -EALREADY already unlocked + * -EINVAL magic == NULL + * -EPERM magic doesn't match the magic that entered + * other negative codes: error when commiting the database + * + * @see cyn_enter, cyn_enter_async + */ extern int cyn_leave( @@ -50,20 +99,50 @@ cyn_leave( bool commit ); +/** + * Enter asynchronously in the critical recoverable section if possible. + * If the critical recoverable section is free, lock it with magic, + * call the callback 'enter_cb' and returns 0. Otherwise, if the critical + * section is already taken, the functions enqueue the entering request + * and the callback will be called when the critical recoverable section is + * available. + * + * @param enter_cb the entering callback + * @param magic a pointer not null that must be used in 'cyn_leave' + * @return 0 entered or or queued + * -ENOMEM critical section already locked but request can't be queued + * -EINVAL magic == NULL + * + * @see cyn_leave, cyn_enter + */ extern int cyn_enter_async( on_enter_cb_t *enter_cb, - void *closure + void *magic ); +/** + * Cancel a an asynchonous waiter to enter + * @param enter_cb the enter callback of the waiter + * @param magic the closure of the waiter + * @return 0 if entry found and removed, -ENOENT if not found + */ extern int cyn_enter_async_cancel( on_enter_cb_t *enter_cb, - void *closure + void *magic ); +/** + * Add an observer to the list of observers + * + * @param on_change_cb callback receiving change events + * @param closure closure of the callback + * @return 0 success + * -ENOMEM can't queue the observer + */ extern int cyn_on_change_add( @@ -71,6 +150,12 @@ cyn_on_change_add( void *closure ); +/** + * Removes an on change observer + * @param on_change_cb the callback of the observer + * @param closure the closure of the observer + * @return 0 if entry found and removed, -ENOENT if not found + */ extern int cyn_on_change_remove( @@ -78,6 +163,14 @@ cyn_on_change_remove( void *closure ); +/** + * Set or add the rule key/value to the change list to commit + * @param key the key of the rule + * @param value the value of the rule for the key + * @return 0 on success + * -EPERM if not locked in critical recoverable section + * other negative codes: error when queuing the change + */ extern int cyn_set( @@ -85,6 +178,13 @@ cyn_set( const data_value_t *value ); +/** + * Drop any rule matching the key + * @param key the key of the rule + * @return 0 on success + * -EPERM if not locked in critical recoverable section + * other negative codes: error when queuing the change + */ extern int cyn_drop( @@ -99,6 +199,16 @@ cyn_list( const data_key_t *key ); +extern +int +cyn_query_async( + on_result_cb_t *on_result_cb, + void *closure, + const data_key_t *key, + int maxdepth +); + +extern int cyn_test_async( on_result_cb_t *on_result_cb, -- cgit 1.2.3-korg