X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafb-monitor.c;h=40a6d3bd57862a768060f6573017c3c97a14be3f;hb=65353dce81a629e042800bb7b86fcd869a76727e;hp=a0618113039cdb640b54af4ab7ad2c90a99ce222;hpb=ae6f684d830871e81b0b4168424f6a4873eabbff;p=src%2Fapp-framework-binder.git diff --git a/src/afb-monitor.c b/src/afb-monitor.c index a0618113..40a6d3bd 100644 --- a/src/afb-monitor.c +++ b/src/afb-monitor.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016, 2017 "IoT.bzh" + * Copyright (C) 2015-2020 "IoT.bzh" * Author José Bollo * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,33 +16,30 @@ */ #define _GNU_SOURCE -#define AFB_BINDING_PRAGMA_NO_VERBOSE_MACRO #include #include + +#define AFB_BINDING_VERSION 3 #include #include "afb-api.h" #include "afb-apiset.h" -#include "afb-api-so-v2.h" -#include "afb-ditf.h" +#include "afb-api-v3.h" +#include "afb-evt.h" #include "afb-xreq.h" +#include "afb-trace.h" +#include "afb-session.h" +#include "afb-error-text.h" #include "verbose.h" +#include "wrap-json.h" #include "monitor-api.inc" -extern struct afb_apiset *main_apiset; -int afb_monitor_init() -{ - static int v; - return afb_api_so_v2_add_binding(&_afb_binding_v2_monitor, NULL, main_apiset, &v); -} - -/****************************************************************************** -**** Monitoring verbosity -******************************************************************************/ +static const char _verbosity_[] = "verbosity"; +static const char _apis_[] = "apis"; static const char _debug_[] = "debug"; static const char _info_[] = "info"; @@ -50,6 +47,19 @@ 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) +{ + target_set = call_set; + return -!afb_api_v3_from_binding(&_afb_binding_monitor, declare_set, call_set); +} + +/****************************************************************************** +**** Monitoring verbosity +******************************************************************************/ + /** * Translate verbosity indication to an integer value. * @param v the verbosity indication @@ -59,31 +69,30 @@ static int decode_verbosity(struct json_object *v) { const char *s; int level = -1; - if (json_object_is_type(v, json_type_int)) { - level = json_object_get_int(v); - level = level < 0 ? 0 : level > 3 ? 3 : level; - } else if (json_object_is_type(v, json_type_string)) { - s = json_object_get_string(v); + + if (!wrap_json_unpack(v, "i", &level)) { + level = level < _VERBOSITY_(Log_Level_Error) ? _VERBOSITY_(Log_Level_Error) : level > _VERBOSITY_(Log_Level_Debug) ? _VERBOSITY_(Log_Level_Debug) : level; + } else if (!wrap_json_unpack(v, "s", &s)) { switch(*s&~' ') { case 'D': if (!strcasecmp(s, _debug_)) - level = 3; + level = _VERBOSITY_(Log_Level_Debug); break; case 'I': if (!strcasecmp(s, _info_)) - level = 2; + level = _VERBOSITY_(Log_Level_Info); break; case 'N': if (!strcasecmp(s, _notice_)) - level = 1; + level = _VERBOSITY_(Log_Level_Notice); break; case 'W': if (!strcasecmp(s, _warning_)) - level = 1; + level = _VERBOSITY_(Log_Level_Warning); break; case 'E': if (!strcasecmp(s, _error_)) - level = 0; + level = _VERBOSITY_(Log_Level_Error); break; } } @@ -96,9 +105,10 @@ static int decode_verbosity(struct json_object *v) * @param the name of the api to set * @param closure the verbosity to set as an integer casted to a pointer */ -static void set_verbosity_to_all_cb(struct afb_apiset *set, const char *name, void *closure) +static void set_verbosity_to_all_cb(void *closure, struct afb_apiset *set, const char *name, int isalias) { - afb_apiset_set_verbosity(set, name, (int)(intptr_t)closure); + if (!isalias) + afb_apiset_set_logmask(set, name, (int)(intptr_t)closure); } /** @@ -108,12 +118,13 @@ static void set_verbosity_to_all_cb(struct afb_apiset *set, const char *name, vo */ static void set_verbosity_to(const char *name, int level) { + int mask = verbosity_to_mask(level); if (!name || !name[0]) - verbosity = level; + verbosity_set(level); else if (name[0] == '*' && !name[1]) - afb_apiset_enum(main_apiset, set_verbosity_to_all_cb, (void*)(intptr_t)level); + afb_apiset_enum(target_set, 1, set_verbosity_to_all_cb, (void*)(intptr_t)mask); else - afb_apiset_set_verbosity(main_apiset, name, level); + afb_apiset_set_logmask(target_set, name, mask); } /** @@ -145,16 +156,17 @@ static void set_verbosity(struct json_object *spec) /** * Translate verbosity level to a protocol indication. - * @param level the verbosity + * @param level the verbosity * @return the encoded verbosity */ static struct json_object *encode_verbosity(int level) { - switch(level) { - case 0: return json_object_new_string(_error_); - case 1: return json_object_new_string(_notice_); - case 2: return json_object_new_string(_info_); - case 3: return json_object_new_string(_debug_); + switch(_DEVERBOSITY_(level)) { + case Log_Level_Error: return json_object_new_string(_error_); + case Log_Level_Warning: return json_object_new_string(_warning_); + case Log_Level_Notice: return json_object_new_string(_notice_); + case Log_Level_Info: return json_object_new_string(_info_); + case Log_Level_Debug: return json_object_new_string(_debug_); default: return json_object_new_int(level); } } @@ -165,12 +177,12 @@ static struct json_object *encode_verbosity(int level) * @param the name of the api to set * @param closure the json object to build */ -static void get_verbosity_of_all_cb(struct afb_apiset *set, const char *name, void *closure) +static void get_verbosity_of_all_cb(void *closure, struct afb_apiset *set, const char *name, int isalias) { struct json_object *resu = closure; - int l = afb_apiset_get_verbosity(set, name); - if (l >= 0) - json_object_object_add(resu, name, encode_verbosity(l)); + int m = afb_apiset_get_logmask(set, name); + if (m >= 0) + json_object_object_add(resu, name, encode_verbosity(verbosity_from_mask(m))); } /** @@ -180,15 +192,15 @@ static void get_verbosity_of_all_cb(struct afb_apiset *set, const char *name, vo */ static void get_verbosity_of(struct json_object *resu, const char *name) { - int l; + int m; if (!name || !name[0]) - json_object_object_add(resu, "", encode_verbosity(verbosity)); + json_object_object_add(resu, "", encode_verbosity(verbosity_get())); else if (name[0] == '*' && !name[1]) - afb_apiset_enum(main_apiset, get_verbosity_of_all_cb, resu); + afb_apiset_enum(target_set, 1, get_verbosity_of_all_cb, resu); else { - l = afb_apiset_get_verbosity(main_apiset, name); - if (l >= 0) - json_object_object_add(resu, name, encode_verbosity(l)); + m = afb_apiset_get_logmask(target_set, name); + if (m >= 0) + json_object_object_add(resu, name, encode_verbosity(verbosity_from_mask(m))); } } @@ -197,11 +209,13 @@ static void get_verbosity_of(struct json_object *resu, const char *name) * @param resu the json object to build * @param spec specification of the verbosity to set */ -static void get_verbosity(struct json_object *resu, struct json_object *spec) +static struct json_object *get_verbosity(struct json_object *spec) { int i, n; + struct json_object *resu; struct json_object_iterator it, end; + resu = json_object_new_object(); if (json_object_is_type(spec, json_type_object)) { it = json_object_iter_begin(spec); end = json_object_iter_end(spec); @@ -210,129 +224,252 @@ static void get_verbosity(struct json_object *resu, struct json_object *spec) json_object_iter_next(&it); } } else if (json_object_is_type(spec, json_type_array)) { - n = json_object_array_length(spec); + n = (int)json_object_array_length(spec); for (i = 0 ; i < n ; i++) get_verbosity_of(resu, json_object_get_string(json_object_array_get_idx(spec, i))); + } else if (json_object_is_type(spec, json_type_string)) { + get_verbosity_of(resu, json_object_get_string(spec)); } else if (json_object_get_boolean(spec)) { get_verbosity_of(resu, ""); get_verbosity_of(resu, "*"); } + return resu; } /****************************************************************************** -**** 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 afb_api api; - int rc; + struct namelist *previous, *next; + + previous = NULL; + while(head) { + next = head->next; + head->next = previous; + previous = head; + head = next; + } + return previous; +} - rc = afb_apiset_lookup(main_apiset, name, &api); - if (!rc) { - o = api.itf->describe ? api.itf->describe(api.closure) : NULL; - 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(struct afb_apiset *set, const char *name, void *closure) +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 void get_apis(struct json_object *resu, struct json_object *spec) +static struct namelist *get_apis_namelist(struct json_object *spec) { int i, n; struct json_object_iterator it, end; + struct namelist *head; + 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 = json_object_array_length(spec); + 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)) { + add_one_name_to_namelist(&head, json_object_get_string(spec), NULL); } else if (json_object_get_boolean(spec)) { - afb_apiset_enum(main_apiset, get_apis_of_all_cb, resu); + afb_apiset_enum(target_set, 1, get_apis_namelist_of_all_cb, &head); } + 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 f_get(struct afb_req req) +static void on_api_description(void *closure, struct json_object *apidesc) { - struct json_object *o, *v, *r, *x; + 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); + } +} - r = json_object_new_object(); - o = afb_req_json(req); +static void describe_apis(afb_req_t req, struct json_object *resu, struct json_object *spec) +{ + struct desc_apis *desc; - if (json_object_object_get_ex(o, _verbosity_, &v)) { - x = json_object_new_object(); - json_object_object_add(r, _verbosity_, x); - get_verbosity(x, v); + 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) +{ + struct json_object *r; + struct json_object *apis = NULL; + struct json_object *verbosity = NULL; - if (json_object_object_get_ex(o, _apis_, &v)) { - x = json_object_new_object(); - json_object_object_add(r, _apis_, x); - get_apis(x, v); + wrap_json_unpack(afb_req_json(req), "{s?:o,s?:o}", _verbosity_, &verbosity, _apis_, &apis); + 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) +{ + struct json_object *verbosity = NULL; - afb_req_success(req, json_object_get(r), NULL); - json_object_put(r); + wrap_json_unpack(afb_req_json(req), "{s?:o}", _verbosity_, &verbosity); + if (verbosity) + set_verbosity(verbosity); + + afb_req_success(req, NULL, NULL); } -static void f_set(struct afb_req req) +#if WITH_AFB_TRACE +static void *context_create(void *closure) { - struct json_object *o, *v; + return afb_trace_create(_afb_binding_monitor.api, NULL); +} - o = afb_req_json(req); - if (json_object_object_get_ex(o, _verbosity_, &v)) { - set_verbosity(v); - } +static void context_destroy(void *pointer) +{ + struct afb_trace *trace = pointer; + afb_trace_unref(trace); +} +static void f_trace(afb_req_t req) +{ + int rc; + struct json_object *add = NULL; + struct json_object *drop = NULL; + struct afb_trace *trace; + + trace = afb_req_context(req, 0, context_create, context_destroy, NULL); + wrap_json_unpack(afb_req_json(req), "{s?o s?o}", "add", &add, "drop", &drop); + if (add) { + rc = afb_trace_add(req, add, trace); + if (rc) + goto end; + } + if (drop) { + rc = afb_trace_drop(req, drop, trace); + if (rc) + goto end; + } afb_req_success(req, NULL, NULL); +end: + afb_apiset_update_hooks(target_set, NULL); + afb_evt_update_hooks(); + return; } +#else +static void f_trace(afb_req_t req) +{ + afb_req_reply(req, NULL, afb_error_text_not_available, NULL); +} +#endif -#if 0 -static void f_hook(struct afb_xreq *xreq) +static void f_session(afb_req_t req) { - struct json_object *o, *v; + struct json_object *r = NULL; + struct afb_xreq *xreq = xreq_from_req_x2(req); - o = afb_xreq_json(xreq); - if (json_object_object_get_ex(o, _verbosity_, &v)) { - set_verbosity(v); + /* check right to call it */ + if (xreq->context.super) { + afb_req_fail(req, "invalid", "reserved to direct clients"); + return; } - if (!xreq->replied) - afb_xreq_success(xreq, NULL, NULL); + /* make the result */ + wrap_json_pack(&r, "{s:s,s:i,s:i}", + "uuid", afb_session_uuid(xreq->context.session), + "timeout", afb_session_timeout(xreq->context.session), + "remain", afb_session_what_remains(xreq->context.session)); + afb_req_success(req, r, NULL); } -#endif