diff options
author | José Bollo <jose.bollo@iot.bzh> | 2017-04-04 14:52:40 +0200 |
---|---|---|
committer | José Bollo <jose.bollo@iot.bzh> | 2017-04-04 14:52:40 +0200 |
commit | ede362db9ea82b85a531849c21582f1692bf0d4d (patch) | |
tree | cc2b274cc66cf959613230d447d03233b3c29033 /src | |
parent | 66c2dc7476c4a5105bcf233dd4e08f0466e7f3dc (diff) |
Add synchronous subcalls
Synchronous subcalls are more easy for
writing simple applications with sequential
logic.
Change-Id: I76a0231a64a6db8270014cd2a64284e1b0fc16ec
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
Diffstat (limited to 'src')
-rw-r--r-- | src/afb-apis.c | 53 | ||||
-rw-r--r-- | src/afb-apis.h | 1 | ||||
-rw-r--r-- | src/afb-msg-json.c | 10 | ||||
-rw-r--r-- | src/afb-msg-json.h | 1 | ||||
-rw-r--r-- | src/afb-subcall.c | 80 | ||||
-rw-r--r-- | src/afb-subcall.h | 9 | ||||
-rw-r--r-- | src/afb-svc.c | 5 | ||||
-rw-r--r-- | src/afb-xreq.c | 21 |
8 files changed, 141 insertions, 39 deletions
diff --git a/src/afb-apis.c b/src/afb-apis.c index 2f61fe95..0e257883 100644 --- a/src/afb-apis.c +++ b/src/afb-apis.c @@ -231,38 +231,55 @@ int afb_apis_start_all_services(int share_session) return 0; } +/** + * Internal direct dispatch of the request 'xreq' + * @param xreq the request to dispatch + */ +static void do_call_direct(struct afb_xreq *xreq) +{ + const struct api_desc *a; + /* search the api */ + a = search(xreq->api); + if (!a) + afb_xreq_fail_f(xreq, "unknown-api", "api %s not found", xreq->api); + else { + xreq->context.api_key = a->api.closure; + a->api.call(a->api.closure, xreq); + } +} - - - +/** + * Asynchronous dispatch callback for the request 'xreq' + * @param signum 0 on normal flow or the signal number that interupted the normal flow + */ static void do_call_async(int signum, void *arg) { struct afb_xreq *xreq = arg; - const struct api_desc *a; if (signum != 0) afb_xreq_fail_f(xreq, "aborted", "signal %s(%d) caught", strsignal(signum), signum); else { - /* search the api */ - a = search(xreq->api); - if (!a) - afb_xreq_fail_f(xreq, "unknown-api", "api %s not found", xreq->api); - else { - xreq->context.api_key = a->api.closure; - a->api.call(a->api.closure, xreq); - } + do_call_direct(xreq); } afb_xreq_unref(xreq); } /** - * Dispatch the request 'req' with the 'context' to the - * method of 'api' and 'verb'. - * @param req the request to dispatch - * @param context the context of the request - * @param api the api of the verb - * @param verb the verb within the api + * Dispatch the request 'xreq' synchronously and directly. + * @param xreq the request to dispatch + */ +void afb_apis_call_direct(struct afb_xreq *xreq) +{ + /* init hooking the request */ + // TODO req = afb_hook_req_call(req, context, api, verb); + + do_call_direct(xreq); +} + +/** + * Dispatch the request 'xreq' asynchronously. + * @param xreq the request to dispatch */ void afb_apis_call(struct afb_xreq *xreq) { diff --git a/src/afb-apis.h b/src/afb-apis.h index e9834d0e..dd3e6b6d 100644 --- a/src/afb-apis.h +++ b/src/afb-apis.h @@ -38,5 +38,6 @@ extern int afb_apis_start_all_services(int share_session); extern int afb_apis_start_service(const char *name, int share_session, int onneed); extern void afb_apis_call(struct afb_xreq *xreq); +extern void afb_apis_call_direct(struct afb_xreq *xreq); diff --git a/src/afb-msg-json.c b/src/afb-msg-json.c index 7702eb63..b4ae51b4 100644 --- a/src/afb-msg-json.c +++ b/src/afb-msg-json.c @@ -107,4 +107,14 @@ struct afb_arg afb_msg_json_get_arg(struct json_object *object, const char *name return arg; } +struct json_object *afb_msg_json_internal_error() +{ + static struct json_object *obj; + + if (obj == NULL) + obj = afb_msg_json_reply_error("failed", "internal error", NULL, NULL); + + return obj; +} + diff --git a/src/afb-msg-json.h b/src/afb-msg-json.h index 9805d3b8..0434e209 100644 --- a/src/afb-msg-json.h +++ b/src/afb-msg-json.h @@ -29,3 +29,4 @@ extern struct json_object *afb_msg_json_event(const char *event, struct json_obj extern struct afb_arg afb_msg_json_get_arg(struct json_object *object, const char *name); +extern struct json_object *afb_msg_json_internal_error(); diff --git a/src/afb-subcall.c b/src/afb-subcall.c index 81361a08..bc5fc862 100644 --- a/src/afb-subcall.c +++ b/src/afb-subcall.c @@ -29,6 +29,7 @@ #include "afb-context.h" #include "afb-xreq.h" #include "verbose.h" +#include "jobs.h" struct subcall; @@ -36,6 +37,7 @@ static void subcall_destroy(void *closure); static void subcall_reply(void *closure, int iserror, struct json_object *obj); static int subcall_subscribe(void *closure, struct afb_event event); static int subcall_unsubscribe(void *closure, struct afb_event event); +static void subcall_sync_leave(struct subcall *subcall); const struct afb_xreq_query_itf afb_subcall_xreq_itf = { .reply = subcall_reply, @@ -50,6 +52,9 @@ struct subcall struct afb_xreq *caller; void (*callback)(void*, int, struct json_object*); void *closure; + struct jobloop *jobloop; + struct json_object *result; + int iserror; }; static void subcall_destroy(void *closure) @@ -65,8 +70,14 @@ static void subcall_reply(void *closure, int iserror, struct json_object *obj) { struct subcall *subcall = closure; - subcall->callback(subcall->closure, iserror, obj); - json_object_put(obj); + if (subcall->callback) { + subcall->callback(subcall->closure, iserror, obj); + json_object_put(obj); + } else { + subcall->result = obj; + subcall->iserror = iserror; + subcall_sync_leave(subcall); + } } static int subcall_subscribe(void *closure, struct afb_event event) @@ -83,16 +94,6 @@ static int subcall_unsubscribe(void *closure, struct afb_event event) return afb_xreq_unsubscribe(subcall->caller, event); } -void afb_subcall_internal_error(void (*callback)(void*, int, struct json_object*), void *closure) -{ - static struct json_object *obj; - - if (obj == NULL) - obj = afb_msg_json_reply_error("failed", "internal error", NULL, NULL); - - callback(closure, 1, obj); -} - static struct subcall *create_subcall(struct afb_xreq *caller, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *closure) { struct subcall *subcall; @@ -102,7 +103,6 @@ static struct subcall *create_subcall(struct afb_xreq *caller, const char *api, return NULL; } - afb_context_subinit(&subcall->xreq.context, &caller->context); subcall->xreq.refcount = 1; subcall->xreq.json = args; @@ -113,6 +113,8 @@ static struct subcall *create_subcall(struct afb_xreq *caller, const char *api, subcall->caller = caller; subcall->callback = callback; subcall->closure = closure; + afb_xreq_addref(caller); + json_object_get(args); return subcall; } @@ -129,13 +131,61 @@ void afb_subcall( subcall = create_subcall(caller, api, verb, args, callback, closure); if (subcall == NULL) { - afb_subcall_internal_error(callback, closure); + callback(closure, 1, afb_msg_json_internal_error()); return; } - afb_xreq_addref(caller); afb_apis_call(&subcall->xreq); afb_xreq_unref(&subcall->xreq); } +static void subcall_sync_leave(struct subcall *subcall) +{ + struct jobloop *jobloop = subcall->jobloop; + subcall->jobloop = NULL; + if (jobloop) + jobs_leave(jobloop); +} + +static void subcall_sync_cb(int signum, void *closure, struct jobloop *jobloop) +{ + struct subcall *subcall = closure; + + if (!signum) { + subcall->jobloop = jobloop; + afb_apis_call_direct(&subcall->xreq); + } else { + afb_xreq_fail_f(&subcall->xreq, "aborted", "signal %s(%d) caught", strsignal(signum), signum); + } + subcall_sync_leave(subcall); +} + +int afb_subcall_sync( + struct afb_xreq *caller, + const char *api, + const char *verb, + struct json_object *args, + struct json_object **result +) +{ + int rc; + struct subcall *subcall; + + subcall = create_subcall(caller, api, verb, args, NULL, NULL); + if (subcall == NULL) { + *result = json_object_get(afb_msg_json_internal_error()); + return 0; + } + + rc = jobs_enter(NULL, 0, subcall_sync_cb, subcall); + if (rc < 0) { + subcall->result = json_object_get(afb_msg_json_internal_error()); + subcall->iserror = 1; + } + rc = !subcall->iserror; + *result = subcall->result; + afb_xreq_unref(&subcall->xreq); + return rc; +} + diff --git a/src/afb-subcall.h b/src/afb-subcall.h index 7d29e1a2..bf3d8cd1 100644 --- a/src/afb-subcall.h +++ b/src/afb-subcall.h @@ -28,7 +28,10 @@ extern void afb_subcall( void (*callback)(void*, int, struct json_object*), void *closure); -extern void afb_subcall_internal_error( - void (*callback)(void*, int, struct json_object*), - void *closure); +extern int afb_subcall_sync( + struct afb_xreq *caller, + const char *api, + const char *verb, + struct json_object *args, + struct json_object **result); diff --git a/src/afb-svc.c b/src/afb-svc.c index 93e85533..59e775cd 100644 --- a/src/afb-svc.c +++ b/src/afb-svc.c @@ -27,7 +27,7 @@ #include "afb-session.h" #include "afb-context.h" #include "afb-evt.h" -#include "afb-subcall.h" +#include "afb-msg-json.h" #include "afb-svc.h" #include "afb-xreq.h" #include "afb-apis.h" @@ -228,7 +228,8 @@ static void svc_call(void *closure, const char *api, const char *verb, struct js if (svcreq == NULL) { ERROR("out of memory"); json_object_put(args); - return afb_subcall_internal_error(callback, cbclosure); + callback(cbclosure, 1, afb_msg_json_internal_error()); + return; } /* initialises the request */ diff --git a/src/afb-xreq.c b/src/afb-xreq.c index c8fd94e9..15ebae05 100644 --- a/src/afb-xreq.c +++ b/src/afb-xreq.c @@ -62,6 +62,13 @@ static void xreq_subcall_cb( void (*callback)(void*, int, struct json_object*), void *cb_closure); +static int xreq_subcallsync_cb( + void *closure, + const char *api, + const char *verb, + struct json_object *args, + struct json_object **result); + const struct afb_req_itf xreq_itf = { .json = xreq_json_cb, .get = xreq_get_cb, @@ -77,7 +84,8 @@ const struct afb_req_itf xreq_itf = { .session_set_LOA = xreq_session_set_LOA_cb, .subscribe = xreq_subscribe_cb, .unsubscribe = xreq_unsubscribe_cb, - .subcall = xreq_subcall_cb + .subcall = xreq_subcall_cb, + .subcallsync = xreq_subcallsync_cb }; static struct json_object *xreq_json_cb(void *closure) @@ -248,6 +256,17 @@ static void xreq_subcall_cb(void *closure, const char *api, const char *verb, st afb_subcall(xreq, api, verb, args, callback, cb_closure); } +static int xreq_subcallsync_cb(void *closure, const char *api, const char *verb, struct json_object *args, struct json_object **result) +{ + struct afb_xreq *xreq = closure; +/* + if (xreq->queryitf->subcallsync) + xreq->queryitf->subcall(xreq->query, api, verb, args, callback, cb_closure); + else +*/ + return afb_subcall_sync(xreq, api, verb, args, result); +} + void afb_xreq_success_f(struct afb_xreq *xreq, struct json_object *obj, const char *info, ...) { char *message; |