diff options
author | Romain Forlot <romain.forlot@iot.bzh> | 2018-12-13 08:53:55 +0100 |
---|---|---|
committer | Romain Forlot <romain.forlot@iot.bzh> | 2018-12-13 11:33:40 +0100 |
commit | 57020f4e0ba8a92b362782b5642f1b1ee58f003c (patch) | |
tree | 6ad0f47cf4611ed86d15fb053cfe103290ac66eb /src | |
parent | 0f14669f9558ede31f19a179a4cb9d13330caaf1 (diff) |
Clean way to wait for an api's event
Modify the way to wait for an event. Here we call synchronously a verb of the
test api that will end when a timeout expires or when the reception of the event
ends the request
Useless set up of verbosity to debug for the monitoring API.
"push_after" messages could be caught without setting up this.
Bump app-controller-submodule:
Submodule app-controller-submodule 303022b..4ddd789:
> memleak fixes
> Retrieve by default an int64 instead of int
> New function to retrieve Api's name from LUA
> Handle number and boolean to subcall an api's verb
> Fix: compiling a controller without LUA support
> Fix Parse plugin
> AFB:servsync: add string for query argument
Bug-AGL: SPEC-2003
Depends-On: https://gerrit.automotivelinux.org/gerrit/#/c/18583/
Change-Id: I24af6bae6a9aa0f70f3b78304134a65e09f12a58
Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
Diffstat (limited to 'src')
-rw-r--r-- | src/aft.c | 66 |
1 files changed, 64 insertions, 2 deletions
@@ -18,8 +18,10 @@ #define _GNU_SOURCE #include <stdio.h> -#include <string.h> #include <time.h> +#include <pthread.h> +#include <string.h> +#include <systemd/sd-event.h> #include "aft.h" #include "mapis.h" @@ -29,6 +31,9 @@ static CtlConfigT *CtrlLoadConfigJson(afb_api_t apiHandle, json_object *configJ); static CtlConfigT *CtrlLoadConfigFile(afb_api_t apiHandle, const char *configPath); static int CtrlCreateApi(afb_api_t apiHandle, CtlConfigT *ctrlConfig); +static pthread_mutex_t memo_lock; +static afb_req_t memo_sync = NULL; +static struct sd_event_source *timersrc = NULL; // Config Section definition static CtlSectionT ctrlSections[] = { @@ -79,15 +84,67 @@ static void ctrlapi_load(afb_req_t request) { static void ctrlapi_exit(afb_req_t request) { AFB_REQ_NOTICE(request, "Exiting..."); + pthread_mutex_destroy(&memo_lock); afb_req_success(request, NULL, NULL); exit(0); } +static int timeoutCB(struct sd_event_source *s, uint64_t us, void *ud) +{ + if (memo_sync) + afb_req_reply(memo_sync, NULL, "timeout", NULL); + memo_sync = NULL; + timersrc = NULL; + + return 0; +} +/** + * @brief A verb to call synchronously that will end when a timeout expires or + * when a call with a 'stop' order given in the arguments. + * + * @param request: the AFB request object + */ +static void ctrlapi_sync(afb_req_t request) { + struct json_object *obj, *val; + uint64_t to, usec; + + AFB_REQ_NOTICE(request, "Syncing..."); + + pthread_mutex_lock(&memo_lock); + obj = afb_req_json(request); + if (json_object_object_get_ex(obj, "start", &val)) { + to = json_object_get_int(val); + if (memo_sync) + afb_req_reply(request, NULL, "Bad-State", "There is an already ongoing waiting request."); + else { + sd_event_now(afb_api_get_event_loop(afb_req_get_api(request)), CLOCK_MONOTONIC, &usec); + usec = to + usec; + sd_event_add_time(afb_api_get_event_loop(afb_req_get_api(request)), &timersrc, CLOCK_MONOTONIC, usec, 0, timeoutCB, NULL); + memo_sync = afb_req_addref(request); + } + } else if (json_object_object_get_ex(obj, "stop", &val)) { + if (!memo_sync) + afb_req_reply(request, NULL, "Bad-State", "There isn't any ongoing waiting request."); + else { + afb_req_reply(memo_sync, json_object_get(val), NULL, NULL); + afb_req_unref(memo_sync); + sd_event_source_unref(timersrc); + memo_sync = NULL; + timersrc = NULL; + afb_req_reply(request, NULL, NULL, NULL); + } + } else + afb_req_reply(request, NULL, "Invalid", "No 'start' nor 'stop' order provided."); + + pthread_mutex_unlock(&memo_lock); +} + static afb_verb_t CtrlApiVerbs[] = { /* VERB'S NAME FUNCTION TO CALL SHORT DESCRIPTION */ {.verb = "ping", .callback = ctrlapi_ping, .info = "ping test for API"}, {.verb = "load", .callback = ctrlapi_load, .info = "load a API meant to launch test for a binding"}, {.verb = "exit", .callback = ctrlapi_exit, .info = "Exit test"}, + {.verb = "sync", .callback = ctrlapi_sync, .info = "Manually make a sync for something using a synchronous subcall"}, {.verb = NULL} /* marker for end of the array */ }; @@ -112,6 +169,11 @@ static int CtrlInitOneApi(afb_api_t apiHandle) { static int CtrlLoadOneApi(void *cbdata, afb_api_t apiHandle) { CtlConfigT *ctrlConfig = (CtlConfigT *)cbdata; + if(pthread_mutex_init(&memo_lock, NULL)) { + AFB_API_ERROR(apiHandle, "Fail to initialize"); + return -1; + } + // save closure as api's data context afb_api_set_userdata(apiHandle, ctrlConfig); @@ -178,7 +240,7 @@ static int CtrlCreateApi(afb_api_t apiHandle, CtlConfigT *ctrlConfig) { wrap_json_object_add(ctrlConfig->configJ, resourcesJ); wrap_json_object_add(ctrlConfig->configJ, eventsJ); - if(! afb_api_new_api(apiHandle, ctrlConfig->api, ctrlConfig->info, 1, CtrlLoadOneApi, ctrlConfig)) + if(! afb_api_new_api(apiHandle, ctrlConfig->api, ctrlConfig->info, 0, CtrlLoadOneApi, ctrlConfig)) return ERROR; return 0; |