diff options
author | José Bollo <jose.bollo@iot.bzh> | 2017-06-01 19:23:28 +0200 |
---|---|---|
committer | José Bollo <jose.bollo@iot.bzh> | 2017-06-01 22:13:07 +0200 |
commit | 9b2c70bf87bb3272cb325f3a9ecf69cd0bd53ba8 (patch) | |
tree | 7b9857812d5ecb70ab1f90b46ad98f986ede9f74 | |
parent | ec0a2d0f6b22750931fddfd6511219bcccd3c4f9 (diff) |
Enforce starting services on need
Also remove default api verbs because it wasn't used
actually and it wasn't compatible with this evolution.
Change-Id: I863b99eddd418f771011bb35b4bcea763046224e
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r-- | src/afb-apiset.c | 162 | ||||
-rw-r--r-- | src/afb-apiset.h | 5 | ||||
-rw-r--r-- | src/afb-xreq.c | 7 |
3 files changed, 90 insertions, 84 deletions
diff --git a/src/afb-apiset.c b/src/afb-apiset.c index 63c28fe7..f41c88c0 100644 --- a/src/afb-apiset.c +++ b/src/afb-apiset.c @@ -38,7 +38,9 @@ /** * Internal description of an api */ -struct api_desc { +struct api_desc +{ + int status; const char *name; /**< name of the api */ struct afb_api api; /**< handler of the api */ }; @@ -50,7 +52,6 @@ struct afb_apiset { struct api_desc *apis; /**< description of apis */ struct afb_apiset *subset; /**< subset if any */ - struct afb_api defapi; /**< default api if any */ int count; /**< count of apis in the set */ int timeout; /**< the timeout in second for the apiset */ int refcount; /**< reference count for freeing resources */ @@ -63,10 +64,10 @@ struct afb_apiset * @param name the api name to search * @return the descriptor if found or NULL otherwise */ -static const struct api_desc *search(struct afb_apiset *set, const char *name) +static struct api_desc *search(struct afb_apiset *set, const char *name) { int i, c, up, lo; - const struct api_desc *a; + struct api_desc *a; /* dichotomic search of the api */ /* initial slice */ @@ -137,7 +138,6 @@ struct afb_apiset *afb_apiset_create(const char *name, int timeout) set->timeout = timeout; set->refcount = 1; set->subset = NULL; - set->defapi.itf = NULL; if (name) strcpy(set->name, name); else @@ -204,51 +204,6 @@ void afb_apiset_subset_set(struct afb_apiset *set, struct afb_apiset *subset) } /** - * Check if the apiset has a default api - * @param set the api set - * @return 1 if the set has a default api or 0 otherwise - */ -int afb_apiset_default_api_exist(struct afb_apiset *set) -{ - return !!set->defapi.itf; -} - -/** - * Get the default api of the api set. - * @param set the api set - * @param api where to store the default api - * @return 0 in case of success or -1 when no default api is set - */ -int afb_apiset_default_api_get(struct afb_apiset *set, struct afb_api *api) -{ - if (set->defapi.itf) { - *api = set->defapi; - return 0; - } - errno = ENOENT; - return -1; -} - -/** - * Set the default api of the api set - * @param set the api set - * @param subset the subset to set - */ -void afb_apiset_default_api_set(struct afb_apiset *set, struct afb_api api) -{ - set->defapi = api; -} - -/** - * Set the default api of the api set - * @param set the api set - */ -void afb_apiset_default_api_drop(struct afb_apiset *set) -{ - set->defapi.itf = NULL; -} - -/** * Adds the api of 'name' described by 'api'. * @param set the api set * @param name the name of the api to add (have to survive, not copied!) @@ -291,6 +246,7 @@ int afb_apiset_add(struct afb_apiset *set, const char *name, struct afb_api api) memmove(apis + 1, apis, ((unsigned)(set->count - i)) * sizeof *apis); /* record the plugin */ + apis->status = -1; apis->api = api; apis->name = name; set->count++; @@ -359,26 +315,86 @@ int afb_apiset_lookup(struct afb_apiset *set, const char *name, struct afb_api * * @param api the structure where to store data about the API of name * @return 0 in case of success or -1 in case of error */ +static struct api_desc *get_api(struct afb_apiset *set, const char *name) +{ + struct api_desc *i = search(set, name); + return i || !set->subset ? i : get_api(set->subset, name); +} + +/** + * Get from the 'set' the API of 'name' in 'api' with fallback to subset or default api + * @param set the set of API + * @param name the name of the API to get + * @param api the structure where to store data about the API of name + * @return 0 in case of success or -1 in case of error + */ int afb_apiset_get(struct afb_apiset *set, const char *name, struct afb_api *api) { const struct api_desc *i; - i = search(set, name); - if (i) { - *api = i->api; - return 0; + i = get_api(set, name); + if (!i) { + errno = ENOENT; + return -1; } + *api = i->api; + return 0; +} - if (set->subset && 0 == afb_apiset_get(set->subset, name, api)) +/** + * Starts the service 'api'. + * @param api the api + * @param share_session if true start the servic"e in a shared session + * if false start it in its own session + * @param onneed if true start the service if possible, if false the api + * must be a service + * @return a positive number on success + */ +static int start_api(struct afb_apiset *set, struct api_desc *api, int share_session, int onneed) +{ + if (api->status == 0) return 0; + else if (api->status > 0) { + errno = api->status; + return -1; + } - if (set->defapi.itf) { - *api = set->defapi; - return 0; + if (api->api.itf->service_start) { + api->status = EBUSY; + if (api->api.itf->service_start(api->api.closure, share_session, onneed, set) >= 0) + api->status = 0; + else if (errno) + api->status = errno ?: ECANCELED; + } else { + if (onneed) + api->status = 0; + else { + /* already started: it is an error */ + ERROR("The api %s is not a startable service", api->name); + api->status = EINVAL; + } } + return -!!api->status; +} - errno = ENOENT; - return -1; +/** + * Get from the 'set' the API of 'name' in 'api' with fallback to subset or default api + * @param set the set of API + * @param name the name of the API to get + * @param api the structure where to store data about the API of name + * @return 0 in case of success or -1 in case of error + */ +int afb_apiset_get_started(struct afb_apiset *set, const char *name, struct afb_api *api) +{ + struct api_desc *i; + + i = get_api(set, name); + if (!i) { + errno = ENOENT; + return -1; + } + *api = i->api; + return i->status ? start_api(set, i, 1, 1) : 0; } /** @@ -393,7 +409,7 @@ int afb_apiset_get(struct afb_apiset *set, const char *name, struct afb_api *api */ int afb_apiset_start_service(struct afb_apiset *set, const char *name, int share_session, int onneed) { - const struct api_desc *a; + struct api_desc *a; a = search(set, name); if (!a) { @@ -402,16 +418,7 @@ int afb_apiset_start_service(struct afb_apiset *set, const char *name, int share return -1; } - if (a->api.itf->service_start) - return a->api.itf->service_start(a->api.closure, share_session, onneed, set); - - if (onneed) - return 0; - - /* already started: it is an error */ - ERROR("The api %s is not a startable service", name); - errno = EINVAL; - return -1; + return start_api(set, a, share_session, onneed); } /** @@ -424,19 +431,18 @@ int afb_apiset_start_service(struct afb_apiset *set, const char *name, int share int afb_apiset_start_all_services(struct afb_apiset *set, int share_session) { int rc; - const struct api_desc *i, *e; + struct api_desc *i, *e; i = set->apis; e = &set->apis[set->count]; while (i != e) { - if (i->api.itf->service_start) { - rc = i->api.itf->service_start(i->api.closure, share_session, 1, set); - if (rc < 0) - return rc; - } + rc = start_api(set, i, share_session, 1); + if (rc < 0) + return rc; i++; } - return 0; + + return set->subset ? afb_apiset_start_all_services(set->subset, share_session) : 0; } /** diff --git a/src/afb-apiset.h b/src/afb-apiset.h index ff6f6b48..fdc169f5 100644 --- a/src/afb-apiset.h +++ b/src/afb-apiset.h @@ -28,14 +28,11 @@ extern int afb_apiset_timeout_get(struct afb_apiset *set); extern void afb_apiset_timeout_set(struct afb_apiset *set, int to); extern void afb_apiset_subset_set(struct afb_apiset *set, struct afb_apiset *subset); extern struct afb_apiset *afb_apiset_subset_get(struct afb_apiset *set); -extern int afb_apiset_default_api_exist(struct afb_apiset *set); -extern int afb_apiset_default_api_get(struct afb_apiset *set, struct afb_api *api); -extern void afb_apiset_default_api_set(struct afb_apiset *set, struct afb_api api); -extern void afb_apiset_default_api_drop(struct afb_apiset *set); extern int afb_apiset_add(struct afb_apiset *set, const char *name, struct afb_api api); extern int afb_apiset_del(struct afb_apiset *set, const char *name); extern int afb_apiset_lookup(struct afb_apiset *set, const char *name, struct afb_api *api); extern int afb_apiset_get(struct afb_apiset *set, const char *name, struct afb_api *api); +extern int afb_apiset_get_started(struct afb_apiset *set, const char *name, struct afb_api *api); extern int afb_apiset_start_service(struct afb_apiset *set, const char *name, int share_session, int onneed); extern int afb_apiset_start_all_services(struct afb_apiset *set, int share_session); extern void afb_apiset_update_hooks(struct afb_apiset *set, const char *name); diff --git a/src/afb-xreq.c b/src/afb-xreq.c index ba533c90..e8a42226 100644 --- a/src/afb-xreq.c +++ b/src/afb-xreq.c @@ -664,8 +664,11 @@ static void process_sync(struct afb_xreq *xreq) afb_hook_xreq_begin(xreq); /* search the api */ - if (afb_apiset_get(xreq->apiset, xreq->api, &api) < 0) { - afb_xreq_fail_f(xreq, "unknown-api", "api %s not found", xreq->api); + if (afb_apiset_get_started(xreq->apiset, xreq->api, &api) < 0) { + if (errno == ENOENT) + afb_xreq_fail_f(xreq, "unknown-api", "api %s not found", xreq->api); + else + afb_xreq_fail_f(xreq, "bad-api-state", "api %s not started correctly: %m", xreq->api); } else { xreq->context.api_key = api.closure; api.itf->call(api.closure, xreq); |