summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Bollo <jose.bollo@iot.bzh>2019-09-10 18:19:51 +0200
committerJose Bollo <jose.bollo@iot.bzh>2019-09-27 14:49:14 +0200
commite4d6dbdf10130b72fe4a898b105d3049a0cdf98a (patch)
tree7fa238ab96c3e7e8955caf79dd5a88afe635da46
parent58607718adf2cc921e9226fd2cde8caedc5ccef9 (diff)
More comment for cyn.[ch]
Change-Id: Ia3e6ca458f27ede690cfc6934dd9a6b320ed5d67 Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r--src/agent-at.c6
-rw-r--r--src/agent-at.h5
-rw-r--r--src/cyn.c156
-rw-r--r--src/cyn.h120
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,