hello3: Add verb 'after' 03/19403/2
authorJose Bollo <jose.bollo@iot.bzh>
Mon, 31 Dec 2018 10:15:19 +0000 (11:15 +0100)
committerJose Bollo <jose.bollo@iot.bzh>
Wed, 2 Jan 2019 08:46:01 +0000 (09:46 +0100)
The verb 'after' launches a new thread
that after a delay will call a verb (like
call). The type of call can be set to 'call',
'callsync', 'subcall' or 'subcallsync'.

This allows to add test for asynchronous issues
in multithreaded environment.

Change-Id: Ic59a27b7b7fbd3716d34fdaa35c42aa9ecb7f201
Signed-off-by: Jose Bollo <jose.bollo@iot.bzh>
bindings/samples/README.md
bindings/samples/hello3.c

index 587da22..091b733 100644 (file)
@@ -9,6 +9,6 @@ The provide examples here are:
 * DemoContext (context): as AuthLogin with use of LOA
 * DemoPost (post): shows how to use HTTP to transfer files
 * tic-tac-toe (tictactoe): example explain in the documentation
-* hello3 (hello3): toolset for exhaustive use of the binder API v3
+* hello3 (hello): toolset for exhaustive use of the binder API v3
 * hello2 (hello2): toolset for use of the binder API v2 (legacy)
 
index b50ea46..131e0e4 100644 (file)
@@ -19,6 +19,8 @@
 #include <string.h>
 #include <pthread.h>
 #include <fcntl.h>
+#include <math.h>
+#include <errno.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -29,7 +31,7 @@
 #include <afb/afb-binding.h>
 
 #if !defined(APINAME)
-#define APINAME "hello3"
+#define APINAME "hello"
 #endif
 
 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -618,6 +620,79 @@ static void locale (afb_req_t request)
        }
 }
 
+static void in_after (afb_req_t request)
+{
+       int rc;
+       const char *ts, *ty;
+       char *te;
+       double td;
+       struct timespec t;
+       void (*calling)(afb_req_t);
+
+       /* get the type */
+       ty = afb_req_value(request, "type") ?: "call";
+       if (strcmp(ty, "call") && strcmp(ty, "callsync")
+        && strcmp(ty, "subcall") && strcmp(ty, "subcallsync"))
+               return afb_req_reply(request, NULL, "invalid", "bad type");
+
+       /* get the delay */
+       ts = afb_req_value(request, "delay");
+       if (!ts)
+               return afb_req_reply(request, NULL, "invalid", "no delay");
+       td = strtod(ts, &te);
+       if (*te || td < 0 || td > 3e6) /* a month is the biggest accepted */
+               return afb_req_reply(request, NULL, "invalid", "bad delay");
+
+       /* wait for that time */
+       if (td > 0) {
+               t.tv_nsec = (long)(1e6 * modf(td, &td));
+               t.tv_sec = (time_t)td;
+               do {
+                       rc = nanosleep(&t, &t);
+               } while (rc != 0 && errno == EINTR);
+
+               if (rc)
+                       return afb_req_reply(request, NULL, "error", "sleep failed");
+       }
+
+       /* do the call */
+       if (!strcmp(ty, "subcallsync"))
+               subcall(request);
+       else if (!strcmp(ty, "subcall"))
+               subcallsync(request);
+       else if (!strcmp(ty, "callsync"))
+               callsync(request);
+       else
+               call(request);
+}
+
+static void *thread_after (void *closure)
+{
+       afb_req_t request = closure;
+       in_after (request);
+       afb_req_unref(request);
+       return NULL;
+}
+
+static void after (afb_req_t request)
+{
+       int rc;
+       pthread_t tid;
+       pthread_attr_t attr;
+
+       afb_req_addref(request);
+
+       pthread_attr_init(&attr);
+       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+       rc =pthread_create(&tid, &attr, thread_after, request);
+       pthread_attr_destroy(&attr);
+
+       if (rc != 0) {
+               afb_req_unref(request);
+               afb_req_reply(request, NULL, "cant-start", NULL);
+       }
+}
+
 static void api (afb_req_t request);
 
 /**
@@ -735,6 +810,7 @@ static const struct afb_verb_v3 verbs[]= {
   { .verb="setctx",      .callback=setctx, .vcbdata = (void*)(intptr_t)1 },
   { .verb="setctxif",    .callback=setctx, .vcbdata = (void*)(intptr_t)0 },
   { .verb="getctx",      .callback=getctx },
+  { .verb="checktok",    .callback=ok, .session=AFB_SESSION_CHECK },
   { .verb="reftok",      .callback=ok, .session=AFB_SESSION_CHECK | AFB_SESSION_REFRESH },
   { .verb="info",        .callback=info },
   { .verb="eventloop",   .callback=eventloop },
@@ -749,6 +825,7 @@ static const struct afb_verb_v3 verbs[]= {
   { .verb="mutebug",     .callback=mutebug},
   { .verb="queue",       .callback=queue},
   { .verb="settings",    .callback=settings},
+  { .verb="after",       .callback=after},
   { .verb=NULL}
 };