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);
             }
         }
     }

Reply via email to