aboutsummaryrefslogtreecommitdiffstats
path: root/src/aft.c
diff options
context:
space:
mode:
authorRomain Forlot <romain.forlot@iot.bzh>2018-12-13 08:53:55 +0100
committerRomain Forlot <romain.forlot@iot.bzh>2018-12-13 11:33:40 +0100
commit57020f4e0ba8a92b362782b5642f1b1ee58f003c (patch)
tree6ad0f47cf4611ed86d15fb053cfe103290ac66eb /src/aft.c
parent0f14669f9558ede31f19a179a4cb9d13330caaf1 (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/aft.c')
-rw-r--r--src/aft.c66
1 files changed, 64 insertions, 2 deletions
diff --git a/src/aft.c b/src/aft.c
index 01bfaa2..9500368 100644
--- a/src/aft.c
+++ b/src/aft.c
@@ -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;