/*
- * Copyright (C) 2016, 2017, 2018 "IoT.bzh"
+ * Copyright (C) 2016-2019 "IoT.bzh"
* Author José Bollo <jose.bollo@iot.bzh>
*
* Licensed under the Apache License, Version 2.0 (the "License");
{
struct api_alias *next;
struct api_desc *api;
- char name[1];
+ char name[];
};
/**
{
struct api_class *next;
struct api_array providers;
- char name[1];
+ char name[];
};
/**
struct api_depend
{
struct afb_apiset *set;
- char name[1];
+ char name[];
};
/**
} 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 */
};
/**
if (!create)
return NULL;
- c = calloc(1, strlen(name) + sizeof *c);
+ c = calloc(1, strlen(name) + 1 + sizeof *c);
if (!c)
errno = ENOMEM;
else {
{
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;
* 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*))
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;
}
/* 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;
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);
+ rc2 = start_api(array->apis[--i]);
if (rc2 < 0) {
rc = rc2;
}
/**
* 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;
}
/**
* 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;
if (!api)
rc = -1;
else {
- rc2 = start_api(api, share_session, 1);
+ rc2 = start_api(api);
if (rc2 < 0) {
rc = rc2;
}
/**
* 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 api_desc *api, int share_session, int onneed)
+static int start_api(struct api_desc *api)
{
int rc;
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;
}
i = lookup(set, name, rec);
if (i)
- return i->status && start_api(i, 1, 1) ? NULL : &i->api;
+ return i->status && start_api(i) ? NULL : &i->api;
errno = ENOENT;
return NULL;
}
* 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
*/
-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;
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)
{
int rc, ret;
int i;
while (set) {
i = 0;
while (i < set->apis.count) {
- rc = start_api(set->apis.apis[i], share_session, 1);
+ rc = start_api(set->apis.apis[i]);
if (rc < 0)
ret = rc;
i++;
return ret;
}
+#if WITH_AFB_HOOK
/**
* Ask to update the hook flags of the 'api'
* @param set the api set
d->api.itf->update_hooks(d->api.closure);
}
}
+#endif
/**
* Set the logmask of the 'api' to 'mask'
if (!a)
errno = ENOENT;
else {
- d = malloc(strlen(required) + sizeof *d);
+ d = malloc(strlen(required) + 1 + sizeof *d);
if (!d)
errno = ENOMEM;
else {
/**
* 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);
}