aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--src/afb-api.h2
-rw-r--r--src/afb-apiset.c26
-rw-r--r--src/afb-apiset.h2
-rw-r--r--src/afb-export.c4
-rw-r--r--src/afb-monitor.c178
-rw-r--r--src/afb-stub-ws.c80
6 files changed, 164 insertions, 128 deletions
diff --git a/src/afb-api.h b/src/afb-api.h
index d55970c9..1f2a4a98 100644
--- a/src/afb-api.h
+++ b/src/afb-api.h
@@ -30,7 +30,7 @@ struct afb_api_itf
#endif
int (*get_logmask)(void *closure);
void (*set_logmask)(void *closure, int level);
- struct json_object *(*describe)(void *closure);
+ void (*describe)(void *closure, void (*describecb)(void *, struct json_object *), void *clocb);
void (*unref)(void *closure);
};
diff --git a/src/afb-apiset.c b/src/afb-apiset.c
index 0a8b3390..9fddd46c 100644
--- a/src/afb-apiset.c
+++ b/src/afb-apiset.c
@@ -28,6 +28,7 @@
#include "afb-apiset.h"
#include "afb-context.h"
#include "afb-xreq.h"
+#include "jobs.h"
#define INCR 8 /* CAUTION: must be a power of 2 */
@@ -941,20 +942,25 @@ int afb_apiset_get_logmask(struct afb_apiset *set, const char *name)
return i->api.itf->get_logmask(i->api.closure);
}
-/**
- * Get the description of the API of 'name'
- * @param set the api set
- * @param name the api whose description is required
- * @return the description or NULL
- */
-struct json_object *afb_apiset_describe(struct afb_apiset *set, const char *name)
+void afb_apiset_describe(struct afb_apiset *set, const char *name, void (*describecb)(void *, struct json_object *), void *closure)
{
const struct api_desc *i;
-
- i = name ? searchrec(set, name) : NULL;
- return i && i->api.itf->describe ? i->api.itf->describe(i->api.closure) : NULL;
+ struct json_object *r;
+
+ r = NULL;
+ if (name) {
+ i = searchrec(set, name);
+ if (i) {
+ if (i->api.itf->describe) {
+ i->api.itf->describe(i->api.closure, describecb, closure);
+ return;
+ }
+ }
+ }
+ describecb(closure, r);
}
+
struct get_names {
union {
struct {
diff --git a/src/afb-apiset.h b/src/afb-apiset.h
index d1f968b7..f21277a5 100644
--- a/src/afb-apiset.h
+++ b/src/afb-apiset.h
@@ -60,7 +60,7 @@ extern void afb_apiset_update_hooks(struct afb_apiset *set, const char *name);
extern void afb_apiset_set_logmask(struct afb_apiset *set, const char *name, int mask);
extern int afb_apiset_get_logmask(struct afb_apiset *set, const char *name);
-extern struct json_object *afb_apiset_describe(struct afb_apiset *set, const char *name);
+extern void afb_apiset_describe(struct afb_apiset *set, const char *name, void (*describecb)(void *, struct json_object *), void *closure);
extern const char **afb_apiset_get_names(struct afb_apiset *set, int rec, int type);
extern void afb_apiset_enum(
diff --git a/src/afb-export.c b/src/afb-export.c
index a9643f54..f96f8f81 100644
--- a/src/afb-export.c
+++ b/src/afb-export.c
@@ -1823,7 +1823,7 @@ static void api_call_cb(void *closure, struct afb_xreq *xreq)
}
}
-static struct json_object *api_describe_cb(void *closure)
+static void api_describe_cb(void *closure, void (*describecb)(void *, struct json_object *), void *clocb)
{
struct afb_export *export = closure;
struct json_object *result;
@@ -1846,7 +1846,7 @@ static struct json_object *api_describe_cb(void *closure)
result = NULL;
break;
}
- return result;
+ describecb(clocb, result);
}
static int api_service_start_cb(void *closure)
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)
diff --git a/src/afb-stub-ws.c b/src/afb-stub-ws.c
index 2a48745b..9bd8ed63 100644
--- a/src/afb-stub-ws.c
+++ b/src/afb-stub-ws.c
@@ -71,16 +71,6 @@ struct client_event
};
/**
- * structure for recording describe requests on the client side
- */
-struct client_describe
-{
- struct afb_stub_ws *stubws; /**< the stub */
- struct jobloop *jobloop; /**< the jobloop to leave */
- struct json_object *result; /**< result */
-};
-
-/**
* structure for jobs of describing
*/
struct server_describe
@@ -280,38 +270,17 @@ static void client_api_call_cb(void * closure, struct afb_xreq *xreq)
}
}
-static void client_on_description_cb(void *closure, struct json_object *data)
-{
- struct client_describe *desc = closure;
-
- desc->result = data;
- jobs_leave(desc->jobloop);
-}
-
-static void client_send_describe_cb(int signum, void *closure, struct jobloop *jobloop)
-{
- struct client_describe *desc = closure;
- struct afb_proto_ws *proto;
-
- proto = client_get_proto(desc->stubws);
- if (signum || proto == NULL)
- jobs_leave(jobloop);
- else {
- desc->jobloop = jobloop;
- afb_proto_ws_client_describe(proto, client_on_description_cb, desc);
- }
-}
-
/* get the description */
-static struct json_object *client_api_describe_cb(void * closure)
+static void client_api_describe_cb(void * closure, void (*describecb)(void *, struct json_object *), void *clocb)
{
- struct client_describe desc;
+ struct afb_stub_ws *stubws = closure;
+ struct afb_proto_ws *proto;
- /* synchronous job: send the request and wait its result */
- desc.stubws = closure;
- desc.result = NULL;
- jobs_enter(NULL, 0, client_send_describe_cb, &desc);
- return desc.result;
+ proto = client_get_proto(stubws);
+ if (proto)
+ afb_proto_ws_client_describe(proto, describecb, clocb);
+ else
+ describecb(clocb, NULL);
}
/******************* server part: manage events **********************************/
@@ -546,42 +515,19 @@ out_of_memory:
afb_proto_ws_call_unref(call);
}
-static void server_describe_cb(int signum, void *closure)
+static void server_on_description_cb(void *closure, struct json_object *description)
{
- struct json_object *obj;
- struct server_describe *desc = closure;
-
- /* get the description if possible */
- obj = !signum ? afb_apiset_describe(desc->stubws->apiset, desc->stubws->apiname) : NULL;
-
- /* send it */
- afb_proto_ws_describe_put(desc->describe, obj);
- json_object_put(obj);
- afb_stub_ws_unref(desc->stubws);
+ struct afb_proto_ws_describe *describe = closure;
+ afb_proto_ws_describe_put(describe, description);
+ json_object_put(description);
}
-static void server_describe_job(int signum, void *closure)
-{
- server_describe_cb(signum, closure);
- free(closure);
-}
static void server_on_describe_cb(void *closure, struct afb_proto_ws_describe *describe)
{
- struct server_describe *desc, sdesc;
struct afb_stub_ws *stubws = closure;
- /* allocate (if possible) and init */
- desc = malloc(sizeof *desc);
- if (desc == NULL)
- desc = &sdesc;
- desc->stubws = stubws;
- desc->describe = describe;
- afb_stub_ws_addref(stubws);
-
- /* process */
- if (desc == &sdesc || jobs_queue(NULL, 0, server_describe_job, desc) < 0)
- jobs_call(NULL, 0, server_describe_cb, desc);
+ afb_apiset_describe(stubws->apiset, stubws->apiname, server_on_description_cb, describe);
}
/*****************************************************/