X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafb-apiset.c;h=dba8a6c927543b89ac40a70ca0bc800303ae2061;hb=f3d1f19ae308cc0559728c0ccf6281cbce5ee37c;hp=0eb64a5af21848bdb927bfcc55d97e4627c8ff4f;hpb=ee022f72194200537dd32f0bdc9b741806dc4f43;p=src%2Fapp-framework-binder.git diff --git a/src/afb-apiset.c b/src/afb-apiset.c index 0eb64a5a..dba8a6c9 100644 --- a/src/afb-apiset.c +++ b/src/afb-apiset.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016, 2017, 2018 "IoT.bzh" + * Copyright (C) 2016-2019 "IoT.bzh" * Author José Bollo * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,15 +21,17 @@ #include #include #include +#include -#include "afb-session.h" #include "verbose.h" #include "afb-api.h" #include "afb-apiset.h" #include "afb-context.h" #include "afb-xreq.h" +#include "jobs.h" -#define INCR 8 /* CAUTION: must be a power of 2 */ +#define INCR 8 /* CAUTION: must be a power of 2 */ +#define NOT_STARTED -1 struct afb_apiset; struct api_desc; @@ -58,7 +60,10 @@ struct api_desc { struct api_desc *next; const char *name; /**< name of the api */ - int status; /**< initialisation status */ + int status; /**< initialisation status: + - NOT_STARTED not started, + - 0 started without error, + - greater than 0, error number of start */ struct afb_api_item api; /**< handler of the api */ struct { struct api_array classes; @@ -73,7 +78,7 @@ struct api_alias { struct api_alias *next; struct api_desc *api; - char name[1]; + char name[]; }; /** @@ -83,7 +88,7 @@ struct api_class { struct api_class *next; struct api_array providers; - char name[1]; + char name[]; }; /** @@ -92,7 +97,7 @@ struct api_class struct api_depend { struct afb_apiset *set; - char name[1]; + char name[]; }; /** @@ -110,7 +115,7 @@ struct afb_apiset } onlack; /** not found handler */ int timeout; /**< the timeout in second for the apiset */ int refcount; /**< reference count for freeing resources */ - char name[1]; /**< name of the apiset */ + char name[]; /**< name of the apiset */ }; /** @@ -215,7 +220,7 @@ static struct api_class *class_search(const char *name, int create) if (!create) return NULL; - c = calloc(1, strlen(name) + sizeof *c); + c = calloc(1, strlen(name) + 1 + sizeof *c); if (!c) errno = ENOMEM; else { @@ -341,7 +346,7 @@ struct afb_apiset *afb_apiset_create(const char *name, int timeout) { struct afb_apiset *set; - set = calloc(1, (name ? strlen(name) : 0) + sizeof *set); + set = calloc(1, (name ? strlen(name) : 0) + 1 + sizeof *set); if (set) { set->timeout = timeout; set->refcount = 1; @@ -427,17 +432,23 @@ struct afb_apiset *afb_apiset_subset_get(struct afb_apiset *set) * Set the subset of the set * @param set the api set * @param subset the subset to set + * + * @return 0 in case of success or -1 if it had created a loop */ -void afb_apiset_subset_set(struct afb_apiset *set, struct afb_apiset *subset) +int afb_apiset_subset_set(struct afb_apiset *set, struct afb_apiset *subset) { struct afb_apiset *tmp; - if (subset == set) { - /* avoid infinite loop */ - subset = NULL; - } + + /* avoid infinite loop */ + for (tmp = subset ; tmp ; tmp = tmp->subset) + if (tmp == set) + return -1; + tmp = set->subset; set->subset = afb_apiset_addref(subset); afb_apiset_unref(tmp); + + return 0; } void afb_apiset_onlack_set(struct afb_apiset *set, int (*callback)(void*, struct afb_apiset*, const char*), void *closure, void (*cleanup)(void*)) @@ -483,7 +494,7 @@ int afb_apiset_add(struct afb_apiset *set, const char *name, struct afb_api_item if (!desc) goto oom; - desc->status = -1; + desc->status = NOT_STARTED; desc->api = api; desc->name = name; @@ -495,7 +506,8 @@ int afb_apiset_add(struct afb_apiset *set, const char *name, struct afb_api_item desc->next = all_apis; all_apis = desc; - INFO("API %s added", name); + if (afb_api_is_public(name)) + INFO("API %s added", name); return 0; @@ -538,7 +550,7 @@ int afb_apiset_add_alias(struct afb_apiset *set, const char *name, const char *a } /* allocates and init the struct */ - ali = malloc(sizeof *ali + strlen(alias)); + ali = malloc(sizeof *ali + strlen(alias) + 1); if (ali == NULL) { ERROR("out of memory"); errno = ENOMEM; @@ -693,21 +705,27 @@ const struct afb_api_item *afb_apiset_lookup(struct afb_apiset *set, const char return NULL; } -static int start_api(struct api_desc *api, int share_session, int onneed); +static int start_api(struct api_desc *api); /** * Start the apis of the 'array' - * The attribute 'share_session' is sent to the start function. */ -static int start_array_apis(struct api_array *array, int share_session) +static int start_array_apis(struct api_array *array) { int i, rc = 0, rc2; - i = array->count; - while (i) { - rc2 = start_api(array->apis[--i], share_session, 1); - if (rc2 < 0) { - rc = rc2; + i = 0; + while (i < array->count) { + rc2 = array->apis[i]->status; + if (rc2 == NOT_STARTED) { + rc2 = start_api(array->apis[i]); + if (rc2 < 0) + rc = rc2; + i = 0; + } else { + if (rc2) + rc = -1; + i++; } } return rc; @@ -715,24 +733,22 @@ static int start_array_apis(struct api_array *array, int share_session) /** * Start the class 'cla' (start the apis that provide it). - * The attribute 'share_session' is sent to the start function. */ -static int start_class(struct api_class *cla, int share_session) +static int start_class(struct api_class *cla) { - return start_array_apis(&cla->providers, share_session); + return start_array_apis(&cla->providers); } /** * Start the classes of the 'array' - * The attribute 'share_session' is sent to the start function. */ -static int start_array_classes(struct api_array *array, int share_session) +static int start_array_classes(struct api_array *array) { int i, rc = 0, rc2; i = array->count; while (i) { - rc2 = start_class(array->classes[--i], share_session); + rc2 = start_class(array->classes[--i]); if (rc2 < 0) { rc = rc2; } @@ -742,67 +758,73 @@ static int start_array_classes(struct api_array *array, int share_session) /** * Start the depends of the 'array' - * The attribute 'share_session' is sent to the start function. */ -static int start_array_depends(struct api_array *array, int share_session) +static int start_array_depends(struct api_array *array) { struct api_desc *api; int i, rc = 0, rc2; - i = array->count; - while (i) { - i--; + i = 0; + while (i < array->count) { api = searchrec(array->depends[i]->set, array->depends[i]->name); - if (!api) + if (!api) { rc = -1; - else { - rc2 = start_api(api, share_session, 1); - if (rc2 < 0) { - rc = rc2; + i++; + } else { + rc2 = api->status; + if (rc2 == NOT_STARTED) { + rc2 = start_api(api); + if (rc2 < 0) + rc = rc2; + i = 0; + } else { + if (rc2) + rc = -1; + i++; } } } + return rc; } /** * 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 + * @return zero on success, -1 on error */ -static int start_api(struct api_desc *api, int share_session, int onneed) +static int start_api(struct api_desc *api) { int rc; - if (api->status == 0) + if (api->status != NOT_STARTED) { + if (api->status > 0) { + errno = api->status; + return -1; + } return 0; - else if (api->status > 0) { - errno = api->status; - return -1; } - INFO("API %s starting...", api->name); - rc = start_array_classes(&api->require.classes, share_session); - rc = start_array_depends(&api->require.apis, share_session); - if (api->api.itf->service_start) { - api->status = EBUSY; - rc = api->api.itf->service_start(api->api.closure, share_session, onneed); - if (rc < 0) { - api->status = errno ?: ECANCELED; - ERROR("The api %s failed to start (%d)", api->name, rc); - return -1; + NOTICE("API %s starting...", api->name); + api->status = EBUSY; + rc = start_array_classes(&api->require.classes); + if (rc < 0) + ERROR("Cannot start classes needed by api %s", api->name); + else { + rc = start_array_depends(&api->require.apis); + if (rc < 0) + ERROR("Cannot start apis needed by api %s", api->name); + else if (api->api.itf->service_start) { + rc = api->api.itf->service_start(api->api.closure); + if (rc < 0) + ERROR("The api %s failed to start", api->name); } - } else if (!onneed) { - /* already started: it is an error */ - ERROR("The api %s is not a startable service", api->name); - api->status = EINVAL; + } + if (rc < 0) { + api->status = errno ?: ECANCELED; return -1; } - NOTICE("API %s started", api->name); + INFO("API %s started", api->name); api->status = 0; return 0; } @@ -812,30 +834,31 @@ static int start_api(struct api_desc *api, int share_session, int onneed) * @param set the set of API * @param name the name of the API to get * @param rec if not zero look also recursively in subsets - * @return 0 in case of success or -1 in case of error + * @return a pointer to the API item in case of success or NULL in case of error */ const struct afb_api_item *afb_apiset_lookup_started(struct afb_apiset *set, const char *name, int rec) { - struct api_desc *i; + struct api_desc *desc; - i = lookup(set, name, rec); - if (i) - return i->status && start_api(i, 1, 1) ? NULL : &i->api; - errno = ENOENT; - return NULL; + desc = lookup(set, name, rec); + if (!desc) { + errno = ENOENT; + return NULL; + } + if (start_api(desc)) { + errno = desc->status; + return NULL; + } + return &desc->api; } /** * Starts a service by its 'api' name. * @param set the api set * @param name name of the service to start - * @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 + * @return zero on success, -1 on error */ -int afb_apiset_start_service(struct afb_apiset *set, const char *name, int share_session, int onneed) +int afb_apiset_start_service(struct afb_apiset *set, const char *name) { struct api_desc *a; @@ -846,35 +869,44 @@ int afb_apiset_start_service(struct afb_apiset *set, const char *name, int share return -1; } - return start_api(a, share_session, onneed); + return start_api(a); } /** * Starts all possible services but stops at first error. * @param set the api set - * @param share_session if true start the servic"e in a shared session - * if false start it in its own session * @return 0 on success or a negative number when an error is found */ -int afb_apiset_start_all_services(struct afb_apiset *set, int share_session) +int afb_apiset_start_all_services(struct afb_apiset *set) { + struct afb_apiset *rootset; int rc, ret; int i; + rootset = set; ret = 0; while (set) { i = 0; while (i < set->apis.count) { - rc = start_api(set->apis.apis[i], share_session, 1); - if (rc < 0) - ret = rc; - i++; + rc = set->apis.apis[i]->status; + if (rc == NOT_STARTED) { + rc = start_api(set->apis.apis[i]); + if (rc < 0) + ret = rc; + set = rootset; + i = 0; + } else { + if (rc) + ret = -1; + i++; + } } set = set->subset; } return ret; } +#if WITH_AFB_HOOK /** * Ask to update the hook flags of the 'api' * @param set the api set @@ -898,6 +930,7 @@ void afb_apiset_update_hooks(struct afb_apiset *set, const char *name) d->api.itf->update_hooks(d->api.closure); } } +#endif /** * Set the logmask of the 'api' to 'mask' @@ -944,20 +977,25 @@ int afb_apiset_get_logmask(struct afb_apiset *set, const char *name) return i->api.itf->get_logmask(i->api.closure); } -/** - * Get the description of the API of 'name' - * @param set the api set - * @param name the api whose description is required - * @return the description or NULL - */ -struct json_object *afb_apiset_describe(struct afb_apiset *set, const char *name) +void afb_apiset_describe(struct afb_apiset *set, const char *name, void (*describecb)(void *, struct json_object *), void *closure) { const struct api_desc *i; - - i = name ? searchrec(set, name) : NULL; - return i && i->api.itf->describe ? i->api.itf->describe(i->api.closure) : NULL; + struct json_object *r; + + r = NULL; + if (name) { + i = searchrec(set, name); + if (i) { + if (i->api.itf->describe) { + i->api.itf->describe(i->api.closure, describecb, closure); + return; + } + } + } + describecb(closure, r); } + struct get_names { union { struct { @@ -1082,7 +1120,7 @@ int afb_apiset_require(struct afb_apiset *set, const char *name, const char *req if (!a) errno = ENOENT; else { - d = malloc(strlen(required) + sizeof *d); + d = malloc(strlen(required) + 1 + sizeof *d); if (!d) errno = ENOMEM; else { @@ -1120,11 +1158,10 @@ int afb_apiset_provide_class(struct afb_apiset *set, const char *apiname, const /** * Start any API that provides the class of name 'classname' - * The attribute 'share_session' is sent to the start function. */ -int afb_apiset_class_start(const char *classname, int share_session) +int afb_apiset_class_start(const char *classname) { struct api_class *cla = class_search(classname, 0); - return cla ? start_class(cla, share_session) : (errno = ENOENT, -1); + return cla ? start_class(cla) : (errno = ENOENT, -1); }