From 03f863dd080d32f71c4a0755c02e23c72e4cb342 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Bollo?= Date: Wed, 12 Apr 2017 17:00:33 +0200 Subject: [PATCH] Optimisation of xreq MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Reduce the count of memory read Change-Id: Ie4dfa4bd30d6485be91961196294c43ffbd3b2a9 Signed-off-by: José Bollo --- src/afb-api-dbus.c | 28 +++++++++++++--------------- src/afb-api-ws.c | 34 ++++++++++++++++------------------ src/afb-hreq.c | 40 +++++++++++++++++++++------------------- src/afb-subcall.c | 28 +++++++++++++--------------- src/afb-svc.c | 33 +++++++++------------------------ src/afb-ws-json1.c | 27 +++++++++++---------------- src/afb-xreq.c | 27 ++++++++++++++++----------- src/afb-xreq.h | 24 +++++++++++++----------- src/main.c | 14 ++++++-------- 9 files changed, 118 insertions(+), 137 deletions(-) diff --git a/src/afb-api-dbus.c b/src/afb-api-dbus.c index 593232b9..b8ec3d02 100644 --- a/src/afb-api-dbus.c +++ b/src/afb-api-dbus.c @@ -808,9 +808,9 @@ struct dbus_req { }; /* decrement the reference count of the request and free/release it on falling to null */ -static void dbus_req_destroy(void *closure) +static void dbus_req_destroy(struct afb_xreq *xreq) { - struct dbus_req *dreq = closure; + struct dbus_req *dreq = CONTAINER_OF_XREQ(struct dbus_req, xreq); afb_context_disconnect(&dreq->xreq.context); json_object_put(dreq->json); @@ -819,9 +819,9 @@ static void dbus_req_destroy(void *closure) } /* get the object of the request */ -static struct json_object *dbus_req_json(void *closure) +static struct json_object *dbus_req_json(struct afb_xreq *xreq) { - struct dbus_req *dreq = closure; + struct dbus_req *dreq = CONTAINER_OF_XREQ(struct dbus_req, xreq); return dreq->json; } @@ -836,25 +836,25 @@ static void dbus_req_reply(struct dbus_req *dreq, uint8_t type, const char *firs ERROR("sending the reply failed"); } -static void dbus_req_success(void *closure, struct json_object *obj, const char *info) +static void dbus_req_success(struct afb_xreq *xreq, struct json_object *obj, const char *info) { - struct dbus_req *dreq = closure; + struct dbus_req *dreq = CONTAINER_OF_XREQ(struct dbus_req, xreq); dbus_req_reply(dreq, RETOK, json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN), info); } -static void dbus_req_fail(void *closure, const char *status, const char *info) +static void dbus_req_fail(struct afb_xreq *xreq, const char *status, const char *info) { - struct dbus_req *dreq = closure; + struct dbus_req *dreq = CONTAINER_OF_XREQ(struct dbus_req, xreq); dbus_req_reply(dreq, RETERR, status, info); } static void afb_api_dbus_server_event_send(struct origin *origin, char order, const char *event, int eventid, const char *data, uint64_t msgid); -static int dbus_req_subscribe(void *closure, struct afb_event event) +static int dbus_req_subscribe(struct afb_xreq *xreq, struct afb_event event) { - struct dbus_req *dreq = closure; + struct dbus_req *dreq = CONTAINER_OF_XREQ(struct dbus_req, xreq); uint64_t msgid; int rc; @@ -864,9 +864,9 @@ static int dbus_req_subscribe(void *closure, struct afb_event event) return rc; } -static int dbus_req_unsubscribe(void *closure, struct afb_event event) +static int dbus_req_unsubscribe(struct afb_xreq *xreq, struct afb_event event) { - struct dbus_req *dreq = closure; + struct dbus_req *dreq = CONTAINER_OF_XREQ(struct dbus_req, xreq); uint64_t msgid; int rc; @@ -976,6 +976,7 @@ static int api_dbus_server_on_object_called(sd_bus_message *message, void *userd } /* connect to the context */ + afb_xreq_init(&dreq->xreq, &afb_api_dbus_xreq_itf); if (afb_context_connect(&dreq->xreq.context, uuid, NULL) < 0) goto out_of_memory; session = dreq->xreq.context.session; @@ -994,9 +995,6 @@ static int api_dbus_server_on_object_called(sd_bus_message *message, void *userd dreq->json = json_object_new_string(dreq->request); } dreq->listener = listener; - dreq->xreq.refcount = 1; - dreq->xreq.query = dreq; - dreq->xreq.queryitf = &afb_api_dbus_xreq_itf; dreq->xreq.api = api->api; dreq->xreq.verb = method; afb_apis_call(&dreq->xreq); diff --git a/src/afb-api-ws.c b/src/afb-api-ws.c index 8be74c03..472a44d4 100644 --- a/src/afb-api-ws.c +++ b/src/afb-api-ws.c @@ -159,11 +159,11 @@ struct api_ws_server_req { uint32_t msgid; /* the incoming request msgid */ }; -static void api_ws_server_req_success_cb(void *closure, struct json_object *obj, const char *info); -static void api_ws_server_req_fail_cb(void *closure, const char *status, const char *info); -static void api_ws_server_req_destroy_cb(void *closure); -static int api_ws_server_req_subscribe_cb(void *closure, struct afb_event event); -static int api_ws_server_req_unsubscribe_cb(void *closure, struct afb_event event); +static void api_ws_server_req_success_cb(struct afb_xreq *xreq, struct json_object *obj, const char *info); +static void api_ws_server_req_fail_cb(struct afb_xreq *xreq, const char *status, const char *info); +static void api_ws_server_req_destroy_cb(struct afb_xreq *xreq); +static int api_ws_server_req_subscribe_cb(struct afb_xreq *xreq, struct afb_event event); +static int api_ws_server_req_unsubscribe_cb(struct afb_xreq *xreq, struct afb_event event); const struct afb_xreq_query_itf afb_api_ws_xreq_itf = { .success = api_ws_server_req_success_cb, @@ -937,6 +937,7 @@ static void api_ws_server_called(struct api_ws_client *client, struct readbuf *r || !api_ws_read_string(rb, &wreq->request, &wreq->lenreq)) goto overflow; + afb_xreq_init(&wreq->xreq, &afb_api_ws_xreq_itf); wreq->xreq.json = json_tokener_parse(wreq->request); if (wreq->xreq.json == NULL && strcmp(wreq->request, "null")) { wreq->xreq.json = json_object_new_string(wreq->request); @@ -948,11 +949,8 @@ static void api_ws_server_called(struct api_ws_client *client, struct readbuf *r wreq->xreq.context.flags = flags; /* makes the call */ - wreq->xreq.refcount = 1; wreq->xreq.api = client->api; wreq->xreq.verb = verb; - wreq->xreq.query = wreq; - wreq->xreq.queryitf = &afb_api_ws_xreq_itf; afb_apis_call(&wreq->xreq); afb_xreq_unref(&wreq->xreq); return; @@ -1071,9 +1069,9 @@ static void api_ws_server_event_broadcast(void *closure, const char *event, int /******************* ws request part for server *****************/ /* decrement the reference count of the request and free/release it on falling to null */ -static void api_ws_server_req_destroy_cb(void *closure) +static void api_ws_server_req_destroy_cb(struct afb_xreq *xreq) { - struct api_ws_server_req *wreq = closure; + struct api_ws_server_req *wreq = CONTAINER_OF_XREQ(struct api_ws_server_req, xreq); afb_context_disconnect(&wreq->xreq.context); json_object_put(wreq->xreq.json); @@ -1082,11 +1080,11 @@ static void api_ws_server_req_destroy_cb(void *closure) free(wreq); } -static void api_ws_server_req_success_cb(void *closure, struct json_object *obj, const char *info) +static void api_ws_server_req_success_cb(struct afb_xreq *xreq, struct json_object *obj, const char *info) { int rc; struct writebuf wb = { .count = 0 }; - struct api_ws_server_req *wreq = closure; + struct api_ws_server_req *wreq = CONTAINER_OF_XREQ(struct api_ws_server_req, xreq); if (api_ws_write_char(&wb, 'T') && api_ws_write_uint32(&wb, wreq->msgid) @@ -1102,11 +1100,11 @@ success: json_object_put(obj); } -static void api_ws_server_req_fail_cb(void *closure, const char *status, const char *info) +static void api_ws_server_req_fail_cb(struct afb_xreq *xreq, const char *status, const char *info) { int rc; struct writebuf wb = { .count = 0 }; - struct api_ws_server_req *wreq = closure; + struct api_ws_server_req *wreq = CONTAINER_OF_XREQ(struct api_ws_server_req, xreq); if (api_ws_write_char(&wb, 'F') && api_ws_write_uint32(&wb, wreq->msgid) @@ -1120,11 +1118,11 @@ static void api_ws_server_req_fail_cb(void *closure, const char *status, const c ERROR("error while sending fail"); } -static int api_ws_server_req_subscribe_cb(void *closure, struct afb_event event) +static int api_ws_server_req_subscribe_cb(struct afb_xreq *xreq, struct afb_event event) { int rc, rc2; struct writebuf wb = { .count = 0 }; - struct api_ws_server_req *wreq = closure; + struct api_ws_server_req *wreq = CONTAINER_OF_XREQ(struct api_ws_server_req, xreq); rc = afb_evt_add_watch(wreq->client->listener, event); if (rc < 0) @@ -1143,11 +1141,11 @@ success: return rc; } -static int api_ws_server_req_unsubscribe_cb(void *closure, struct afb_event event) +static int api_ws_server_req_unsubscribe_cb(struct afb_xreq *xreq, struct afb_event event) { int rc, rc2; struct writebuf wb = { .count = 0 }; - struct api_ws_server_req *wreq = closure; + struct api_ws_server_req *wreq = CONTAINER_OF_XREQ(struct api_ws_server_req, xreq); if (api_ws_write_char(&wb, 'U') && api_ws_write_uint32(&wb, wreq->msgid) diff --git a/src/afb-hreq.c b/src/afb-hreq.c index 69403f65..6589f0f4 100644 --- a/src/afb-hreq.c +++ b/src/afb-hreq.c @@ -72,19 +72,18 @@ struct hreq_data { char *path; /* path of the file saved */ }; -static struct json_object *req_json(struct afb_hreq *hreq); -static struct afb_arg req_get(struct afb_hreq *hreq, const char *name); -static void req_fail(struct afb_hreq *hreq, const char *status, const char *info); -static void req_success(struct afb_hreq *hreq, json_object *obj, const char *info); - -static void afb_hreq_destroy(struct afb_hreq *hreq); +static struct json_object *req_json(struct afb_xreq *xreq); +static struct afb_arg req_get(struct afb_xreq *xreq, const char *name); +static void req_fail(struct afb_xreq *xreq, const char *status, const char *info); +static void req_success(struct afb_xreq *xreq, json_object *obj, const char *info); +static void req_destroy(struct afb_xreq *xreq); const struct afb_xreq_query_itf afb_hreq_xreq_query_itf = { - .json = (void*)req_json, - .get = (void*)req_get, - .success = (void*)req_success, - .fail = (void*)req_fail, - .unref = (void*)afb_hreq_destroy + .json = req_json, + .get = req_get, + .success = req_success, + .fail = req_fail, + .unref = req_destroy }; static struct hreq_data *get_data(struct afb_hreq *hreq, const char *key, int create) @@ -299,8 +298,9 @@ static const char *mimetype_fd_name(int fd, const char *filename) return result; } -static void afb_hreq_destroy(struct afb_hreq *hreq) +static void req_destroy(struct afb_xreq *xreq) { + struct afb_hreq *hreq = CONTAINER_OF_XREQ(struct afb_hreq, xreq); struct hreq_data *data; if (hreq->postform != NULL) @@ -820,9 +820,10 @@ int afb_hreq_post_add_file(struct afb_hreq *hreq, const char *key, const char *f return !size; } -static struct afb_arg req_get(struct afb_hreq *hreq, const char *name) +static struct afb_arg req_get(struct afb_xreq *xreq, const char *name) { const char *value; + struct afb_hreq *hreq = CONTAINER_OF_XREQ(struct afb_hreq, xreq); struct hreq_data *hdat = get_data(hreq, name, 0); if (hdat) return (struct afb_arg){ @@ -845,10 +846,11 @@ static int _iterargs_(struct json_object *obj, enum MHD_ValueKind kind, const ch return 1; } -static struct json_object *req_json(struct afb_hreq *hreq) +static struct json_object *req_json(struct afb_xreq *xreq) { struct hreq_data *hdat; struct json_object *obj, *val; + struct afb_hreq *hreq = CONTAINER_OF_XREQ(struct afb_hreq, xreq); obj = hreq->json; if (obj == NULL) { @@ -896,13 +898,15 @@ static void req_reply(struct afb_hreq *hreq, unsigned retcode, const char *statu afb_hreq_reply(hreq, retcode, response, NULL); } -static void req_fail(struct afb_hreq *hreq, const char *status, const char *info) +static void req_fail(struct afb_xreq *xreq, const char *status, const char *info) { + struct afb_hreq *hreq = CONTAINER_OF_XREQ(struct afb_hreq, xreq); req_reply(hreq, MHD_HTTP_OK, status, info, NULL); } -static void req_success(struct afb_hreq *hreq, json_object *obj, const char *info) +static void req_success(struct afb_xreq *xreq, json_object *obj, const char *info) { + struct afb_hreq *hreq = CONTAINER_OF_XREQ(struct afb_hreq, xreq); req_reply(hreq, MHD_HTTP_OK, "success", info, obj); } @@ -973,9 +977,7 @@ struct afb_hreq *afb_hreq_create() struct afb_hreq *hreq = calloc(1, sizeof *hreq); if (hreq) { /* init the request */ - hreq->xreq.refcount = 1; - hreq->xreq.query = hreq; - hreq->xreq.queryitf = &afb_hreq_xreq_query_itf; + afb_xreq_init(&hreq->xreq, &afb_hreq_xreq_query_itf); hreq->reqid = ++global_reqids; } return hreq; diff --git a/src/afb-subcall.c b/src/afb-subcall.c index 7026f20e..498f73b5 100644 --- a/src/afb-subcall.c +++ b/src/afb-subcall.c @@ -33,10 +33,10 @@ struct subcall; -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_destroy(struct afb_xreq *xreq); +static void subcall_reply(struct afb_xreq *xreq, int iserror, struct json_object *obj); +static int subcall_subscribe(struct afb_xreq *xreq, struct afb_event event); +static int subcall_unsubscribe(struct afb_xreq *xreq, struct afb_event event); const struct afb_xreq_query_itf afb_subcall_xreq_itf = { .reply = subcall_reply, @@ -53,33 +53,33 @@ struct subcall void *closure; }; -static void subcall_destroy(void *closure) +static void subcall_destroy(struct afb_xreq *xreq) { - struct subcall *subcall = closure; + struct subcall *subcall = CONTAINER_OF_XREQ(struct subcall, xreq); json_object_put(subcall->xreq.json); afb_xreq_unref(subcall->caller); free(subcall); } -static void subcall_reply(void *closure, int iserror, struct json_object *obj) +static void subcall_reply(struct afb_xreq *xreq, int iserror, struct json_object *obj) { - struct subcall *subcall = closure; + struct subcall *subcall = CONTAINER_OF_XREQ(struct subcall, xreq); subcall->callback(subcall->closure, iserror, obj); json_object_put(obj); } -static int subcall_subscribe(void *closure, struct afb_event event) +static int subcall_subscribe(struct afb_xreq *xreq, struct afb_event event) { - struct subcall *subcall = closure; + struct subcall *subcall = CONTAINER_OF_XREQ(struct subcall, xreq); return afb_xreq_subscribe(subcall->caller, event); } -static int subcall_unsubscribe(void *closure, struct afb_event event) +static int subcall_unsubscribe(struct afb_xreq *xreq, struct afb_event event) { - struct subcall *subcall = closure; + struct subcall *subcall = CONTAINER_OF_XREQ(struct subcall, xreq); return afb_xreq_unsubscribe(subcall->caller, event); } @@ -93,13 +93,11 @@ static struct subcall *create_subcall(struct afb_xreq *caller, const char *api, return NULL; } + afb_xreq_init(&subcall->xreq, &afb_subcall_xreq_itf); afb_context_subinit(&subcall->xreq.context, &caller->context); - subcall->xreq.refcount = 1; subcall->xreq.json = args; subcall->xreq.api = api; /* TODO: alloc ? */ subcall->xreq.verb = verb; /* TODO: alloc ? */ - subcall->xreq.query = subcall; - subcall->xreq.queryitf = &afb_subcall_xreq_itf; subcall->caller = caller; subcall->callback = callback; subcall->closure = closure; diff --git a/src/afb-svc.c b/src/afb-svc.c index 59e775cd..d4932802 100644 --- a/src/afb-svc.c +++ b/src/afb-svc.c @@ -56,12 +56,8 @@ struct svc_req struct afb_xreq xreq; /* the args */ - struct json_object *args; void (*callback)(void*, int, struct json_object*); void *closure; - - /* the service */ - struct afb_svc *svc; }; /* functions for services */ @@ -81,14 +77,12 @@ static const struct afb_evt_itf evt_itf = { }; /* functions for requests of services */ -static struct json_object *svcreq_json(void *closure); -static void svcreq_destroy(void *closure); -static void svcreq_reply(void *closure, int iserror, json_object *obj); +static void svcreq_destroy(struct afb_xreq *xreq); +static void svcreq_reply(struct afb_xreq *xreq, int iserror, json_object *obj); /* interface for requests of services */ const struct afb_xreq_query_itf afb_svc_xreq_itf = { .unref = svcreq_destroy, - .json = svcreq_json, .reply = svcreq_reply }; @@ -233,41 +227,32 @@ static void svc_call(void *closure, const char *api, const char *verb, struct js } /* initialises the request */ + afb_xreq_init(&svcreq->xreq, &afb_svc_xreq_itf); afb_context_init(&svcreq->xreq.context, svc->session, NULL); svcreq->xreq.context.validated = 1; - svcreq->xreq.refcount = 1; - svcreq->xreq.query = svcreq; - svcreq->xreq.queryitf = &afb_svc_xreq_itf; svcreq->xreq.api = api; svcreq->xreq.verb = verb; svcreq->xreq.listener = svc->listener; - svcreq->args = args; + svcreq->xreq.json = args; svcreq->callback = callback; svcreq->closure = cbclosure; - svcreq->svc = svc; /* terminates and frees ressources if needed */ afb_apis_call(&svcreq->xreq); afb_xreq_unref(&svcreq->xreq); } -static void svcreq_destroy(void *closure) +static void svcreq_destroy(struct afb_xreq *xreq) { - struct svc_req *svcreq = closure; + struct svc_req *svcreq = CONTAINER_OF_XREQ(struct svc_req, xreq); afb_context_disconnect(&svcreq->xreq.context); - json_object_put(svcreq->args); + json_object_put(svcreq->xreq.json); free(svcreq); } -static struct json_object *svcreq_json(void *closure) -{ - struct svc_req *svcreq = closure; - return svcreq->args; -} - -static void svcreq_reply(void *closure, int iserror, json_object *obj) +static void svcreq_reply(struct afb_xreq *xreq, int iserror, json_object *obj) { - struct svc_req *svcreq = closure; + struct svc_req *svcreq = CONTAINER_OF_XREQ(struct svc_req, xreq); svcreq->callback(svcreq->closure, iserror, obj); json_object_put(obj); } diff --git a/src/afb-ws-json1.c b/src/afb-ws-json1.c index fec41173..60a0a801 100644 --- a/src/afb-ws-json1.c +++ b/src/afb-ws-json1.c @@ -50,9 +50,8 @@ static void aws_on_call(struct afb_ws_json1 *ws, const char *api, const char *ve static void aws_on_event(struct afb_ws_json1 *ws, const char *event, int eventid, struct json_object *object); /* predeclaration of wsreq callbacks */ -static void wsreq_destroy(struct afb_wsreq *wsreq); -static struct json_object *wsreq_json(struct afb_wsreq *wsreq); -static void wsreq_reply(struct afb_wsreq *wsreq, int iserror, json_object *obj); +static void wsreq_destroy(struct afb_xreq *xreq); +static void wsreq_reply(struct afb_xreq *xreq, int iserror, json_object *obj); /* declaration of websocket structure */ struct afb_ws_json1 @@ -84,9 +83,8 @@ static struct afb_wsj1_itf wsj1_itf = { /* interface for xreq */ const struct afb_xreq_query_itf afb_ws_json1_xreq_itf = { - .json = (void*)wsreq_json, - .reply = (void*)wsreq_reply, - .unref = (void*)wsreq_destroy + .reply = wsreq_reply, + .unref = wsreq_destroy }; /* the interface for events */ @@ -182,6 +180,7 @@ static void aws_on_call(struct afb_ws_json1 *ws, const char *api, const char *ve } /* init the context */ + afb_xreq_init(&wsreq->xreq, &afb_ws_json1_xreq_itf); afb_context_init(&wsreq->xreq.context, ws->session, afb_wsj1_msg_token(msg)); if (!wsreq->xreq.context.invalidated) wsreq->xreq.context.validated = 1; @@ -193,11 +192,9 @@ static void aws_on_call(struct afb_ws_json1 *ws, const char *api, const char *ve /* fill and record the request */ afb_wsj1_msg_addref(msg); wsreq->msgj1 = msg; - wsreq->xreq.refcount = 1; - wsreq->xreq.query = wsreq; - wsreq->xreq.queryitf = &afb_ws_json1_xreq_itf; wsreq->xreq.api = api; wsreq->xreq.verb = verb; + wsreq->xreq.json = afb_wsj1_msg_object_j(wsreq->msgj1); wsreq->aws = aws_addref(ws); wsreq->xreq.listener = wsreq->aws->listener; @@ -219,21 +216,19 @@ static void aws_on_event(struct afb_ws_json1 *aws, const char *event, int eventi **************************************************************** ***************************************************************/ -static void wsreq_destroy(struct afb_wsreq *wsreq) +static void wsreq_destroy(struct afb_xreq *xreq) { + struct afb_wsreq *wsreq = CONTAINER_OF_XREQ(struct afb_wsreq, xreq); + afb_context_disconnect(&wsreq->xreq.context); afb_wsj1_msg_unref(wsreq->msgj1); aws_unref(wsreq->aws); free(wsreq); } -static struct json_object *wsreq_json(struct afb_wsreq *wsreq) -{ - return afb_wsj1_msg_object_j(wsreq->msgj1); -} - -static void wsreq_reply(struct afb_wsreq *wsreq, int iserror, json_object *obj) +static void wsreq_reply(struct afb_xreq *xreq, int iserror, json_object *obj) { + struct afb_wsreq *wsreq = CONTAINER_OF_XREQ(struct afb_wsreq, xreq); int rc; rc = (iserror ? afb_wsj1_reply_error_j : afb_wsj1_reply_ok_j)( diff --git a/src/afb-xreq.c b/src/afb-xreq.c index cf982220..4282f624 100644 --- a/src/afb-xreq.c +++ b/src/afb-xreq.c @@ -37,14 +37,14 @@ static struct json_object *xreq_json_cb(void *closure) { struct afb_xreq *xreq = closure; - return xreq->json ? : (xreq->json = xreq->queryitf->json(xreq->query)); + return xreq->json ? : (xreq->json = xreq->queryitf->json(xreq)); } static struct afb_arg xreq_get_cb(void *closure, const char *name) { struct afb_xreq *xreq = closure; if (xreq->queryitf->get) - return xreq->queryitf->get(xreq->query, name); + return xreq->queryitf->get(xreq, name); else return afb_msg_json_get_arg(xreq_json_cb(closure), name); } @@ -59,9 +59,9 @@ static void xreq_success_cb(void *closure, struct json_object *obj, const char * } else { xreq->replied = 1; if (xreq->queryitf->success) - xreq->queryitf->success(xreq->query, obj, info); + xreq->queryitf->success(xreq, obj, info); else - xreq->queryitf->reply(xreq->query, 0, afb_msg_json_reply_ok(info, obj, &xreq->context, NULL)); + xreq->queryitf->reply(xreq, 0, afb_msg_json_reply_ok(info, obj, &xreq->context, NULL)); } } @@ -74,9 +74,9 @@ static void xreq_fail_cb(void *closure, const char *status, const char *info) } else { xreq->replied = 1; if (xreq->queryitf->fail) - xreq->queryitf->fail(xreq->query, status, info); + xreq->queryitf->fail(xreq, status, info); else - xreq->queryitf->reply(xreq->query, 1, afb_msg_json_reply_error(status, info, &xreq->context, NULL)); + xreq->queryitf->reply(xreq, 1, afb_msg_json_reply_error(status, info, &xreq->context, NULL)); } } @@ -120,7 +120,7 @@ static void xreq_unref_cb(void *closure) { struct afb_xreq *xreq = closure; if (!__atomic_sub_fetch(&xreq->refcount, 1, __ATOMIC_RELAXED)) { - xreq->queryitf->unref(xreq->query); + xreq->queryitf->unref(xreq); } } @@ -147,7 +147,7 @@ int afb_xreq_subscribe(struct afb_xreq *xreq, struct afb_event event) if (xreq->listener) return afb_evt_add_watch(xreq->listener, event); if (xreq->queryitf->subscribe) - return xreq->queryitf->subscribe(xreq->query, event); + return xreq->queryitf->subscribe(xreq, event); ERROR("no event listener, subscription impossible"); errno = EINVAL; return -1; @@ -164,7 +164,7 @@ int afb_xreq_unsubscribe(struct afb_xreq *xreq, struct afb_event event) if (xreq->listener) return afb_evt_remove_watch(xreq->listener, event); if (xreq->queryitf->unsubscribe) - return xreq->queryitf->unsubscribe(xreq->query, event); + return xreq->queryitf->unsubscribe(xreq, event); ERROR("no event listener, unsubscription impossible"); errno = EINVAL; return -1; @@ -175,7 +175,7 @@ static void xreq_subcall_cb(void *closure, const char *api, const char *verb, st struct afb_xreq *xreq = closure; if (xreq->queryitf->subcall) - xreq->queryitf->subcall(xreq->query, api, verb, args, callback, cb_closure); + xreq->queryitf->subcall(xreq, api, verb, args, callback, cb_closure); else afb_subcall(xreq, api, verb, args, callback, cb_closure); } @@ -256,7 +256,7 @@ static void xreq_hooked_unref_cb(void *closure) afb_hook_xreq_unref(xreq); if (!__atomic_sub_fetch(&xreq->refcount, 1, __ATOMIC_RELAXED)) { afb_hook_xreq_end(xreq); - xreq->queryitf->unref(xreq->query); + xreq->queryitf->unref(xreq); } } @@ -489,4 +489,9 @@ void afb_xreq_begin(struct afb_xreq *xreq) afb_hook_xreq_begin(xreq); } +void afb_xreq_init(struct afb_xreq *xreq, const struct afb_xreq_query_itf *queryitf) +{ + xreq->refcount = 1; + xreq->queryitf = queryitf; +} diff --git a/src/afb-xreq.h b/src/afb-xreq.h index ba99d4af..4cd58209 100644 --- a/src/afb-xreq.h +++ b/src/afb-xreq.h @@ -25,20 +25,20 @@ struct json_object; struct afb_evt_listener; +struct afb_xreq; struct afb_xreq_query_itf { - struct json_object *(*json)(void *closure); - struct afb_arg (*get)(void *closure, const char *name); - void (*success)(void *closure, struct json_object *obj, const char *info); - void (*fail)(void *closure, const char *status, const char *info); - void (*reply)(void *closure, int iserror, struct json_object *obj); - void (*unref)(void *closure); - int (*subscribe)(void *closure, struct afb_event event); - int (*unsubscribe)(void *closure, struct afb_event event); - void (*subcall)(void *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cb_closure); + struct json_object *(*json)(struct afb_xreq *xreq); + struct afb_arg (*get)(struct afb_xreq *xreq, const char *name); + void (*success)(struct afb_xreq *xreq, struct json_object *obj, const char *info); + void (*fail)(struct afb_xreq *xreq, const char *status, const char *info); + void (*reply)(struct afb_xreq *xreq, int iserror, struct json_object *obj); + void (*unref)(struct afb_xreq *xreq); + int (*subscribe)(struct afb_xreq *xreq, struct afb_event event); + int (*unsubscribe)(struct afb_xreq *xreq, struct afb_event event); + void (*subcall)(struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cb_closure); }; - /** * Internal data for requests */ @@ -48,7 +48,6 @@ struct afb_xreq const char *api; /**< the requested API */ const char *verb; /**< the requested VERB */ struct json_object *json; /**< the json object (or NULL) */ - void *query; /**< closure for the query */ const struct afb_xreq_query_itf *queryitf; int refcount; /**< current ref count */ int replied; /**< is replied? */ @@ -57,6 +56,8 @@ struct afb_xreq struct afb_evt_listener *listener; }; +#define CONTAINER_OF_XREQ(type,x) ((type*)(((intptr_t)(x))-((intptr_t)&(((type*)NULL)->xreq)))) + extern void afb_xreq_addref(struct afb_xreq *xreq); extern void afb_xreq_unref(struct afb_xreq *xreq); extern void afb_xreq_success(struct afb_xreq *xreq, struct json_object *obj, const char *info); @@ -69,6 +70,7 @@ extern int afb_xreq_unsubscribe(struct afb_xreq *xreq, struct afb_event event); extern void afb_xreq_subcall(struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cb_closure); extern void afb_xreq_unhooked_subcall(struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cb_closure); +extern void afb_xreq_init(struct afb_xreq *xreq, const struct afb_xreq_query_itf *queryitf); extern void afb_xreq_begin(struct afb_xreq *xreq); extern void afb_xreq_call(struct afb_xreq *xreq, int sessionflags, void (*callback)(struct afb_req req)); diff --git a/src/main.c b/src/main.c index 32b12dd3..4dc6cb81 100644 --- a/src/main.c +++ b/src/main.c @@ -446,9 +446,9 @@ struct startup_req struct afb_session *session; }; -static void startup_call_reply(void *closure, int iserror, struct json_object *obj) +static void startup_call_reply(struct afb_xreq *xreq, int iserror, struct json_object *obj) { - struct startup_req *sreq = closure; + struct startup_req *sreq = CONTAINER_OF_XREQ(struct startup_req, xreq); if (!iserror) NOTICE("startup call %s returned %s", sreq->current->value, json_object_get_string(obj)); @@ -460,9 +460,9 @@ static void startup_call_reply(void *closure, int iserror, struct json_object *o static void startup_call_current(struct startup_req *sreq); -static void startup_call_unref(void *closure) +static void startup_call_unref(struct afb_xreq *xreq) { - struct startup_req *sreq = closure; + struct startup_req *sreq = CONTAINER_OF_XREQ(struct startup_req, xreq); free(sreq->api); free(sreq->verb); @@ -493,16 +493,14 @@ static void startup_call_current(struct startup_req *sreq) json = strchr(verb, ':'); if (json) { memset(&sreq->xreq, 0, sizeof sreq->xreq); + afb_xreq_init(&sreq->xreq, &startup_xreq_itf); afb_context_init(&sreq->xreq.context, sreq->session, NULL); sreq->xreq.context.validated = 1; sreq->api = strndup(api, verb - api); - sreq->xreq.api = sreq->api; sreq->verb = strndup(verb + 1, json - verb - 1); + sreq->xreq.api = sreq->api; sreq->xreq.verb = sreq->verb; sreq->xreq.json = json_tokener_parse(json + 1); - sreq->xreq.refcount = 1; - sreq->xreq.query = sreq; - sreq->xreq.queryitf = &startup_xreq_itf; if (sreq->api && sreq->verb && sreq->xreq.json) { afb_apis_call(&sreq->xreq); afb_xreq_unref(&sreq->xreq); -- 2.16.6