This is an automated email from the ASF dual-hosted git repository. pnoltes pushed a commit to branch feature/refactor_c_dep_man_service_trackers in repository https://gitbox.apache.org/repos/asf/celix.git
commit af6a73bb3af650be46d824fbc4f95b02c23d7a5f Author: Pepijn Noltes <pepijnnol...@gmail.com> AuthorDate: Tue Jan 5 20:25:02 2021 +0100 Makes start and stop of service dependency tracker and svc registration async --- .../gtest/src/DependencyManagerTestSuite.cc | 2 - libs/framework/gtest/src/single_framework_test.cpp | 46 +++--- libs/framework/include/celix/dm/Component_Impl.h | 2 +- .../include/celix/dm/DependencyManager_Impl.h | 5 +- libs/framework/include/celix_dm_component.h | 5 + libs/framework/src/dm_component_impl.c | 174 +++++++++++++-------- libs/framework/src/dm_component_impl.h | 3 - libs/framework/src/dm_dependency_manager_impl.c | 7 +- libs/framework/src/dm_service_dependency.c | 50 +++--- libs/framework/src/dm_service_dependency_impl.h | 2 +- libs/framework/src/framework.c | 7 +- 11 files changed, 186 insertions(+), 117 deletions(-) diff --git a/libs/framework/gtest/src/DependencyManagerTestSuite.cc b/libs/framework/gtest/src/DependencyManagerTestSuite.cc index 7b0bf12..063fa1d 100644 --- a/libs/framework/gtest/src/DependencyManagerTestSuite.cc +++ b/libs/framework/gtest/src/DependencyManagerTestSuite.cc @@ -104,8 +104,6 @@ TEST_F(DependencyManagerTestSuite, DmGetInfo) { EXPECT_EQ(1, celix_arrayList_size(info->interfaces)); EXPECT_EQ(1, celix_arrayList_size(info->dependency_list)); celix_dependencyManager_destroyInfos(mng, infos); - - celix_dependencyManager_removeAllComponents(mng); } diff --git a/libs/framework/gtest/src/single_framework_test.cpp b/libs/framework/gtest/src/single_framework_test.cpp index 3070ac4..f28f96c 100644 --- a/libs/framework/gtest/src/single_framework_test.cpp +++ b/libs/framework/gtest/src/single_framework_test.cpp @@ -26,35 +26,43 @@ class CelixFramework : public ::testing::Test { -}; +public: + CelixFramework() { + int rc; + celix_framework_t *fw = nullptr; + celix_bundle_context_t *context = nullptr; -TEST_F(CelixFramework, testFramework) { - int rc; - celix_framework_t *framework = nullptr; - celix_bundle_context_t *context = nullptr; + rc = celixLauncher_launch("config.properties", &fw); + EXPECT_EQ(CELIX_SUCCESS, rc); - rc = celixLauncher_launch("config.properties", &framework); - EXPECT_EQ(CELIX_SUCCESS, rc); + bundle_pt bundle = nullptr; + rc = framework_getFrameworkBundle(fw, &bundle); + EXPECT_EQ(CELIX_SUCCESS, rc); - bundle_pt bundle = nullptr; - rc = framework_getFrameworkBundle(framework, &bundle); - EXPECT_EQ(CELIX_SUCCESS, rc); + rc = bundle_getContext(bundle, &context); + EXPECT_EQ(CELIX_SUCCESS, rc); - rc = bundle_getContext(bundle, &context); - EXPECT_EQ(CELIX_SUCCESS, rc); + framework = std::shared_ptr<celix_framework_t>{fw, [](celix_framework_t* cFw) { + celixLauncher_stop(cFw); + celixLauncher_waitForShutdown(cFw); + celixLauncher_destroy(cFw); + }}; + } - celixLauncher_stop(framework); - celixLauncher_waitForShutdown(framework); - celixLauncher_destroy(framework); + std::shared_ptr<celix_framework_t> framework{}; +}; + +TEST_F(CelixFramework, testFramework) { + //nop } TEST_F(CelixFramework, testEventQueue) { - long eid = celix_framework_nextEventId(framework); + long eid = celix_framework_nextEventId(framework.get()); EXPECT_GE(eid, 0); - celix_framework_waitForGenericEvent(framework, eid); //event never issued so should return directly + celix_framework_waitForGenericEvent(framework.get(), eid); //event never issued so should return directly std::atomic<int> count{0}; - celix_framework_fireGenericEvent(framework, eid, -1L, "test", static_cast<void*>(&count), [](void* data) { + celix_framework_fireGenericEvent(framework.get(), eid, -1L, "test", static_cast<void*>(&count), [](void* data) { auto *c = static_cast<std::atomic<int>*>(data); *c += 1; }, static_cast<void*>(&count), [](void* data) { @@ -62,7 +70,7 @@ TEST_F(CelixFramework, testEventQueue) { *c += 3; }); - celix_framework_waitForGenericEvent(framework, eid); + celix_framework_waitForGenericEvent(framework.get(), eid); EXPECT_EQ(4, count); } diff --git a/libs/framework/include/celix/dm/Component_Impl.h b/libs/framework/include/celix/dm/Component_Impl.h index 6e0d8f3..4b80892 100644 --- a/libs/framework/include/celix/dm/Component_Impl.h +++ b/libs/framework/include/celix/dm/Component_Impl.h @@ -52,7 +52,7 @@ inline void BaseComponent::runBuild() { } inline BaseComponent::~BaseComponent() noexcept { - if (!cmpAddedToDepMan) { + if (context != nullptr && !cmpAddedToDepMan) { celix_dmComponent_destroy(cCmp); } } diff --git a/libs/framework/include/celix/dm/DependencyManager_Impl.h b/libs/framework/include/celix/dm/DependencyManager_Impl.h index 3a05135..d4e3a76 100644 --- a/libs/framework/include/celix/dm/DependencyManager_Impl.h +++ b/libs/framework/include/celix/dm/DependencyManager_Impl.h @@ -25,7 +25,7 @@ inline DependencyManager::DependencyManager(celix_bundle_context_t *ctx) : context{ctx, [](celix_bundle_context_t*){/*nop*/}}, cDepMan{celix_bundleContext_getDependencyManager(ctx), [](celix_dependency_manager_t*){/*nop*/}} {} -inline DependencyManager::~DependencyManager() {/*nop*/} +inline DependencyManager::~DependencyManager() {/*nop} template<class T> Component<T>& DependencyManager::createComponentInternal(std::string name) { @@ -33,8 +33,9 @@ Component<T>& DependencyManager::createComponentInternal(std::string name) { Component<T>::create(this->context.get(), this->cDepMan.get()) : Component<T>::create(this->context.get(), this->cDepMan.get(), name); if (cmp->isValid()) { - this->components.push_back(std::unique_ptr<BaseComponent> {cmp}); + this->components.push_back(std::shared_ptr<BaseComponent>{cmp}); } + return *cmp; } diff --git a/libs/framework/include/celix_dm_component.h b/libs/framework/include/celix_dm_component.h index 9e6b7db..3998086 100644 --- a/libs/framework/include/celix_dm_component.h +++ b/libs/framework/include/celix_dm_component.h @@ -59,6 +59,11 @@ celix_dm_component_t* celix_dmComponent_create(celix_bundle_context_t *context, celix_dm_component_t* celix_dmComponent_createWithUUID(celix_bundle_context_t *context, const char* name, const char* UUID); /** + * Get the UUID of the component. + */ +const char* celix_dmComponent_getUUID(celix_dm_component_t* cmp); + +/** * Destroys a DM Component */ void celix_dmComponent_destroy(celix_dm_component_t *cmp); diff --git a/libs/framework/src/dm_component_impl.c b/libs/framework/src/dm_component_impl.c index 409da5a..d930e52 100644 --- a/libs/framework/src/dm_component_impl.c +++ b/libs/framework/src/dm_component_impl.c @@ -22,6 +22,7 @@ #include <uuid/uuid.h> #include <celix_utils.h> #include <assert.h> +#include <celix_bundle.h> #include "celix_constants.h" #include "celix_filter.h" @@ -46,6 +47,15 @@ struct celix_dm_component_struct { celix_array_list_t* providedInterfaces; celix_array_list_t* dependencies; + /** + * TODO needed + * True if the component provides the same service type as it depends on. + * In that case a addtional check has to be made that the component does not depend on its own provided service, + * because this can result in a deadlock (cannot unregister if service is in use and unregister can happen in a + * remote service tracker callback) + */ + bool providesSameServiceAsOneOfTheDependencies; + celix_dm_component_state_t state; bool isStarted; }; @@ -55,6 +65,7 @@ typedef struct dm_interface_struct { const void* service; celix_properties_t *properties; long svcId; + bool unregistering; } dm_interface_t; static celix_status_t component_registerServices(celix_dm_component_t *component); @@ -69,6 +80,7 @@ static celix_status_t component_handleSet(celix_dm_component_t *component, const static celix_status_t component_startDependencies(celix_dm_component_t *component); static celix_status_t component_suspend(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency); static celix_status_t component_resume(celix_dm_component_t *component, celix_dm_service_dependency_t *dependency); +static celix_status_t celix_dmComponent_stop(celix_dm_component_t *component); celix_dm_component_t* celix_dmComponent_create(bundle_context_t *context, const char* name) { @@ -88,7 +100,8 @@ celix_dm_component_t* celix_dmComponent_createWithUUID(bundle_context_t *context genRandomUUID = false; } else { //parsing went wrong - //TODO print error + fw_log(context->framework->logger, CELIX_LOG_LEVEL_WARNING, + "Cannot parse provided uuid '%s'. Not a valid UUID?. UUID will be generated", uuidIn); } } @@ -135,31 +148,35 @@ void component_destroy(celix_dm_component_t *component) { void celix_dmComponent_destroy(celix_dm_component_t *component) { if (component) { - celix_private_dmComponent_stop(component); //all service deregistered // all svc tracker stopped - //TODO for async wait till events are cleared (maintain a async count + condition?) + celix_dmComponent_stop(component); //all service deregistered // all svc tracker stopped - for (int i = 0; i < celix_arrayList_size(component->providedInterfaces); ++i) { - dm_interface_t *interface = celix_arrayList_get(component->providedInterfaces, i); + for (int i = 0; i < celix_arrayList_size(component->providedInterfaces); ++i) { + dm_interface_t *interface = celix_arrayList_get(component->providedInterfaces, i); - if (interface->properties != NULL) { + if (interface->properties != NULL) { celix_properties_destroy(interface->properties); - } - free(interface->serviceName); + } + free(interface->serviceName); free(interface); - } + } celix_arrayList_destroy(component->providedInterfaces); - for (int i = 0; i < celix_arrayList_size(component->dependencies); ++i) { - celix_dm_service_dependency_t* dep = celix_arrayList_get(component->dependencies, i); - celix_dmServiceDependency_destroy(dep); - } - celix_arrayList_destroy(component->dependencies); - celixThreadMutex_destroy(&component->mutex); + for (int i = 0; i < celix_arrayList_size(component->dependencies); ++i) { + celix_dm_service_dependency_t* dep = celix_arrayList_get(component->dependencies, i); + celix_dmServiceDependency_destroy(dep); + } + celix_arrayList_destroy(component->dependencies); + celixThreadMutex_destroy(&component->mutex); - free(component); + free(component); } } + +const char* celix_dmComponent_getUUID(celix_dm_component_t* cmp) { + return cmp->uuid; +} + celix_status_t component_addServiceDependency(celix_dm_component_t *component, celix_dm_service_dependency_t *dep) { return celix_dmComponent_addServiceDependency(component, dep); } @@ -171,17 +188,13 @@ celix_status_t celix_dmComponent_addServiceDependency(celix_dm_component_t *comp celixThreadMutex_lock(&component->mutex); arrayList_add(component->dependencies, dep); bool startDep = component->state != DM_CMP_STATE_INACTIVE; - - - celixThreadMutex_unlock(&component->mutex); - if (startDep) { //TODO race condition, fix with asyn branch -> async track services + if (startDep) { celix_serviceDependency_start(dep); } - celixThreadMutex_lock(&component->mutex); - component_handleChange(component); celixThreadMutex_unlock(&component->mutex); + component_handleChange(component); return status; } @@ -190,16 +203,13 @@ celix_status_t celix_dmComponent_removeServiceDependency(celix_dm_component_t *c celixThreadMutex_lock(&component->mutex); arrayList_removeElement(component->dependencies, dep); bool stopDependency = component->state != DM_CMP_STATE_INACTIVE; - - celixThreadMutex_unlock(&component->mutex); - if (stopDependency) { //TODO race condition, fix with asyn branch -> async stop track services + if (stopDependency) { celix_serviceDependency_stop(dep); } celix_dmServiceDependency_destroy(dep); - celixThreadMutex_lock(&component->mutex); + celixThreadMutex_unlock(&component->mutex); component_handleChange(component); - celixThreadMutex_unlock(&component->mutex); return CELIX_SUCCESS; } @@ -235,19 +245,19 @@ celix_status_t celix_private_dmComponent_start(celix_dm_component_t *component) celixThreadMutex_lock(&component->mutex); if (!component->isStarted) { component->isStarted = true; - component_handleChange(component); } celixThreadMutex_unlock(&component->mutex); + component_handleChange(component); return CELIX_SUCCESS; } -celix_status_t celix_private_dmComponent_stop(celix_dm_component_t *component) { +static celix_status_t celix_dmComponent_stop(celix_dm_component_t *component) { celixThreadMutex_lock(&component->mutex); if (component->isStarted) { component->isStarted = false; - component_handleChange(component); } celixThreadMutex_unlock(&component->mutex); + component_handleChange(component); return CELIX_SUCCESS; } @@ -406,14 +416,14 @@ static celix_status_t component_handleAdd(celix_dm_component_t *component, const celix_serviceDependency_invokeAdd(event->dep, event->svc, event->props); break; } - component_handleChange(component); celixThreadMutex_unlock(&component->mutex); + component_handleChange(component); return CELIX_SUCCESS; } static celix_status_t component_handleRemove(celix_dm_component_t *component, const celix_dm_event_t* event) { - celixThreadMutex_lock(&component->mutex); component_handleChange(component); + celixThreadMutex_lock(&component->mutex); switch (component->state) { case DM_CMP_STATE_TRACKING_OPTIONAL: if (celix_serviceDependency_hasRemoveCallback(event->dep)) { //if to prevent unneeded suspends @@ -432,11 +442,11 @@ static celix_status_t component_handleRemove(celix_dm_component_t *component, co static celix_status_t component_handleSet(celix_dm_component_t *component, const celix_dm_event_t* event) { - celixThreadMutex_lock(&component->mutex); if (event->svc == NULL) { //note set with removes a service -> update state first component_handleChange(component); } + celixThreadMutex_lock(&component->mutex); switch (component->state) { case DM_CMP_STATE_TRACKING_OPTIONAL: if (celix_serviceDependency_hasSetCallback(event->dep)) { //if to prevent unneeded suspends @@ -449,10 +459,10 @@ static celix_status_t component_handleSet(celix_dm_component_t *component, const celix_serviceDependency_invokeSet(event->dep, event->svc, event->props); break; } + celixThreadMutex_unlock(&component->mutex); if (event->svc != NULL) { component_handleChange(component); } - celixThreadMutex_unlock(&component->mutex); return CELIX_SUCCESS; } @@ -462,10 +472,8 @@ static celix_status_t component_handleSet(celix_dm_component_t *component, const static celix_status_t component_startDependencies(celix_dm_component_t *component) { for (int i = 0; i < celix_arrayList_size(component->dependencies); i++) { celix_dm_service_dependency_t *dependency = arrayList_get(component->dependencies, i); - if (!celix_dmServiceDependency_isStarted(dependency)) { - celixThreadMutex_unlock(&component->mutex); - celix_serviceDependency_start(dependency); //TODO race condition. unlock/lock can be removed with async branch -> async startServiceTracker - celixThreadMutex_lock(&component->mutex); + if (!celix_dmServiceDependency_isTrackerOpen(dependency)) { + celix_serviceDependency_start(dependency); } } return CELIX_SUCCESS; @@ -477,28 +485,28 @@ static celix_status_t component_startDependencies(celix_dm_component_t *componen static celix_status_t component_stopDependencies(celix_dm_component_t *component) { for (int i = 0; i < celix_arrayList_size(component->dependencies); i++) { celix_dm_service_dependency_t *dependency = arrayList_get(component->dependencies, i); - if (celix_dmServiceDependency_isStarted(dependency)) { - celixThreadMutex_unlock(&component->mutex); - celix_serviceDependency_stop(dependency); //TODO race condition. unlock/lock can be removed with async branch -> async stopServiceTracker - celixThreadMutex_lock(&component->mutex); + if (celix_dmServiceDependency_isTrackerOpen(dependency)) { + celix_serviceDependency_stop(dependency); } } return CELIX_SUCCESS; } + /** * Calculate and handle state change. This call should be called with the component->mutex locked. */ -static celix_status_t component_handleChange(celix_dm_component_t *component) { - celix_status_t status = CELIX_SUCCESS; +static void component_handleChangeOnEventThread(void *data) { + celix_dm_component_t* component = data; + assert(celix_framework_isCurrentThreadTheEventLoop(component->context->framework)); + celixThreadMutex_lock(&component->mutex); celix_dm_component_state_t oldState; celix_dm_component_state_t newState; - bool transition = false; do { oldState = component->state; - status = component_calculateNewState(component, oldState, &newState); + celix_status_t status = component_calculateNewState(component, oldState, &newState); if (status == CELIX_SUCCESS) { status = component_performTransition(component, oldState, newState, &transition); component->state = newState; @@ -508,10 +516,44 @@ static celix_status_t component_handleChange(celix_dm_component_t *component) { break; } } while (transition); + celixThreadMutex_unlock(&component->mutex); +} - return status; +static celix_status_t component_handleChange(celix_dm_component_t *component) { + if (celix_framework_isCurrentThreadTheEventLoop(component->context->framework)) { + component_handleChangeOnEventThread(component); + } else { + long eventId = celix_framework_fireGenericEvent( + component->context->framework, + -1, + celix_bundle_getId(component->context->bundle), + "dm component handle change", + component, + component_handleChangeOnEventThread, + NULL, + NULL); + celix_framework_waitForGenericEvent(component->context->framework, eventId); + } + return CELIX_SUCCESS; } + +///** +// * Check if service trackers are still open for the dependencies. +// * This call should be called with the component->mutex locked. +// */ +//static bool component_allDependencyStopped(celix_dm_component_t* component) { +// bool anyOpen = false; +// for (int i = 0; i < celix_arrayList_size(component->dependencies); ++i) { +// celix_dm_service_dependency_t *dep = celix_arrayList_get(component->dependencies, i); +// if (celix_dmServiceDependency_isTrackerOpen(dep)) { +// anyOpen = true; +// break; +// } +// } +// return !anyOpen; +//} + /** * Calculate possible state change. This call should be called with the component->mutex locked. */ @@ -565,7 +607,6 @@ static celix_status_t component_calculateNewState(celix_dm_component_t *componen */ static celix_status_t component_performTransition(celix_dm_component_t *component, celix_dm_component_state_t oldState, celix_dm_component_state_t newState, bool *transition) { celix_status_t status = CELIX_SUCCESS; - //TODO improve log (via bundle context?) fw_log(component->context->framework->logger, CELIX_LOG_LEVEL_TRACE, "performing transition for component %s from state %i to state %i\n", component->name, oldState, newState); if (oldState == newState) { @@ -591,9 +632,9 @@ static celix_status_t component_performTransition(celix_dm_component_t *componen } *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); - } + if (component->callbackDeinit) { + status = component->callbackDeinit(component->implementation); + } *transition = true; } else if (oldState == DM_CMP_STATE_WAITING_FOR_REQUIRED && newState == DM_CMP_STATE_INACTIVE) { component_stopDependencies(component); @@ -610,10 +651,14 @@ static bool component_areAllRequiredServiceDependenciesResolved(celix_dm_compone bool allResolved = true; for (int i = 0; i < celix_arrayList_size(component->dependencies); i++) { celix_dm_service_dependency_t *dependency = celix_arrayList_get(component->dependencies, i); - bool started = celix_dmServiceDependency_isStarted(dependency); + bool started = celix_dmServiceDependency_isTrackerOpen(dependency); bool required = celix_dmServiceDependency_isRequired(dependency); bool available = celix_serviceDependency_isAvailable(dependency); - if (started && required && !available) { + if (!started) { + allResolved = false; + break; + } + if (required && !available) { allResolved = false; break; } @@ -634,13 +679,13 @@ static celix_status_t component_registerServices(celix_dm_component_t *component opts.svc = (void*)interface->service; opts.serviceName = interface->serviceName; opts.serviceLanguage = celix_properties_get(regProps, CELIX_FRAMEWORK_SERVICE_LANGUAGE, NULL); - interface->svcId = 99999999; //TODO remove, not needed when using async svc registration - celixThreadMutex_unlock(&component->mutex); - long svcId = celix_bundleContext_registerServiceWithOptions(component->context, &opts); //TODO fix race condition with async branch -> registerAsync - celixThreadMutex_lock(&component->mutex); - interface->svcId = svcId; + interface->svcId = celix_bundleContext_registerServiceWithOptionsAsync(component->context, &opts); + if (!celix_framework_isCurrentThreadTheEventLoop(component->context->framework)) { + celix_framework_waitForAsyncRegistration(component->context->framework, interface->svcId); + } } } + return CELIX_SUCCESS; } @@ -650,15 +695,20 @@ static celix_status_t component_registerServices(celix_dm_component_t *component static celix_status_t component_unregisterServices(celix_dm_component_t *component) { celix_status_t status = CELIX_SUCCESS; + celix_array_list_t* ids = celix_arrayList_create(); for (int i = 0; i < celix_arrayList_size(component->providedInterfaces); ++i) { dm_interface_t *interface = arrayList_get(component->providedInterfaces, i); - long svcId = interface->svcId; + interface->unregistering = true; interface->svcId = -1L; - celixThreadMutex_unlock(&component->mutex); - celix_bundleContext_unregisterService(component->context, svcId); //TODO fix race condition with async branch -> unregister async - celixThreadMutex_lock(&component->mutex); } + celixThreadMutex_unlock(&component->mutex); + for (int i = 0; i < celix_arrayList_size(ids); ++i) { + long svcId = celix_arrayList_getLong(ids, i); + celix_bundleContext_unregisterService(component->context, svcId); //TODO make async + } + celixThreadMutex_lock(&component->mutex); + celix_arrayList_destroy(ids); return status; } diff --git a/libs/framework/src/dm_component_impl.h b/libs/framework/src/dm_component_impl.h index 897b0bc..452f89f 100644 --- a/libs/framework/src/dm_component_impl.h +++ b/libs/framework/src/dm_component_impl.h @@ -36,9 +36,6 @@ extern "C" { #include "celix_dm_event.h" celix_status_t celix_private_dmComponent_start(celix_dm_component_t *component); - -celix_status_t celix_private_dmComponent_stop(celix_dm_component_t *component); - celix_status_t celix_private_dmComponent_handleEvent(celix_dm_component_t *component, const celix_dm_event_t* event); #ifdef __cplusplus diff --git a/libs/framework/src/dm_dependency_manager_impl.c b/libs/framework/src/dm_dependency_manager_impl.c index 81f5cbb..5073072 100644 --- a/libs/framework/src/dm_dependency_manager_impl.c +++ b/libs/framework/src/dm_dependency_manager_impl.c @@ -77,9 +77,7 @@ celix_status_t celix_dependencyManager_remove(celix_dependency_manager_t *manage if (index >= 0) { celix_arrayList_removeAt(manager->components, index); celixThreadMutex_unlock(&manager->mutex); - - status = celix_private_dmComponent_stop(component); - component_destroy(component); + celix_dmComponent_destroy(component); } else { celixThreadMutex_unlock(&manager->mutex); fprintf(stderr, "Cannot find component with pointer %p\n", component); @@ -106,8 +104,7 @@ celix_status_t celix_dependencyManager_removeAllComponents(celix_dependency_mana while (!arrayList_isEmpty(toRemoveComponents)) { celix_dm_component_t *cmp = celix_arrayList_get(toRemoveComponents, 0); celix_arrayList_removeAt(toRemoveComponents, 0); - celix_private_dmComponent_stop(cmp); - component_destroy(cmp); + celix_dmComponent_destroy(cmp); } celix_arrayList_destroy(toRemoveComponents); diff --git a/libs/framework/src/dm_service_dependency.c b/libs/framework/src/dm_service_dependency.c index 5b33261..5cca374 100644 --- a/libs/framework/src/dm_service_dependency.c +++ b/libs/framework/src/dm_service_dependency.c @@ -60,6 +60,9 @@ celix_status_t serviceDependency_destroy(celix_dm_service_dependency_t **depende void celix_dmServiceDependency_destroy(celix_dm_service_dependency_t *dep) { if (dep != NULL) { + celix_bundle_context_t* ctx = celix_dmComponent_getBundleContext(dep->component); + celix_bundleContext_waitForAsyncStopTracker(ctx, dep->svcTrackerId); + celixThreadMutex_destroy(&dep->mutex); free(dep->serviceName); free(dep->versionRange); free(dep->filter); @@ -192,11 +195,8 @@ celix_status_t celix_serviceDependency_start(celix_dm_service_dependency_t *depe } celixThreadMutex_lock(&dependency->mutex); - bool open = dependency->isTrackerOpen; - dependency->isTrackerOpen = true; - celixThreadMutex_unlock(&dependency->mutex); - - if (!open) { + if (!dependency->isTrackerOpen) { + dependency->isTrackerOpen = true; celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS; opts.filter.filter = dependency->filter; opts.filter.serviceName = dependency->serviceName; @@ -211,12 +211,9 @@ celix_status_t celix_serviceDependency_start(celix_dm_service_dependency_t *depe } else { opts.filter.ignoreServiceLanguage = true; } - long newTrackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts); //TODO async - - celixThreadMutex_lock(&dependency->mutex); - dependency->svcTrackerId = newTrackerId; - celixThreadMutex_unlock(&dependency->mutex); + dependency->svcTrackerId = celix_bundleContext_trackServicesWithOptionsAsync(ctx, &opts); } + celixThreadMutex_unlock(&dependency->mutex); return CELIX_SUCCESS; } @@ -225,16 +222,12 @@ celix_status_t celix_serviceDependency_stop(celix_dm_service_dependency_t *depen celix_bundle_context_t* ctx = celix_dmComponent_getBundleContext(dependency->component); celixThreadMutex_lock(&dependency->mutex); - long stopTrackerId = dependency->svcTrackerId; - dependency->svcTrackerId = -1l; bool open = dependency->isTrackerOpen; dependency->isTrackerOpen = false; - celixThreadMutex_unlock(&dependency->mutex); - - //TODO if async branch is available this can be done with the lock using a async stop service tracker call - if (open && stopTrackerId >= 0) { - celix_bundleContext_stopTracker(ctx, stopTrackerId); + if (open && dependency->svcTrackerId >= 0) { + celix_bundleContext_stopTrackerAsync(ctx, dependency->svcTrackerId, NULL, NULL); } + celixThreadMutex_unlock(&dependency->mutex); return CELIX_SUCCESS; } @@ -242,6 +235,13 @@ celix_status_t celix_serviceDependency_stop(celix_dm_service_dependency_t *depen static void serviceDependency_setServiceTrackerCallback(void *handle, void *svc, const celix_properties_t *props) { celix_dm_service_dependency_t* dependency = handle; + const char *uuid = celix_dmComponent_getUUID(dependency->component); + const char *svcCmpUUID = celix_properties_get(props, CELIX_DM_COMPONENT_UUID, NULL); + if (svcCmpUUID != NULL && strncmp(uuid, svcCmpUUID, DM_COMPONENT_MAX_ID_LENGTH) == 0) { + fprintf(stderr, "TODO warning: ignoring svc of own component\n"); //TODO + return; + } + celix_dm_event_t event; event.dep = dependency; event.eventType = CELIX_DM_EVENT_SVC_SET; @@ -263,6 +263,13 @@ celix_status_t celix_serviceDependency_invokeSet(celix_dm_service_dependency_t * static void serviceDependency_addServiceTrackerCallback(void *handle, void *svc, const celix_properties_t *props) { celix_dm_service_dependency_t* dependency = handle; + const char *uuid = celix_dmComponent_getUUID(dependency->component); + const char *svcCmpUUID = celix_properties_get(props, CELIX_DM_COMPONENT_UUID, NULL); + if (svcCmpUUID != NULL && strncmp(uuid, svcCmpUUID, DM_COMPONENT_MAX_ID_LENGTH) == 0) { + fprintf(stderr, "TODO warning: ignoring svc of own component\n"); //TODO + return; + } + celixThreadMutex_lock(&dependency->mutex); dependency->trackedSvcCount += 1; celixThreadMutex_unlock(&dependency->mutex); @@ -288,6 +295,13 @@ celix_status_t celix_serviceDependency_invokeAdd(celix_dm_service_dependency_t * static void serviceDependency_removeServiceTrackerCallback(void *handle, void *svc, const celix_properties_t *props) { celix_dm_service_dependency_t* dependency = handle; + const char *uuid = celix_dmComponent_getUUID(dependency->component); + const char *svcCmpUUID = celix_properties_get(props, CELIX_DM_COMPONENT_UUID, NULL); + if (svcCmpUUID != NULL && strncmp(uuid, svcCmpUUID, DM_COMPONENT_MAX_ID_LENGTH) == 0) { + fprintf(stderr, "TODO warning: ignoring svc of own component\n"); //TODO + return; + } + celixThreadMutex_lock(&dependency->mutex); dependency->trackedSvcCount -= 1; celixThreadMutex_unlock(&dependency->mutex); @@ -334,7 +348,7 @@ bool celix_dmServiceDependency_isRequired(const celix_dm_service_dependency_t* d return dep->required; } -bool celix_dmServiceDependency_isStarted(celix_dm_service_dependency_t* dependency) { +bool celix_dmServiceDependency_isTrackerOpen(celix_dm_service_dependency_t* dependency) { celixThreadMutex_lock(&dependency->mutex); bool started = dependency->isTrackerOpen; celixThreadMutex_unlock(&dependency->mutex); diff --git a/libs/framework/src/dm_service_dependency_impl.h b/libs/framework/src/dm_service_dependency_impl.h index bab5d7c..a946739 100644 --- a/libs/framework/src/dm_service_dependency_impl.h +++ b/libs/framework/src/dm_service_dependency_impl.h @@ -79,7 +79,7 @@ bool celix_serviceDependency_hasRemoveCallback(const celix_dm_service_dependency bool celix_serviceDependency_isAvailable(celix_dm_service_dependency_t *dependency); bool celix_dmServiceDependency_isRequired(const celix_dm_service_dependency_t* dependency); -bool celix_dmServiceDependency_isStarted(celix_dm_service_dependency_t* dependency); +bool celix_dmServiceDependency_isTrackerOpen(celix_dm_service_dependency_t* dependency); #ifdef __cplusplus } diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c index 1cf3e83..59013c2 100644 --- a/libs/framework/src/framework.c +++ b/libs/framework/src/framework.c @@ -70,14 +70,13 @@ static inline celix_framework_bundle_entry_t* fw_bundleEntry_create(celix_bundle static inline void fw_bundleEntry_waitTillUseCountIs(celix_framework_bundle_entry_t *entry, size_t desiredUseCount) { celixThreadMutex_lock(&entry->useMutex); time_t start = time(NULL); - bool warningPrinted = false; while (entry->useCount != desiredUseCount) { celixThreadCondition_timedwaitRelative(&entry->useCond, &entry->useMutex, 5, 0); if (entry->useCount != desiredUseCount) { time_t now = time(NULL); - if (!warningPrinted && (now-start) > 5) { - fw_log(celix_frameworkLogger_globalLogger(), CELIX_LOG_LEVEL_WARNING, "Bundle %s (%li) still in use. Use count is %u, desired is %li", celix_bundle_getSymbolicName(entry->bnd), entry->bndId, entry->useCount, desiredUseCount); - warningPrinted = true; + if ((now-start) > 5) { + fw_log(celix_frameworkLogger_globalLogger(), CELIX_LOG_LEVEL_WARNING, "Bundle '%s' (bnd id = %li) still in use. Use count is %u, desired is %li", celix_bundle_getSymbolicName(entry->bnd), entry->bndId, entry->useCount, desiredUseCount); + start = time(NULL); } } }