aboutsummaryrefslogtreecommitdiffstats
path: root/src/afb-monitor.c
diff options
context:
space:
mode:
authorJose Bollo <jose.bollo@iot.bzh>2019-11-04 17:57:23 +0100
committerJosé Bollo <jose.bollo@iot.bzh>2019-11-29 12:48:17 +0100
commitb55f3cd48507105e85894be89557787eccfbe22f (patch)
tree337b771a460688087c622e3b27c43c0b5a77a233 /src/afb-monitor.c
parenteaf5670e9d10b5d7c066043e7563706cf1e01bd5 (diff)
afb-stub-ws: Enforce asynchronous describe
Because remote apis describe themselves asynchronousely, it is better to have asynchronous describe api. Bug-AGL: SPEC-2968 Change-Id: I52b4dab697f229ad01ea2b73d6b8dee22d507912 Signed-off-by: Jose Bollo <jose.bollo@iot.bzh>
Diffstat (limited to 'src/afb-monitor.c')
-rw-r--r--src/afb-monitor.c178
1 files changed, 131 insertions, 47 deletions
diff --git a/src/afb-monitor.c b/src/afb-monitor.c
index e32c85ac..a53f75a3 100644
--- a/src/afb-monitor.c
+++ b/src/afb-monitor.c
@@ -36,6 +36,17 @@
#include "monitor-api.inc"
+
+static const char _verbosity_[] = "verbosity";
+static const char _apis_[] = "apis";
+
+static const char _debug_[] = "debug";
+static const char _info_[] = "info";
+static const char _notice_[] = "notice";
+static const char _warning_[] = "warning";
+static const char _error_[] = "error";
+
+
static struct afb_apiset *target_set;
int afb_monitor_init(struct afb_apiset *declare_set, struct afb_apiset *call_set)
@@ -48,12 +59,6 @@ int afb_monitor_init(struct afb_apiset *declare_set, struct afb_apiset *call_set
**** Monitoring verbosity
******************************************************************************/
-static const char _debug_[] = "debug";
-static const char _info_[] = "info";
-static const char _notice_[] = "notice";
-static const char _warning_[] = "warning";
-static const char _error_[] = "error";
-
/**
* Translate verbosity indication to an integer value.
* @param v the verbosity indication
@@ -231,72 +236,141 @@ static struct json_object *get_verbosity(struct json_object *spec)
}
/******************************************************************************
-**** Monitoring apis
+**** Manage namelist of api names
******************************************************************************/
-/**
- * get apis accordling to specification in 'spec'
- * @param resu the json object to build
- * @param spec specification of the verbosity to set
- */
-static void get_one_api(struct json_object *resu, const char *name, struct json_object *spec)
+struct namelist {
+ struct namelist *next;
+ json_object *data;
+ char name[];
+};
+
+static struct namelist *reverse_namelist(struct namelist *head)
{
- struct json_object *o;
+ struct namelist *previous, *next;
+
+ previous = NULL;
+ while(head) {
+ next = head->next;
+ head->next = previous;
+ previous = head;
+ head = next;
+ }
+ return previous;
+}
- o = afb_apiset_describe(target_set, name);
- if (o || afb_apiset_lookup(target_set, name, 1))
- json_object_object_add(resu, name, o);
+static void add_one_name_to_namelist(struct namelist **head, const char *name, struct json_object *data)
+{
+ size_t length = strlen(name) + 1;
+ struct namelist *item = malloc(length + sizeof *item);
+ if (!item)
+ ERROR("out of memory");
+ else {
+ item->next = *head;
+ item->data = data;
+ memcpy(item->name, name, length);
+ *head = item;
+ }
}
-/**
- * callback for getting verbosity of all apis
- * @param set the apiset
- * @param the name of the api to set
- * @param closure the json object to build
- */
-static void get_apis_of_all_cb(void *closure, struct afb_apiset *set, const char *name, int isalias)
+static void get_apis_namelist_of_all_cb(void *closure, struct afb_apiset *set, const char *name, int isalias)
{
- struct json_object *resu = closure;
- get_one_api(resu, name, NULL);
+ struct namelist **head = closure;
+ add_one_name_to_namelist(head, name, NULL);
}
/**
- * get apis accordling to specification in 'spec'
- * @param resu the json object to build
- * @param spec specification of the verbosity to set
+ * get apis names as a list accordling to specification in 'spec'
+ * @param spec specification of the apis to get
*/
-static struct json_object *get_apis(struct json_object *spec)
+static struct namelist *get_apis_namelist(struct json_object *spec)
{
int i, n;
- struct json_object *resu;
struct json_object_iterator it, end;
+ struct namelist *head;
- resu = json_object_new_object();
+ head = NULL;
if (json_object_is_type(spec, json_type_object)) {
it = json_object_iter_begin(spec);
end = json_object_iter_end(spec);
while (!json_object_iter_equal(&it, &end)) {
- get_one_api(resu, json_object_iter_peek_name(&it), json_object_iter_peek_value(&it));
+ add_one_name_to_namelist(&head,
+ json_object_iter_peek_name(&it),
+ json_object_iter_peek_value(&it));
json_object_iter_next(&it);
}
} else if (json_object_is_type(spec, json_type_array)) {
n = (int)json_object_array_length(spec);
for (i = 0 ; i < n ; i++)
- get_one_api(resu, json_object_get_string(json_object_array_get_idx(spec, i)), NULL);
+ add_one_name_to_namelist(&head,
+ json_object_get_string(
+ json_object_array_get_idx(spec, i)),
+ NULL);
} else if (json_object_is_type(spec, json_type_string)) {
- get_one_api(resu, json_object_get_string(spec), NULL);
+ add_one_name_to_namelist(&head, json_object_get_string(spec), NULL);
} else if (json_object_get_boolean(spec)) {
- afb_apiset_enum(target_set, 1, get_apis_of_all_cb, resu);
+ afb_apiset_enum(target_set, 1, get_apis_namelist_of_all_cb, &head);
}
- return resu;
+ return reverse_namelist(head);
}
/******************************************************************************
-**** Implementation monitoring verbs
+**** Monitoring apis
******************************************************************************/
-static const char _verbosity_[] = "verbosity";
-static const char _apis_[] = "apis";
+struct desc_apis {
+ struct namelist *names;
+ struct json_object *resu;
+ struct json_object *apis;
+ afb_req_t req;
+};
+
+static void describe_first_api(struct desc_apis *desc);
+
+static void on_api_description(void *closure, struct json_object *apidesc)
+{
+ struct desc_apis *desc = closure;
+ struct namelist *head = desc->names;
+
+ if (apidesc || afb_apiset_lookup(target_set, head->name, 1))
+ json_object_object_add(desc->apis, head->name, apidesc);
+ desc->names = head->next;
+ free(head);
+ describe_first_api(desc);
+}
+
+static void describe_first_api(struct desc_apis *desc)
+{
+ struct namelist *head = desc->names;
+ if (head)
+ afb_apiset_describe(target_set, head->name, on_api_description, desc);
+ else {
+ afb_req_success(desc->req, desc->resu, NULL);
+ afb_req_unref(desc->req);
+ free(desc);
+ }
+}
+
+static void describe_apis(afb_req_t req, struct json_object *resu, struct json_object *spec)
+{
+ struct desc_apis *desc;
+
+ desc = malloc(sizeof *desc);
+ if (!desc)
+ afb_req_fail(req, "out-of-memory", NULL);
+ else {
+ desc->req = afb_req_addref(req);
+ desc->resu = resu;
+ desc->apis = json_object_new_object();
+ json_object_object_add(desc->resu, _apis_, desc->apis);
+ desc->names = get_apis_namelist(spec);
+ describe_first_api(desc);
+ }
+}
+
+/******************************************************************************
+**** Implementation monitoring verbs
+******************************************************************************/
static void f_get(afb_req_t req)
{
@@ -305,13 +379,23 @@ static void f_get(afb_req_t req)
struct json_object *verbosity = NULL;
wrap_json_unpack(afb_req_json(req), "{s?:o,s?:o}", _verbosity_, &verbosity, _apis_, &apis);
- if (verbosity)
- verbosity = get_verbosity(verbosity);
- if (apis)
- apis = get_apis(apis);
-
- wrap_json_pack(&r, "{s:o*,s:o*}", _verbosity_, verbosity, _apis_, apis);
- afb_req_success(req, r, NULL);
+ if (!verbosity && !apis)
+ afb_req_success(req, NULL, NULL);
+ else {
+ r = json_object_new_object();
+ if (!r)
+ afb_req_fail(req, "out-of-memory", NULL);
+ else {
+ if (verbosity) {
+ verbosity = get_verbosity(verbosity);
+ json_object_object_add(r, _verbosity_, verbosity);
+ }
+ if (!apis)
+ afb_req_success(req, r, NULL);
+ else
+ describe_apis(req, r, apis);
+ }
+ }
}
static void f_set(afb_req_t req)