http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/dependency_manager/src/dm_component_impl.c ---------------------------------------------------------------------- diff --cc dependency_manager/src/dm_component_impl.c index 13a2ee0,0000000..e0d9f52 mode 100644,000000..100644 --- a/dependency_manager/src/dm_component_impl.c +++ b/dependency_manager/src/dm_component_impl.c @@@ -1,1442 -1,0 +1,1451 @@@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * dm_component_impl.c + * + * \date 9 Oct 2014 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> + +#include "constants.h" +#include "filter.h" +#include "dm_component_impl.h" + + +typedef struct dm_executor_struct * dm_executor_pt; + +struct dm_component_struct { + char id[DM_COMPONENT_MAX_ID_LENGTH]; + char name[DM_COMPONENT_MAX_NAME_LENGTH]; + bundle_context_pt context; - array_list_pt dm_interfaces; ++ array_list_pt dm_interfaces; //protected by mutex + + void* implementation; + + init_fpt callbackInit; + start_fpt callbackStart; + stop_fpt callbackStop; + deinit_fpt callbackDeinit; + + array_list_pt dependencies; //protected by mutex + pthread_mutex_t mutex; + + dm_component_state_t state; + bool isStarted; + bool active; + + bool setCLanguageProperty; + + hash_map_pt dependencyEvents; //protected by mutex + + dm_executor_pt executor; +}; + +typedef struct dm_interface_struct { + char* serviceName; + const void* service; + properties_pt properties; + service_registration_pt registration; +} dm_interface_t; + +struct dm_executor_struct { + pthread_t runningThread; + bool runningThreadSet; + linked_list_pt workQueue; + pthread_mutex_t mutex; +}; + +typedef struct dm_executor_task_struct { + dm_component_pt component; + void (*command)(void *command_ptr, void *data); + void *data; +} dm_executor_task_t; + +typedef struct dm_handle_event_type_struct { + dm_service_dependency_pt dependency; + dm_event_pt event; + dm_event_pt newEvent; +} *dm_handle_event_type_pt; + +static celix_status_t executor_runTasks(dm_executor_pt executor, pthread_t currentThread __attribute__((unused))); +static celix_status_t executor_execute(dm_executor_pt executor); +static celix_status_t executor_executeTask(dm_executor_pt executor, dm_component_pt component, void (*command), void *data); +static celix_status_t executor_schedule(dm_executor_pt executor, dm_component_pt component, void (*command), void *data); +static celix_status_t executor_create(dm_component_pt component __attribute__((unused)), dm_executor_pt *executor); +static void executor_destroy(dm_executor_pt executor); + +static celix_status_t component_invokeRemoveRequiredDependencies(dm_component_pt component); +static celix_status_t component_invokeRemoveInstanceBoundDependencies(dm_component_pt component); +static celix_status_t component_invokeRemoveOptionalDependencies(dm_component_pt component); +static celix_status_t component_registerServices(dm_component_pt component); +static celix_status_t component_unregisterServices(dm_component_pt component); +static celix_status_t component_invokeAddOptionalDependencies(dm_component_pt component); +static celix_status_t component_invokeAddRequiredInstanceBoundDependencies(dm_component_pt component); +static celix_status_t component_invokeAddRequiredDependencies(dm_component_pt component); +static celix_status_t component_invokeAutoConfigInstanceBoundDependencies(dm_component_pt component); +static celix_status_t component_invokeAutoConfigDependencies(dm_component_pt component); +static celix_status_t component_configureImplementation(dm_component_pt component, dm_service_dependency_pt dependency); +static celix_status_t component_allInstanceBoundAvailable(dm_component_pt component, bool *available); +static celix_status_t component_allRequiredAvailable(dm_component_pt component, bool *available); +static celix_status_t component_performTransition(dm_component_pt component, dm_component_state_t oldState, dm_component_state_t newState, bool *transition); +static celix_status_t component_calculateNewState(dm_component_pt component, dm_component_state_t currentState, dm_component_state_t *newState); +static celix_status_t component_handleChange(dm_component_pt component); +static celix_status_t component_startDependencies(dm_component_pt component __attribute__((unused)), array_list_pt dependencies); +static celix_status_t component_getDependencyEvent(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt *event_pptr); +static celix_status_t component_updateInstance(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event, bool update, bool add); + +static celix_status_t component_addTask(dm_component_pt component, dm_service_dependency_pt dep); +static celix_status_t component_startTask(dm_component_pt component, void * data __attribute__((unused))); +static celix_status_t component_stopTask(dm_component_pt component, void * data __attribute__((unused))); +static celix_status_t component_removeTask(dm_component_pt component, dm_service_dependency_pt dependency); +static celix_status_t component_handleEventTask(dm_component_pt component, dm_handle_event_type_pt data); + +static celix_status_t component_handleAdded(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event); +static celix_status_t component_handleChanged(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event); +static celix_status_t component_handleRemoved(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event); +static celix_status_t component_handleSwapped(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event, dm_event_pt newEvent); + +static celix_status_t component_suspend(dm_component_pt component, dm_service_dependency_pt dependency); +static celix_status_t component_resume(dm_component_pt component, dm_service_dependency_pt dependency); + +celix_status_t component_create(bundle_context_pt context, const char *name, dm_component_pt *out) { + celix_status_t status = CELIX_SUCCESS; + + dm_component_pt component = calloc(1, sizeof(*component)); + + if (!component) { + status = CELIX_ENOMEM; + } else { + snprintf(component->id, DM_COMPONENT_MAX_ID_LENGTH, "%p", component); + snprintf(component->name, DM_COMPONENT_MAX_NAME_LENGTH, "%s", name == NULL ? "n/a" : name); + + component->context = context; + + arrayList_create(&component->dm_interfaces); + arrayList_create(&(component)->dependencies); + pthread_mutex_init(&(component)->mutex, NULL); + + component->implementation = NULL; + + component->callbackInit = NULL; + component->callbackStart = NULL; + component->callbackStop = NULL; + component->callbackDeinit = NULL; + + component->state = DM_CMP_STATE_INACTIVE; + component->isStarted = false; + component->active = false; + + component->setCLanguageProperty = false; + + component->dependencyEvents = hashMap_create(NULL, NULL, NULL, NULL); + + component->executor = NULL; + executor_create(component, &component->executor); + } + + if (status == CELIX_SUCCESS) { + *out = component; + } + + return status; +} + +void component_destroy(dm_component_pt component) { + if (component) { + unsigned int i; + + for (i = 0; i < arrayList_size(component->dm_interfaces); i++) { + dm_interface_t *interface = arrayList_get(component->dm_interfaces, i); + + if(interface->properties!=NULL){ + properties_destroy(interface->properties); + } + free (interface->serviceName); + free (interface); + } + arrayList_destroy(component->dm_interfaces); + + executor_destroy(component->executor); + + hash_map_iterator_pt iter = hashMapIterator_create(component->dependencyEvents); + while(hashMapIterator_hasNext(iter)){ + hash_map_entry_pt entry = hashMapIterator_nextEntry(iter); + dm_service_dependency_pt sdep = (dm_service_dependency_pt)hashMapEntry_getKey(entry); + array_list_pt eventList = (array_list_pt)hashMapEntry_getValue(entry); + serviceDependency_destroy(&sdep); + arrayList_destroy(eventList); + } + hashMapIterator_destroy(iter); + + hashMap_destroy(component->dependencyEvents, false, false); + + arrayList_destroy(component->dependencies); + pthread_mutex_destroy(&component->mutex); + + free(component); + } +} + +celix_status_t component_addServiceDependency(dm_component_pt component, dm_service_dependency_pt dep) { + celix_status_t status = CELIX_SUCCESS; + + executor_executeTask(component->executor, component, component_addTask, dep); + + return status; +} + + +static celix_status_t component_addTask(dm_component_pt component, dm_service_dependency_pt dep) { + celix_status_t status = CELIX_SUCCESS; + + array_list_pt bounds = NULL; + arrayList_create(&bounds); + + array_list_pt events = NULL; + arrayList_createWithEquals(event_equals, &events); + + pthread_mutex_lock(&component->mutex); + hashMap_put(component->dependencyEvents, dep, events); + arrayList_add(component->dependencies, dep); + pthread_mutex_unlock(&component->mutex); + + serviceDependency_setComponent(dep, component); + + if (component->state != DM_CMP_STATE_INACTIVE) { + serviceDependency_setInstanceBound(dep, true); + arrayList_add(bounds, dep); + } + component_startDependencies(component, bounds); + component_handleChange(component); + + arrayList_destroy(bounds); + + return status; +} + +dm_component_state_t component_currentState(dm_component_pt cmp) { + return cmp->state; +} + +void * component_getImplementation(dm_component_pt cmp) { + return cmp->implementation; +} + +const char * component_getName(dm_component_pt cmp) { + return cmp->name; +} + +celix_status_t component_removeServiceDependency(dm_component_pt component, dm_service_dependency_pt dependency) { + celix_status_t status = CELIX_SUCCESS; + + executor_executeTask(component->executor, component, component_removeTask, dependency); + + return status; +} + +celix_status_t component_removeTask(dm_component_pt component, dm_service_dependency_pt dependency) { + celix_status_t status = CELIX_SUCCESS; + + pthread_mutex_lock(&component->mutex); + arrayList_removeElement(component->dependencies, dependency); + pthread_mutex_unlock(&component->mutex); + + if (component->state != DM_CMP_STATE_INACTIVE) { + serviceDependency_stop(dependency); + } + + pthread_mutex_lock(&component->mutex); + array_list_pt events = hashMap_remove(component->dependencyEvents, dependency); + pthread_mutex_unlock(&component->mutex); + + serviceDependency_destroy(&dependency); + + while (!arrayList_isEmpty(events)) { + dm_event_pt event = arrayList_remove(events, 0); + event_destroy(&event); + } + arrayList_destroy(events); + + component_handleChange(component); + + return status; +} + +celix_status_t component_start(dm_component_pt component) { + celix_status_t status = CELIX_SUCCESS; + + component->active = true; + executor_executeTask(component->executor, component, component_startTask, NULL); + + return status; +} + +celix_status_t component_startTask(dm_component_pt component, void *data __attribute__((unused))) { + celix_status_t status = CELIX_SUCCESS; + + component->isStarted = true; + component_handleChange(component); + + return status; +} + +celix_status_t component_stop(dm_component_pt component) { + celix_status_t status = CELIX_SUCCESS; + + component->active = false; + executor_executeTask(component->executor, component, component_stopTask, NULL); + + return status; +} + +celix_status_t component_stopTask(dm_component_pt component, void *data __attribute__((unused))) { + celix_status_t status = CELIX_SUCCESS; + + component->isStarted = false; + component_handleChange(component); + component->active = false; + + return status; +} + +celix_status_t component_setCLanguageProperty(dm_component_pt component, bool setCLangProp) { + component->setCLanguageProperty = setCLangProp; + return CELIX_SUCCESS; +} + +celix_status_t component_addInterface(dm_component_pt component, const char* serviceName, const char* serviceVersion, const void* service, properties_pt properties) { + celix_status_t status = CELIX_SUCCESS; + - if (component->active) { - return CELIX_ILLEGAL_STATE; - } else { - dm_interface_t *interface = (dm_interface_t *) calloc(1, sizeof(*interface)); - char *name = strdup(serviceName); ++ dm_interface_t *interface = (dm_interface_t *) calloc(1, sizeof(*interface)); ++ char *name = strdup(serviceName); + - if (properties == NULL) { - properties = properties_create(); - } ++ if (properties == NULL) { ++ properties = properties_create(); ++ } + - if ((properties_get(properties, CELIX_FRAMEWORK_SERVICE_VERSION) == NULL) && (serviceVersion != NULL)) { - properties_set(properties, CELIX_FRAMEWORK_SERVICE_VERSION, serviceVersion); - } ++ if ((properties_get(properties, CELIX_FRAMEWORK_SERVICE_VERSION) == NULL) && (serviceVersion != NULL)) { ++ properties_set(properties, CELIX_FRAMEWORK_SERVICE_VERSION, serviceVersion); ++ } + - if (component->setCLanguageProperty && properties_get(properties, CELIX_FRAMEWORK_SERVICE_LANGUAGE) == NULL) { //always set default lang to C - properties_set(properties, CELIX_FRAMEWORK_SERVICE_LANGUAGE, CELIX_FRAMEWORK_SERVICE_C_LANGUAGE); - } ++ if (component->setCLanguageProperty && properties_get(properties, CELIX_FRAMEWORK_SERVICE_LANGUAGE) == NULL) { //always set default lang to C ++ properties_set(properties, CELIX_FRAMEWORK_SERVICE_LANGUAGE, CELIX_FRAMEWORK_SERVICE_C_LANGUAGE); ++ } + - if (interface && name) { - interface->serviceName = name; - interface->service = service; - interface->properties = properties; - interface->registration = NULL; - arrayList_add(component->dm_interfaces, interface); - } else { - free(interface); - free(name); - status = CELIX_ENOMEM; ++ if (interface && name) { ++ interface->serviceName = name; ++ interface->service = service; ++ interface->properties = properties; ++ interface->registration = NULL; ++ celixThreadMutex_lock(&component->mutex); ++ arrayList_add(component->dm_interfaces, interface); ++ celixThreadMutex_unlock(&component->mutex); ++ if (component->state == DM_CMP_STATE_TRACKING_OPTIONAL) { ++ component_registerServices(component); + } ++ } else { ++ free(interface); ++ free(name); ++ status = CELIX_ENOMEM; + } + + return status; +} + ++ +celix_status_t component_getInterfaces(dm_component_pt component, array_list_pt *out) { + celix_status_t status = CELIX_SUCCESS; + array_list_pt names = NULL; + arrayList_create(&names); + celixThreadMutex_lock(&component->mutex); + int size = arrayList_size(component->dm_interfaces); + int i; + for (i = 0; i < size; i += 1) { + dm_interface_info_pt info = calloc(1, sizeof(*info)); + dm_interface_t *interface = arrayList_get(component->dm_interfaces, i); + info->name = strdup(interface->serviceName); + properties_copy(interface->properties, &info->properties); + arrayList_add(names, info); + } + celixThreadMutex_unlock(&component->mutex); + + if (status == CELIX_SUCCESS) { + *out = names; + } + + return status; +} + +celix_status_t component_handleEvent(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event) { + celix_status_t status = CELIX_SUCCESS; + + dm_handle_event_type_pt data = calloc(1, sizeof(*data)); + data->dependency = dependency; + data->event = event; + data->newEvent = NULL; + + status = executor_executeTask(component->executor, component, component_handleEventTask, data); +// component_handleEventTask(component, data); + + return status; +} + +celix_status_t component_handleEventTask(dm_component_pt component, dm_handle_event_type_pt data) { + celix_status_t status = CELIX_SUCCESS; + + switch (data->event->event_type) { + case DM_EVENT_ADDED: + component_handleAdded(component,data->dependency, data->event); + break; + case DM_EVENT_CHANGED: + component_handleChanged(component,data->dependency, data->event); + break; + case DM_EVENT_REMOVED: + component_handleRemoved(component,data->dependency, data->event); + break; + case DM_EVENT_SWAPPED: + component_handleSwapped(component,data->dependency, data->event, data->newEvent); + break; + default: + break; + } + + free(data); + + return status; +} + +static celix_status_t component_suspend(dm_component_pt component, dm_service_dependency_pt dependency) { + celix_status_t status = CELIX_SUCCESS; + + dm_service_dependency_strategy_t strategy; + serviceDependency_getStrategy(dependency, &strategy); + if (strategy == DM_SERVICE_DEPENDENCY_STRATEGY_SUSPEND && component->callbackStop != NULL) { + status = component->callbackStop(component->implementation); + } + + return status; +} + +static celix_status_t component_resume(dm_component_pt component, dm_service_dependency_pt dependency) { + celix_status_t status = CELIX_SUCCESS; + + dm_service_dependency_strategy_t strategy; + serviceDependency_getStrategy(dependency, &strategy); + if (strategy == DM_SERVICE_DEPENDENCY_STRATEGY_SUSPEND && component->callbackStop != NULL) { + status = component->callbackStart(component->implementation); + } + + return status; +} + +celix_status_t component_handleAdded(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event) { + celix_status_t status = CELIX_SUCCESS; + + pthread_mutex_lock(&component->mutex); + array_list_pt events = hashMap_get(component->dependencyEvents, dependency); + arrayList_add(events, event); + pthread_mutex_unlock(&component->mutex); + + serviceDependency_setAvailable(dependency, true); + + switch (component->state) { + case DM_CMP_STATE_WAITING_FOR_REQUIRED: { + serviceDependency_invokeSet(dependency, event); + bool required = false; + serviceDependency_isRequired(dependency, &required); + if (required) { + component_handleChange(component); + } + break; + } + case DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED: { + bool instanceBound = false; + serviceDependency_isInstanceBound(dependency, &instanceBound); + bool required = false; + serviceDependency_isRequired(dependency, &required); + if (!instanceBound) { + if (required) { + serviceDependency_invokeSet(dependency, event); + serviceDependency_invokeAdd(dependency, event); + } + dm_event_pt event = NULL; + component_getDependencyEvent(component, dependency, &event); + component_updateInstance(component, dependency, event, false, true); + } + + if (required) { + component_handleChange(component); + } + break; + } + case DM_CMP_STATE_TRACKING_OPTIONAL: + component_suspend(component,dependency); + serviceDependency_invokeSet(dependency, event); + serviceDependency_invokeAdd(dependency, event); + component_resume(component,dependency); + dm_event_pt event = NULL; + component_getDependencyEvent(component, dependency, &event); + component_updateInstance(component, dependency, event, false, true); + break; + default: + break; + } + + return status; +} + +celix_status_t component_handleChanged(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event) { + celix_status_t status = CELIX_SUCCESS; + + pthread_mutex_lock(&component->mutex); + array_list_pt events = hashMap_get(component->dependencyEvents, dependency); + int index = arrayList_indexOf(events, event); + if (index < 0) { + pthread_mutex_unlock(&component->mutex); + status = CELIX_BUNDLE_EXCEPTION; + } else { + dm_event_pt old = arrayList_remove(events, (unsigned int) index); + arrayList_add(events, event); + pthread_mutex_unlock(&component->mutex); + + serviceDependency_invokeSet(dependency, event); + switch (component->state) { + case DM_CMP_STATE_TRACKING_OPTIONAL: + component_suspend(component,dependency); + serviceDependency_invokeChange(dependency, event); + component_resume(component,dependency); + dm_event_pt hevent = NULL; + component_getDependencyEvent(component, dependency, &hevent); + component_updateInstance(component, dependency, hevent, true, false); + break; + case DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED: { + bool instanceBound = false; + serviceDependency_isInstanceBound(dependency, &instanceBound); + if (!instanceBound) { + serviceDependency_invokeChange(dependency, event); + dm_event_pt hevent = NULL; + component_getDependencyEvent(component, dependency, &hevent); + component_updateInstance(component, dependency, hevent, true, false); + } + break; + } + default: + break; + } + + event_destroy(&old); + } + + return status; +} + +celix_status_t component_handleRemoved(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event) { + celix_status_t status = CELIX_SUCCESS; + + pthread_mutex_lock(&component->mutex); + array_list_pt events = hashMap_get(component->dependencyEvents, dependency); + int size = arrayList_size(events); + if (arrayList_contains(events, event)) { + size--; + } + pthread_mutex_unlock(&component->mutex); + serviceDependency_setAvailable(dependency, size > 0); + component_handleChange(component); + + pthread_mutex_lock(&component->mutex); + int index = arrayList_indexOf(events, event); + if (index < 0) { + pthread_mutex_unlock(&component->mutex); + status = CELIX_BUNDLE_EXCEPTION; + } else { + dm_event_pt old = arrayList_remove(events, (unsigned int) index); + pthread_mutex_unlock(&component->mutex); + + + switch (component->state) { + case DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED: { + serviceDependency_invokeSet(dependency, event); + bool instanceBound = false; + serviceDependency_isInstanceBound(dependency, &instanceBound); + if (!instanceBound) { + bool required = false; + serviceDependency_isRequired(dependency, &required); + if (required) { + serviceDependency_invokeRemove(dependency, event); + } + dm_event_pt hevent = NULL; + component_getDependencyEvent(component, dependency, &hevent); + component_updateInstance(component, dependency, hevent, false, false); + } + break; + } + case DM_CMP_STATE_TRACKING_OPTIONAL: + component_suspend(component,dependency); + serviceDependency_invokeSet(dependency, event); + serviceDependency_invokeRemove(dependency, event); + component_resume(component,dependency); + dm_event_pt hevent = NULL; + component_getDependencyEvent(component, dependency, &hevent); + component_updateInstance(component, dependency, hevent, false, false); + break; + default: + break; + } + + event_destroy(&event); + if (old) { + event_destroy(&old); + } + } + + return status; +} + +celix_status_t component_handleSwapped(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event, dm_event_pt newEvent) { + celix_status_t status = CELIX_SUCCESS; + + pthread_mutex_lock(&component->mutex); + array_list_pt events = hashMap_get(component->dependencyEvents, dependency); + int index = arrayList_indexOf(events, event); + if (index < 0) { + pthread_mutex_unlock(&component->mutex); + status = CELIX_BUNDLE_EXCEPTION; + } else { + dm_event_pt old = arrayList_remove(events, (unsigned int) index); + arrayList_add(events, newEvent); + pthread_mutex_unlock(&component->mutex); + + serviceDependency_invokeSet(dependency, event); + + switch (component->state) { + case DM_CMP_STATE_WAITING_FOR_REQUIRED: + break; + case DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED: { + bool instanceBound = false; + serviceDependency_isInstanceBound(dependency, &instanceBound); + if (!instanceBound) { + bool required = false; + serviceDependency_isRequired(dependency, &required); + if (required) { + serviceDependency_invokeSwap(dependency, event, newEvent); + } + } + break; + } + case DM_CMP_STATE_TRACKING_OPTIONAL: + component_suspend(component,dependency); + serviceDependency_invokeSwap(dependency, event, newEvent); + component_resume(component,dependency); + break; + default: + break; + } + + event_destroy(&event); + if (old) { + event_destroy(&old); + } + } + + return status; +} + +celix_status_t component_updateInstance(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event, bool update, bool add) { + celix_status_t status = CELIX_SUCCESS; + + bool autoConfig = false; + + serviceDependency_isAutoConfig(dependency, &autoConfig); + + if (autoConfig) { + const void *service = NULL; + const void **field = NULL; + + if (event != NULL) { + event_getService(event, &service); + } + serviceDependency_getAutoConfig(dependency, &field); + serviceDependency_lock(dependency); + *field = service; + serviceDependency_unlock(dependency); + } + + return status; +} + +celix_status_t component_startDependencies(dm_component_pt component __attribute__((unused)), array_list_pt dependencies) { + celix_status_t status = CELIX_SUCCESS; + array_list_pt required_dependencies = NULL; + arrayList_create(&required_dependencies); + + for (unsigned int i = 0; i < arrayList_size(dependencies); i++) { + dm_service_dependency_pt dependency = arrayList_get(dependencies, i); + bool required = false; + serviceDependency_isRequired(dependency, &required); + if (required) { + arrayList_add(required_dependencies, dependency); + continue; + } + + serviceDependency_start(dependency); + } + + for (unsigned int i = 0; i < arrayList_size(required_dependencies); i++) { + dm_service_dependency_pt dependency = arrayList_get(required_dependencies, i); + serviceDependency_start(dependency); + } + + arrayList_destroy(required_dependencies); + + return status; +} + +celix_status_t component_stopDependencies(dm_component_pt component) { + celix_status_t status = CELIX_SUCCESS; + + pthread_mutex_lock(&component->mutex); + for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) { + dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i); + pthread_mutex_unlock(&component->mutex); + serviceDependency_stop(dependency); + pthread_mutex_lock(&component->mutex); + } + pthread_mutex_unlock(&component->mutex); + + return status; +} + +celix_status_t component_handleChange(dm_component_pt component) { + celix_status_t status = CELIX_SUCCESS; + + dm_component_state_t oldState; + dm_component_state_t newState; + + bool transition = false; + do { + oldState = component->state; + status = component_calculateNewState(component, oldState, &newState); + if (status == CELIX_SUCCESS) { + component->state = newState; + status = component_performTransition(component, oldState, newState, &transition); + } + + if (status != CELIX_SUCCESS) { + break; + } + } while (transition); + + return status; +} + +celix_status_t component_calculateNewState(dm_component_pt component, dm_component_state_t currentState, dm_component_state_t *newState) { + celix_status_t status = CELIX_SUCCESS; + + if (currentState == DM_CMP_STATE_INACTIVE) { + if (component->isStarted) { + *newState = DM_CMP_STATE_WAITING_FOR_REQUIRED; + } else { + *newState = currentState; + } + } else if (currentState == DM_CMP_STATE_WAITING_FOR_REQUIRED) { + if (!component->isStarted) { + *newState = DM_CMP_STATE_INACTIVE; + } else { + bool available = false; + component_allRequiredAvailable(component, &available); + + if (available) { + *newState = DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED; + } else { + *newState = currentState; + } + } + } else if (currentState == DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED) { + if (!component->isStarted) { + *newState = DM_CMP_STATE_WAITING_FOR_REQUIRED; + } else { + bool available = false; + component_allRequiredAvailable(component, &available); + + if (available) { + bool instanceBoundAvailable = false; + component_allInstanceBoundAvailable(component, &instanceBoundAvailable); + + if (instanceBoundAvailable) { + *newState = DM_CMP_STATE_TRACKING_OPTIONAL; + } else { + *newState = currentState; + } + } else { + *newState = currentState; + } + } + } else if (currentState == DM_CMP_STATE_TRACKING_OPTIONAL) { + bool instanceBoundAvailable = false; + bool available = false; + + component_allInstanceBoundAvailable(component, &instanceBoundAvailable); + component_allRequiredAvailable(component, &available); + + if (component->isStarted && available && instanceBoundAvailable) { + *newState = currentState; + } else { + *newState = DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED; + } + } else { + //should not reach + *newState = DM_CMP_STATE_INACTIVE; + status = CELIX_BUNDLE_EXCEPTION; + } + + return status; +} + +celix_status_t component_performTransition(dm_component_pt component, dm_component_state_t oldState, dm_component_state_t newState, bool *transition) { + celix_status_t status = CELIX_SUCCESS; + //printf("performing transition for %s in thread %i from %i to %i\n", component->name, (int) pthread_self(), oldState, newState); + + if (oldState == newState) { + *transition = false; + } else if (oldState == DM_CMP_STATE_INACTIVE && newState == DM_CMP_STATE_WAITING_FOR_REQUIRED) { + component_startDependencies(component, component->dependencies); + *transition = true; + } else if (oldState == DM_CMP_STATE_WAITING_FOR_REQUIRED && newState == DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED) { + component_invokeAddRequiredDependencies(component); + component_invokeAutoConfigDependencies(component); + if (component->callbackInit) { + status = component->callbackInit(component->implementation); + } + *transition = true; + } else if (oldState == DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED && newState == DM_CMP_STATE_TRACKING_OPTIONAL) { + component_invokeAddRequiredInstanceBoundDependencies(component); + component_invokeAutoConfigInstanceBoundDependencies(component); + component_invokeAddOptionalDependencies(component); + if (component->callbackStart) { + status = component->callbackStart(component->implementation); + } + component_registerServices(component); + *transition = true; + } else if (oldState == DM_CMP_STATE_TRACKING_OPTIONAL && newState == DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED) { + component_unregisterServices(component); + if (component->callbackStop) { + status = component->callbackStop(component->implementation); + } + component_invokeRemoveOptionalDependencies(component); + component_invokeRemoveInstanceBoundDependencies(component); + *transition = true; + } else if (oldState == DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED && newState == DM_CMP_STATE_WAITING_FOR_REQUIRED) { + if (component->callbackDeinit) { + status = component->callbackDeinit(component->implementation); + } + component_invokeRemoveRequiredDependencies(component); + *transition = true; + } else if (oldState == DM_CMP_STATE_WAITING_FOR_REQUIRED && newState == DM_CMP_STATE_INACTIVE) { + component_stopDependencies(component); + *transition = true; + } + + return status; +} + +celix_status_t component_allRequiredAvailable(dm_component_pt component, bool *available) { + celix_status_t status = CELIX_SUCCESS; + + pthread_mutex_lock(&component->mutex); + *available = true; + for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) { + dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i); + bool required = false; + bool instanceBound = false; + + serviceDependency_isRequired(dependency, &required); + serviceDependency_isInstanceBound(dependency, &instanceBound); + + if (required && !instanceBound) { + bool isAvailable = false; + serviceDependency_isAvailable(dependency, &isAvailable); + if (!isAvailable) { + *available = false; + break; + } + } + } + pthread_mutex_unlock(&component->mutex); + + return status; +} + +celix_status_t component_allInstanceBoundAvailable(dm_component_pt component, bool *available) { + celix_status_t status = CELIX_SUCCESS; + + pthread_mutex_lock(&component->mutex); + *available = true; + for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) { + dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i); + bool required = false; + bool instanceBound = false; + + serviceDependency_isRequired(dependency, &required); + serviceDependency_isInstanceBound(dependency, &instanceBound); + + if (required && instanceBound) { + bool isAvailable = false; + serviceDependency_isAvailable(dependency, &isAvailable); + if (!isAvailable) { + *available = false; + break; + } + } + } + pthread_mutex_unlock(&component->mutex); + + return status; +} + +celix_status_t component_invokeAddRequiredDependencies(dm_component_pt component) { + celix_status_t status = CELIX_SUCCESS; + + pthread_mutex_lock(&component->mutex); + for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) { + dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i); + + bool required = false; + bool instanceBound = false; + + serviceDependency_isRequired(dependency, &required); + serviceDependency_isInstanceBound(dependency, &instanceBound); + + if (required && !instanceBound) { + array_list_pt events = hashMap_get(component->dependencyEvents, dependency); + if (events) { + for (unsigned int j = 0; j < arrayList_size(events); j++) { + dm_event_pt event = arrayList_get(events, j); + serviceDependency_invokeAdd(dependency, event); + } + } + } + } + pthread_mutex_unlock(&component->mutex); + + return status; +} + +celix_status_t component_invokeAutoConfigDependencies(dm_component_pt component) { + celix_status_t status = CELIX_SUCCESS; + + pthread_mutex_lock(&component->mutex); + for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) { + dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i); + + bool autoConfig = false; + bool instanceBound = false; + + serviceDependency_isAutoConfig(dependency, &autoConfig); + serviceDependency_isInstanceBound(dependency, &instanceBound); + + if (autoConfig && !instanceBound) { + component_configureImplementation(component, dependency); + } + } + pthread_mutex_unlock(&component->mutex); + + return status; +} + +celix_status_t component_invokeAutoConfigInstanceBoundDependencies(dm_component_pt component) { + celix_status_t status = CELIX_SUCCESS; + + pthread_mutex_lock(&component->mutex); + for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) { + dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i); + + bool autoConfig = false; + bool instanceBound = false; + + serviceDependency_isAutoConfig(dependency, &autoConfig); + serviceDependency_isInstanceBound(dependency, &instanceBound); + + if (autoConfig && instanceBound) { + component_configureImplementation(component, dependency); + } + } + pthread_mutex_unlock(&component->mutex); + + return status; +} + +celix_status_t component_invokeAddRequiredInstanceBoundDependencies(dm_component_pt component) { + celix_status_t status = CELIX_SUCCESS; + + pthread_mutex_lock(&component->mutex); + for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) { + dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i); + + bool required = false; + bool instanceBound = false; + + serviceDependency_isRequired(dependency, &required); + serviceDependency_isInstanceBound(dependency, &instanceBound); + + if (instanceBound && required) { + array_list_pt events = hashMap_get(component->dependencyEvents, dependency); + if (events) { + for (unsigned int j = 0; j < arrayList_size(events); j++) { + dm_event_pt event = arrayList_get(events, j); + serviceDependency_invokeAdd(dependency, event); + } + } + } + } + pthread_mutex_unlock(&component->mutex); + + return status; +} + +celix_status_t component_invokeAddOptionalDependencies(dm_component_pt component) { + celix_status_t status = CELIX_SUCCESS; + + pthread_mutex_lock(&component->mutex); + for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) { + dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i); + + bool required = false; + + serviceDependency_isRequired(dependency, &required); + + if (!required) { + array_list_pt events = hashMap_get(component->dependencyEvents, dependency); + if (events) { + for (unsigned int j = 0; j < arrayList_size(events); j++) { + dm_event_pt event = arrayList_get(events, j); + serviceDependency_invokeAdd(dependency, event); + } + } + } + } + pthread_mutex_unlock(&component->mutex); + + return status; +} + +celix_status_t component_invokeRemoveOptionalDependencies(dm_component_pt component) { + celix_status_t status = CELIX_SUCCESS; + + pthread_mutex_lock(&component->mutex); + for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) { + dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i); + + bool required = false; + + serviceDependency_isRequired(dependency, &required); + + if (!required) { + array_list_pt events = hashMap_get(component->dependencyEvents, dependency); + if (events) { + for (unsigned int j = 0; j < arrayList_size(events); j++) { + dm_event_pt event = arrayList_get(events, j); + serviceDependency_invokeRemove(dependency, event); + } + } + } + } + pthread_mutex_unlock(&component->mutex); + + return status; +} + +celix_status_t component_invokeRemoveInstanceBoundDependencies(dm_component_pt component) { + celix_status_t status = CELIX_SUCCESS; + + pthread_mutex_lock(&component->mutex); + for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) { + dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i); + + bool instanceBound = false; + + serviceDependency_isInstanceBound(dependency, &instanceBound); + + if (instanceBound) { + array_list_pt events = hashMap_get(component->dependencyEvents, dependency); + if (events) { + for (unsigned int j = 0; j < arrayList_size(events); j++) { + dm_event_pt event = arrayList_get(events, j); + serviceDependency_invokeRemove(dependency, event); + } + } + } + } + pthread_mutex_unlock(&component->mutex); + + return status; +} + +celix_status_t component_invokeRemoveRequiredDependencies(dm_component_pt component) { + celix_status_t status = CELIX_SUCCESS; + + pthread_mutex_lock(&component->mutex); + for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) { + dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i); + + bool required = false; + bool instanceBound = false; + + serviceDependency_isRequired(dependency, &required); + serviceDependency_isInstanceBound(dependency, &instanceBound); + + if (!instanceBound && required) { + array_list_pt events = hashMap_get(component->dependencyEvents, dependency); + if (events) { + for (unsigned int j = 0; j < arrayList_size(events); j++) { + dm_event_pt event = arrayList_get(events, j); + serviceDependency_invokeRemove(dependency, event); + } + } + } + } + pthread_mutex_unlock(&component->mutex); + + return status; +} + +celix_status_t component_getDependencyEvent(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt *event_pptr) { + celix_status_t status = CELIX_SUCCESS; + + array_list_pt events = hashMap_get(component->dependencyEvents, dependency); + *event_pptr = NULL; + + if (events) { + for (unsigned int j = 0; j < arrayList_size(events); j++) { + dm_event_pt event_ptr = arrayList_get(events, j); + if (*event_pptr != NULL) { + int compare = 0; + event_compareTo(event_ptr, *event_pptr, &compare); + if (compare > 0) { + *event_pptr = event_ptr; + } + } else { + *event_pptr = event_ptr; + } + } + } + + return status; +} + +celix_status_t component_configureImplementation(dm_component_pt component, dm_service_dependency_pt dependency) { + celix_status_t status = CELIX_SUCCESS; + + const void **field = NULL; + + array_list_pt events = hashMap_get(component->dependencyEvents, dependency); + if (events) { + const void *service = NULL; + dm_event_pt event = NULL; + component_getDependencyEvent(component, dependency, &event); + if (event != NULL) { + event_getService(event, &service); + serviceDependency_getAutoConfig(dependency, &field); + serviceDependency_lock(dependency); + *field = service; + serviceDependency_unlock(dependency); + } + } + + return status; +} + +celix_status_t component_registerServices(dm_component_pt component) { + celix_status_t status = CELIX_SUCCESS; + + if (component->context != NULL) { + unsigned int i; ++ celixThreadMutex_lock(&component->mutex); + for (i = 0; i < arrayList_size(component->dm_interfaces); i++) { + dm_interface_t *interface = arrayList_get(component->dm_interfaces, i); ++ if (interface->registration == NULL) { + properties_pt regProps = NULL; + properties_copy(interface->properties, ®Props); - bundleContext_registerService(component->context, interface->serviceName, interface->service, regProps, &interface->registration); ++ bundleContext_registerService(component->context, interface->serviceName, interface->service, regProps, ++ &interface->registration); ++ } + } ++ celixThreadMutex_unlock(&component->mutex); + } + + return status; +} + +celix_status_t component_unregisterServices(dm_component_pt component) { + celix_status_t status = CELIX_SUCCESS; + + unsigned int i; + ++ celixThreadMutex_lock(&component->mutex); + for (i = 0; i < arrayList_size(component->dm_interfaces); i++) { - dm_interface_t *interface = arrayList_get(component->dm_interfaces, i); ++ dm_interface_t *interface = arrayList_get(component->dm_interfaces, i); + - serviceRegistration_unregister(interface->registration); - interface->registration = NULL; ++ serviceRegistration_unregister(interface->registration); ++ interface->registration = NULL; + } ++ celixThreadMutex_unlock(&component->mutex); + + return status; +} + +celix_status_t component_setCallbacks(dm_component_pt component, init_fpt init, start_fpt start, stop_fpt stop, deinit_fpt deinit) { + if (component->active) { + return CELIX_ILLEGAL_STATE; + } + component->callbackInit = init; + component->callbackStart = start; + component->callbackStop = stop; + component->callbackDeinit = deinit; + return CELIX_SUCCESS; +} + +celix_status_t component_isAvailable(dm_component_pt component, bool *available) { + *available = component->state == DM_CMP_STATE_TRACKING_OPTIONAL; + return CELIX_SUCCESS; +} + +celix_status_t component_setImplementation(dm_component_pt component, void *implementation) { + component->implementation = implementation; + return CELIX_SUCCESS; +} + +celix_status_t component_getBundleContext(dm_component_pt component, bundle_context_pt *context) { + celix_status_t status = CELIX_SUCCESS; + + if (!component) { + status = CELIX_ILLEGAL_ARGUMENT; + } + + if (status == CELIX_SUCCESS) { + *context = component->context; + } + + return status; +} + + +static celix_status_t executor_create(dm_component_pt component __attribute__((unused)), dm_executor_pt *executor) { + celix_status_t status = CELIX_SUCCESS; + + *executor = malloc(sizeof(**executor)); + if (!*executor) { + status = CELIX_ENOMEM; + } else { + linkedList_create(&(*executor)->workQueue); + pthread_mutex_init(&(*executor)->mutex, NULL); + (*executor)->runningThreadSet = false; + } + + return status; +} + +static void executor_destroy(dm_executor_pt executor) { + + if (executor) { + pthread_mutex_destroy(&executor->mutex); + linkedList_destroy(executor->workQueue); + + free(executor); + } +} + +static celix_status_t executor_schedule(dm_executor_pt executor, dm_component_pt component, void (*command), void *data) { + celix_status_t status = CELIX_SUCCESS; + + dm_executor_task_t *task = NULL; + task = malloc(sizeof(*task)); + if (!task) { + status = CELIX_ENOMEM; + } else { + task->component = component; + task->command = command; + task->data = data; + + pthread_mutex_lock(&executor->mutex); + linkedList_addLast(executor->workQueue, task); + pthread_mutex_unlock(&executor->mutex); + } + + return status; +} + +static celix_status_t executor_executeTask(dm_executor_pt executor, dm_component_pt component, void (*command), void *data) { + celix_status_t status = CELIX_SUCCESS; + + // Check thread and executor thread, if the same, execute immediately. +// bool execute = false; +// pthread_mutex_lock(&executor->mutex); +// pthread_t currentThread = pthread_self(); +// if (pthread_equal(executor->runningThread, currentThread)) { +// execute = true; +// } +// pthread_mutex_unlock(&executor->mutex); + + // For now, just schedule. + executor_schedule(executor, component, command, data); + executor_execute(executor); + + return status; +} + +static celix_status_t executor_execute(dm_executor_pt executor) { + celix_status_t status = CELIX_SUCCESS; + pthread_t currentThread = pthread_self(); + + pthread_mutex_lock(&executor->mutex); + bool execute = false; + if (!executor->runningThreadSet) { + executor->runningThread = currentThread; + executor->runningThreadSet = true; + execute = true; + } + pthread_mutex_unlock(&executor->mutex); + if (execute) { + executor_runTasks(executor, currentThread); + } + + return status; +} + +static celix_status_t executor_runTasks(dm_executor_pt executor, pthread_t currentThread __attribute__((unused))) { + celix_status_t status = CELIX_SUCCESS; +// bool execute = false; + + do { + dm_executor_task_t *entry = NULL; + pthread_mutex_lock(&executor->mutex); + while ((entry = linkedList_removeFirst(executor->workQueue)) != NULL) { + pthread_mutex_unlock(&executor->mutex); + + entry->command(entry->component, entry->data); + + pthread_mutex_lock(&executor->mutex); + + free(entry); + } + executor->runningThreadSet = false; + pthread_mutex_unlock(&executor->mutex); + +// pthread_mutex_lock(&executor->mutex); +// if (executor->runningThread == NULL) { +// executor->runningThread = currentThread; +// execute = true; +// } +// pthread_mutex_unlock(&executor->mutex); + } while (!linkedList_isEmpty(executor->workQueue)); // && execute + + return status; +} + +celix_status_t component_getComponentInfo(dm_component_pt component, dm_component_info_pt *out) { + celix_status_t status = CELIX_SUCCESS; + int i; + int size; + dm_component_info_pt info = NULL; + info = calloc(1, sizeof(*info)); + + if (info == NULL) { + return CELIX_ENOMEM; + } + + arrayList_create(&info->dependency_list); + component_getInterfaces(component, &info->interfaces); + info->active = false; + memcpy(info->id, component->id, DM_COMPONENT_MAX_ID_LENGTH); + memcpy(info->name, component->name, DM_COMPONENT_MAX_NAME_LENGTH); + + switch (component->state) { + case DM_CMP_STATE_INACTIVE : + info->state = strdup("INACTIVE"); + break; + case DM_CMP_STATE_WAITING_FOR_REQUIRED : + info->state = strdup("WAITING_FOR_REQUIRED"); + break; + case DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED : + info->state = strdup("INSTANTIATED_AND_WAITING_FOR_REQUIRED"); + break; + case DM_CMP_STATE_TRACKING_OPTIONAL : + info->state = strdup("TRACKING_OPTIONAL"); + info->active = true; + break; + default : + info->state = strdup("UNKNOWN"); + break; + } + + celixThreadMutex_lock(&component->mutex); + size = arrayList_size(component->dependencies); + for (i = 0; i < size; i += 1) { + dm_service_dependency_pt dep = arrayList_get(component->dependencies, i); + dm_service_dependency_info_pt depInfo = NULL; + status = serviceDependency_getServiceDependencyInfo(dep, &depInfo); + if (status == CELIX_SUCCESS) { + arrayList_add(info->dependency_list, depInfo); + } else { + break; + } + } + celixThreadMutex_unlock(&component->mutex); + + if (status == CELIX_SUCCESS) { + *out = info; + } else if (info != NULL) { + component_destroyComponentInfo(info); + } + + return status; +} + +void component_destroyComponentInfo(dm_component_info_pt info) { + int i; + int size; + if (info != NULL) { + free(info->state); + + if (info->interfaces != NULL) { + size = arrayList_size(info->interfaces); + for (i = 0; i < size; i += 1) { + dm_interface_info_pt intfInfo = arrayList_get(info->interfaces, i); + free(intfInfo->name); + properties_destroy(intfInfo->properties); + free(intfInfo); + } + arrayList_destroy(info->interfaces); + } + if (info->dependency_list != NULL) { + size = arrayList_size(info->dependency_list); + for (i = 0; i < size; i += 1) { + dm_service_dependency_info_pt depInfo = arrayList_get(info->dependency_list, i); + dependency_destroyDependencyInfo(depInfo); + } + arrayList_destroy(info->dependency_list); + } + } + free(info); +}
http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/dfi/CMakeLists.txt ---------------------------------------------------------------------- diff --cc dfi/CMakeLists.txt index 642ac68,676277c..950aaa5 --- a/dfi/CMakeLists.txt +++ b/dfi/CMakeLists.txt @@@ -18,57 -18,73 +18,65 @@@ find_package(FFI REQUIRED) find_package(Jansson REQUIRED) -include_directories( - ${FFI_INCLUDE_DIRS} - ${JANSSON_INCLUDE_DIRS} - private/include - public/include - ${PROJECT_SOURCE_DIR}/utils/public/include +set(SOURCES + src/dyn_common.c + src/dyn_type.c + src/dyn_function.c + src/dyn_interface.c + src/dyn_message.c + src/json_serializer.c + src/json_rpc.c ) - add_library(dfi SHARED ${SOURCES}) - set_target_properties(dfi PROPERTIES OUTPUT_NAME "celix_dfi") - target_include_directories(dfi PUBLIC include ${JANSSON_INCLUDE_DIRS}) - target_include_directories(dfi PRIVATE src ${FFI_INCLUDE_DIRS}) - target_link_libraries(dfi PUBLIC ${JANSSON_LIBRARY}) - target_link_libraries(dfi PRIVATE Celix::utils ${FFI_LIBRARIES}) - set_target_properties(dfi PROPERTIES "SOVERSION" 1) -set(MEMSTREAM_SOURCES ) -set(MEMSTREAM_INCLUDES ) -if (APPLE OR ANDROID) - set(MEMSTREAM_SOURCES ${PROJECT_SOURCE_DIR}/utils/private/src/memstream/open_memstream.c ${PROJECT_SOURCE_DIR}/utils/private/src/memstream/fmemopen.c) - set(MEMSTREAM_INCLUDES ${PROJECT_SOURCE_DIR}/utils/public/include/memstream/open_memstream.h ${PROJECT_SOURCE_DIR}/utils/public/include/memstream/fmemopen.h) - include_directories(${PROJECT_SOURCE_DIR}/utils/public/include/memstream) -endif() ++add_library(celix_dfi SHARED ${SOURCES}) ++set_target_properties(celix_dfi PROPERTIES OUTPUT_NAME "celix_dfi") ++target_include_directories(celix_dfi PUBLIC include ${JANSSON_INCLUDE_DIRS}) ++target_include_directories(celix_dfi PRIVATE src ${FFI_INCLUDE_DIRS}) ++target_link_libraries(celix_dfi PUBLIC ${JANSSON_LIBRARY}) ++target_link_libraries(celix_dfi PRIVATE Celix::utils ${FFI_LIBRARIES}) ++set_target_properties(celix_dfi PROPERTIES "SOVERSION" 1) - add_library(dfi_static STATIC ${SOURCES}) - set_target_properties(dfi_static PROPERTIES OUTPUT_NAME "celix_dfi_static") - target_include_directories(dfi_static PUBLIC include ${JANSSON_INCLUDE_DIRS}) - target_include_directories(dfi_static PRIVATE src ${FFI_INCLUDE_DIRS}) - target_link_libraries(dfi_static PUBLIC ${JANSSON_LIBRARY}) - target_link_libraries(dfi_static PRIVATE Celix::utils ${FFI_LIBRARIES}) -add_library(celix_dfi SHARED - private/src/dyn_common.c - private/src/dyn_type.c - private/src/dyn_function.c - private/src/dyn_interface.c - private/src/dyn_message.c - private/src/json_serializer.c - private/src/json_rpc.c - ${MEMSTREAM_SOURCES} ++add_library(celix_dfi_static STATIC ${SOURCES}) ++set_target_properties(celix_dfi_static PROPERTIES OUTPUT_NAME "celix_dfi_static") ++target_include_directories(celix_dfi_static PUBLIC include ${JANSSON_INCLUDE_DIRS}) ++target_include_directories(celix_dfi_static PRIVATE src ${FFI_INCLUDE_DIRS}) ++target_link_libraries(celix_dfi_static PUBLIC ${JANSSON_LIBRARY}) ++target_link_libraries(celix_dfi_static PRIVATE Celix::utils ${FFI_LIBRARIES}) - install(TARGETS dfi dfi_static DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT framework) - public/include/dyn_common.h - public/include/dyn_type.h - public/include/dyn_function.h - public/include/dyn_interface.h - public/include/dyn_message.h - public/include/json_serializer.h - public/include/json_rpc.h - ${MEMSTREAM_INCLUDES} -) -set_target_properties(celix_dfi PROPERTIES "SOVERSION" 1) -set_target_properties(celix_dfi PROPERTIES "VERSION" 1.1.0) -target_link_libraries(celix_dfi celix_utils ${FFI_LIBRARIES} ${JANSSON_LIBRARY}) ++install(TARGETS celix_dfi celix_dfi_static DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT framework) + install(TARGETS celix_dfi DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT framework) -FILE(GLOB files "public/include/*.h" ${MEMSTREAM_INCLUDES}) ++FILE(GLOB files "include/*.h") + INSTALL(FILES ${files} DESTINATION include/celix/dfi COMPONENT framework) +#Alias setup to match external usage - add_library(Celix::dfi ALIAS dfi) - add_library(Celix::dfi_static ALIAS dfi_static) ++add_library(Celix::dfi ALIAS celix_dfi) ++add_library(Celix::dfi_static ALIAS celix_dfi_static) if (ENABLE_TESTING) find_package(CppUTest REQUIRED) + include_directories(${CPPUTEST_INCLUDE_DIR}) + SET(CMAKE_SKIP_BUILD_RPATH FALSE) #TODO needed? + SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) #TODO needed? + SET(CMAKE_INSTALL_RPATH "${PROJECT_BINARY_DIR}/dfi" "${PROJECT_BINARY_DIR}/utils") + add_executable(test_dfi - private/test/dyn_type_tests.cpp - private/test/dyn_function_tests.cpp - private/test/dyn_closure_tests.cpp - private/test/dyn_interface_tests.cpp - private/test/dyn_message_tests.cpp - private/test/json_serializer_tests.cpp - private/test/json_rpc_tests.cpp - private/test/run_tests.cpp + test/dyn_type_tests.cpp + test/dyn_function_tests.cpp + test/dyn_closure_tests.cpp + test/dyn_interface_tests.cpp + test/dyn_message_tests.cpp + test/json_serializer_tests.cpp + test/json_rpc_tests.cpp + test/run_tests.cpp ) - target_link_libraries(test_dfi celix_dfi ${FFI_LIBRARIES} ${CPPUTEST_LIBRARY}) + target_link_libraries(test_dfi PRIVATE Celix::dfi Celix::utils ${FFI_LIBRARIES} ${CPPUTEST_LIBRARY}) + target_include_directories(test_dfi PRIVATE ${FFI_INCLUDE_DIRS}) - file(COPY ${CMAKE_CURRENT_LIST_DIR}/private/test/schemas DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - file(COPY ${CMAKE_CURRENT_LIST_DIR}/private/test/descriptors DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + file(COPY ${CMAKE_CURRENT_LIST_DIR}/test/schemas DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + file(COPY ${CMAKE_CURRENT_LIST_DIR}/test/descriptors DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) add_test(NAME run_test_dfi COMMAND test_dfi) SETUP_TARGET_FOR_COVERAGE(test_dfi_cov test_dfi ${CMAKE_BINARY_DIR}/coverage/test_dfi/test_dfi) http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/etcdlib/CMakeLists.txt ---------------------------------------------------------------------- diff --cc etcdlib/CMakeLists.txt index 060eeb0,1904dea..fac356a --- a/etcdlib/CMakeLists.txt +++ b/etcdlib/CMakeLists.txt @@@ -41,17 -41,19 +41,18 @@@ endif ( find_package(CURL REQUIRED) find_package(Jansson REQUIRED) -include_directories( - ${CURL_INCLUDE_DIRS} - ${JANSSON_INCLUDE_DIRS} - private/include - public/include -) - add_library(etcdlib SHARED - private/src/etcd.c + src/etcd.c +) +target_include_directories(etcdlib PUBLIC api) +target_include_directories(etcdlib PRIVATE + src + ${CURL_INCLUDE_DIRS} + ${JANSSON_INCLUDE_DIRS} ) - set_target_properties(etcdlib PROPERTIES "SOVERSION" 1) + set_target_properties(etcdlib PROPERTIES SOVERSION 1) + set_target_properties(etcdlib PROPERTIES VERSION 1.0.0) target_link_libraries(etcdlib ${CURL_LIBRARIES} ${JANSSON_LIBRARIES}) add_library(etcdlib_static STATIC http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/examples/dm_example/CMakeLists.txt ---------------------------------------------------------------------- diff --cc examples/dm_example/CMakeLists.txt index 2cef7ec,fa6ec57..a18a675 --- a/examples/dm_example/CMakeLists.txt +++ b/examples/dm_example/CMakeLists.txt @@@ -24,42 -27,41 +24,40 @@@ if (BUILD_DEPENDENCY_MANAGER add_subdirectory(phase3) -- add_deploy("dm_example" ++ add_deploy(dm_example COPY BUNDLES - shell - shell_tui - dm_shell - phase1 - phase2a - phase2b - phase3 + Celix::shell + Celix::shell_tui + Celix::dm_shell + dm_example_phase1 + dm_example_phase2a + dm_example_phase2b + dm_example_phase3 PROPERTIES LOGHELPER_ENABLE_STDOUT_FALLBACK=true ) - if (ENABLE_DOCKER) - add_celix_docker(dm_exmpl_base - NAME dmbase - IMAGE_NAME dmbase - GROUP examples - INSTRUCTIONS - "LABEL exmpl=value" - ) - add_celix_docker(dm_exmpl - FROM dmbase + add_celix_docker(dm_exmpl_base + NAME dmbase + IMAGE_NAME dmbase GROUP examples - BUNDLES - Celix::shell - Celix::shell_tui - Celix::dm_shell - dm_example_phase1 - dm_example_phase2a - dm_example_phase2b - dm_example_phase3 - PROPERTIES - LOGHELPER_ENABLE_STDOUT_FALLBACK=true - ) - endif () + INSTRUCTIONS + "LABEL exmpl=value" + ) + add_celix_docker(dm_exmpl + FROM dmbase + GROUP examples + BUNDLES - shell - shell_tui - dm_shell - phase1 - phase2a - phase2b - phase3 ++ Celix::shell ++ Celix::shell_tui ++ Celix::dm_shell ++ dm_example_phase1 ++ dm_example_phase2a ++ dm_example_phase2b ++ dm_example_phase3 + PROPERTIES + LOGHELPER_ENABLE_STDOUT_FALLBACK=true + ) - add_dependencies(celix-build-dm_exmpl-docker-image celix-build-dm_exmpl_base-docker-image) endif () http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/examples/dm_example/phase1/src/phase1_activator.c ---------------------------------------------------------------------- diff --cc examples/dm_example/phase1/src/phase1_activator.c index 783e642,0000000..31dcb16 mode 100644,000000..100644 --- a/examples/dm_example/phase1/src/phase1_activator.c +++ b/examples/dm_example/phase1/src/phase1_activator.c @@@ -1,85 -1,0 +1,86 @@@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * activator.c + * + * \date Oct 29, 2015 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ +#include <stdlib.h> +#include <phase1_cmp.h> + +#include "bundle_activator.h" +#include "dm_activator.h" + +#include "phase1.h" + +struct phase1_activator_struct { + phase1_cmp_t *phase1Cmp; + phase1_t phase1Serv; +}; + +celix_status_t dm_create(bundle_context_pt context, void **userData) { + printf("PHASE1: dm_create\n"); + *userData = calloc(1, sizeof(struct phase1_activator_struct)); + return *userData != NULL ? CELIX_SUCCESS : CELIX_ENOMEM; +} + +celix_status_t dm_init(void * userData, bundle_context_pt context, dm_dependency_manager_pt manager) { + printf("PHASE1: dm_init\n"); + celix_status_t status = CELIX_SUCCESS; + + + struct phase1_activator_struct *act = (struct phase1_activator_struct *)userData; + + act->phase1Cmp = phase1_create(); + if (act->phase1Cmp != NULL) { + + act->phase1Serv.handle = act->phase1Cmp; + act->phase1Serv.getData = (void *)phase1_getData; + + properties_pt props = properties_create(); + properties_set(props, "id", "phase1"); + + dm_component_pt cmp; + component_create(context, "PHASE1_PROCESSING_COMPONENT", &cmp); + component_setImplementation(cmp, act->phase1Cmp); + component_setCallbacksSafe(cmp, phase1_cmp_t *, phase1_init, phase1_start, phase1_stop, phase1_deinit); ++ phase1_setComp(act->phase1Cmp, cmp); + component_addInterface(cmp, PHASE1_NAME, PHASE1_VERSION, &act->phase1Serv, props); + + dependencyManager_add(manager, cmp); + } else { + status = CELIX_ENOMEM; + } + + return status; +} + +celix_status_t dm_destroy(void * userData, bundle_context_pt context, dm_dependency_manager_pt manager) { + printf("PHASE1: dm-destroy\n"); + + struct phase1_activator_struct *act = (struct phase1_activator_struct *)userData; + if (act->phase1Cmp != NULL) { + phase1_destroy(act->phase1Cmp); + } + free(act); + + return CELIX_SUCCESS; +} http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/examples/dm_example/phase1/src/phase1_cmp.c ---------------------------------------------------------------------- diff --cc examples/dm_example/phase1/src/phase1_cmp.c index 75de182,0000000..40da821 mode 100644,000000..100644 --- a/examples/dm_example/phase1/src/phase1_cmp.c +++ b/examples/dm_example/phase1/src/phase1_cmp.c @@@ -1,99 -1,0 +1,110 @@@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * publisher.c + * + * \date Oct 29, 2015 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <signal.h> + +#include "celix_threads.h" +#include "phase1_cmp.h" ++#include "dm_component.h" + +#define SLEEPTIME 1000 + +struct phase1_cmp_struct { + celix_thread_t thread; + bool running; + unsigned int counter; ++ dm_component_pt component; ++ +}; + +static void *phase1_thread(void *data); + +phase1_cmp_t *phase1_create(void) { + phase1_cmp_t *cmp = calloc(1, sizeof(*cmp)); + if (cmp != NULL) { + cmp->counter = 0; + cmp->running = false; + } + return cmp; +} + ++void phase1_setComp(phase1_cmp_t *cmp, dm_component_pt dmCmp) { ++ cmp->component = dmCmp; ++} ++ +int phase1_init(phase1_cmp_t *cmp) { + printf("init phase1\n"); + return 0; +} + +int phase1_start(phase1_cmp_t *cmp) { + printf("start phase1\n"); + cmp->running = true; + celixThread_create(&cmp->thread, NULL, phase1_thread, cmp); + return 0; +} + +int phase1_stop(phase1_cmp_t *cmp) { + printf("stop phase1\n"); + cmp->running = false; + celixThread_kill(cmp->thread, SIGUSR1); + celixThread_join(cmp->thread, NULL); + return 0; +} + +int phase1_deinit(phase1_cmp_t *cmp) { + printf("deinit phase1\n"); + return 0; +} + +void phase1_destroy(phase1_cmp_t *cmp) { + free(cmp); + printf("destroy phase1\n"); +} + +static void *phase1_thread(void *data) { + phase1_cmp_t *cmp = data; + + while (cmp->running) { + cmp->counter += 1; ++ if (cmp->counter == 2) { ++ static char *runtime_interface = "DUMMY INTERFACE: DO NOT USE\n"; ++ component_addInterface(cmp->component, "RUNTIME_ADDED_INTERFACE", "1.0.0", runtime_interface, NULL); ++ } + usleep(SLEEPTIME); + } + + celixThread_exit(NULL); + return NULL; +} + +int phase1_getData(phase1_cmp_t *cmp, unsigned int *data) { + *data = cmp->counter; + return 0; +} http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/examples/dm_example/phase1/src/phase1_cmp.h ---------------------------------------------------------------------- diff --cc examples/dm_example/phase1/src/phase1_cmp.h index 5715f6e,0000000..153eed1 mode 100644,000000..100644 --- a/examples/dm_example/phase1/src/phase1_cmp.h +++ b/examples/dm_example/phase1/src/phase1_cmp.h @@@ -1,43 -1,0 +1,44 @@@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * publisher.h + * + * \date Oct 29, 2015 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + +#ifndef PHASE1_CMP_H +#define PHASE1_CMP_H - ++#include "dm_component.h" + +typedef struct phase1_cmp_struct phase1_cmp_t; + +phase1_cmp_t *phase1_create(void); ++void phase1_setComp(phase1_cmp_t *cmp, dm_component_pt dmCmp); +int phase1_init(phase1_cmp_t *cmp); +int phase1_start(phase1_cmp_t *cmp); +int phase1_stop(phase1_cmp_t *cmp); +int phase1_deinit(phase1_cmp_t *cmp); +void phase1_destroy(phase1_cmp_t *cmp); + +int phase1_getData(phase1_cmp_t *cmp, unsigned int *data); + + +#endif //PHASE1_CMP_H http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/examples/dm_example_cxx/CMakeLists.txt ---------------------------------------------------------------------- diff --cc examples/dm_example_cxx/CMakeLists.txt index 9ef4c1e,b07f5cc..3f37373 --- a/examples/dm_example_cxx/CMakeLists.txt +++ b/examples/dm_example_cxx/CMakeLists.txt @@@ -24,45 -31,44 +24,45 @@@ if (BUILD_DEPENDENCY_MANAGER_CXX add_subdirectory(phase3_locking) -- add_deploy("dm_example_cxx" ++ add_celix_container("dm_example_cxx" COPY - CXX + CXX BUNDLES - shell - shell_tui - dm_shell - log_service - log_writer + Celix::shell + Celix::shell_tui + Celix::dm_shell + Celix::log_service + Celix::log_writer_stdout - phase1_cxx - phase2a_cxx - phase2b_cxx - phase3_cxx - phase3_locking_cxx + dm_example_cxx_phase1 + dm_example_cxx_phase2a + dm_example_cxx_phase2b + dm_example_cxx_phase3 + dm_example_cxx_phase3_locking PROPERTIES LOGHELPER_ENABLE_STDOUT_FALLBACK=true ) - if (ENABLE_DOCKER) - add_celix_docker(dm_exmpl_cxx - GROUP examples - BUNDLES_DIR /usr/share/bundles - WORKDIR /workspace - BUNDLES - Celix::shell - Celix::shell_tui - Celix::dm_shell - Celix::log_service - Celix::log_writer_stdout - add_celix_docker(dm_exmpl_cxx - CXX - GROUP examples - BUNDLES_DIR /usr/share/bundles - WORKDIR /workspace - BUNDLES - shell - shell_tui - dm_shell - log_service - log_writer - dm_example_cxx_phase1 - dm_example_cxx_phase2a - dm_example_cxx_phase2b - dm_example_cxx_phase3 - dm_example_cxx_phase3_locking - PROPERTIES - LOGHELPER_ENABLE_STDOUT_FALLBACK=true - ) - endif () - phase1_cxx - phase2a_cxx - phase2b_cxx - phase3_cxx - phase3_locking_cxx - PROPERTIES - LOGHELPER_ENABLE_STDOUT_FALLBACK=true - ) ++ add_celix_docker(dm_exmpl_cxx_docker ++ IMAGE_NAME dm_exmpl_cxx ++ GROUP examples ++ BUNDLES_DIR /usr/share/bundles ++ WORKDIR /workspace ++ BUNDLES ++ Celix::shell ++ Celix::shell_tui ++ Celix::dm_shell ++ Celix::log_service ++ Celix::log_writer_stdout ++ ++ dm_example_cxx_phase1 ++ dm_example_cxx_phase2a ++ dm_example_cxx_phase2b ++ dm_example_cxx_phase3 ++ dm_example_cxx_phase3_locking ++ PROPERTIES ++ LOGHELPER_ENABLE_STDOUT_FALLBACK=true ++ ) endif () http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/examples/log_service_example/CMakeLists.txt ---------------------------------------------------------------------- diff --cc examples/log_service_example/CMakeLists.txt index 0363da3,6b7e681..1326a0f --- a/examples/log_service_example/CMakeLists.txt +++ b/examples/log_service_example/CMakeLists.txt @@@ -27,5 -30,7 +27,5 @@@ target_link_libraries(log_service_examp add_deploy(log_example GROUP log_service - BUNDLES log_service_example log_service shell shell_tui + BUNDLES log_service_example Celix::log_service Celix::shell Celix::shell_tui - ) + ) - -target_link_libraries(log_service_example celix_framework celix_utils) http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/framework/include/celix_launcher.h ---------------------------------------------------------------------- diff --cc framework/include/celix_launcher.h index 0d819c9,0000000..5c7cf4d mode 100644,000000..100644 --- a/framework/include/celix_launcher.h +++ b/framework/include/celix_launcher.h @@@ -1,55 -1,0 +1,57 @@@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * celix_launcher.h + * + * \date Jul 30, 2015 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + +#ifndef CELIX_LAUNCHER_H +#define CELIX_LAUNCHER_H + +#include <stdio.h> +#include "framework.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int celixLauncher_launchWithArgs(int argc, char *argv[]); + ++int celixLauncher_launchWithArgsAndProps(int argc, char *argv[], properties_pt config); ++ +int celixLauncher_launch(const char *configFile, framework_pt *framework); + +int celixLauncher_launchWithStream(FILE *config, framework_pt *framework); + +int celixLauncher_launchWithProperties(properties_pt config, framework_pt *framework); + +void celixLauncher_stop(framework_pt framework); + +void celixLauncher_destroy(framework_pt framework); + +void celixLauncher_waitForShutdown(framework_pt framework); + +#ifdef __cplusplus +} +#endif + +#endif //CELIX_LAUNCHER_H
