You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2021/01/11 15:18:04 UTC
[celix] 05/08: Makes start and stop of service dependency tracker
and svc registration async
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 <pe...@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);
}
}
}