This is an automated email from the ASF dual-hosted git repository.

pnoltes pushed a commit to branch feature/async_svc_registration
in repository https://gitbox.apache.org/repos/asf/celix.git

commit a576a90565b0ac8701d9d61346e8bf778186c3d4
Author: Pepijn Noltes <[email protected]>
AuthorDate: Mon Sep 7 16:26:45 2020 +0200

    Added async svc regitration usage to log_admin
---
 bundles/logging/log_admin/src/celix_log_admin.c    | 45 ++++++++++------------
 .../gtest/src/bundle_context_services_test.cpp     |  2 +-
 libs/framework/include/celix_bundle_context.h      |  8 +++-
 libs/framework/include/celix_framework.h           |  6 +++
 libs/framework/src/bundle_context.c                | 10 +++--
 libs/framework/src/framework.c                     | 30 +++++++++++++++
 6 files changed, 72 insertions(+), 29 deletions(-)

diff --git a/bundles/logging/log_admin/src/celix_log_admin.c 
b/bundles/logging/log_admin/src/celix_log_admin.c
index e594abc..805233b 100644
--- a/bundles/logging/log_admin/src/celix_log_admin.c
+++ b/bundles/logging/log_admin/src/celix_log_admin.c
@@ -210,7 +210,7 @@ static void 
celix_logAdmin_addLogSvcForName(celix_log_admin_t* admin, const char
             opts.serviceVersion = CELIX_LOG_SERVICE_VERSION;
             opts.properties = props;
             opts.svc = &newEntry->logSvc;
-            newEntry->logSvcId = 
celix_bundleContext_registerServiceAsyncWithOptions(admin->ctx, &opts);
+            newEntry->logSvcId = 
celix_bundleContext_registerServiceWithOptionsAsync(admin->ctx, &opts);
         }
 
         if (celix_utils_stringEquals(newEntry->name, 
CELIX_LOG_ADMIN_FRAMEWORK_LOG_NAME)) {
@@ -232,31 +232,28 @@ static void celix_logAdmin_trackerAdd(void *handle, const 
celix_service_tracker_
     celix_logAdmin_addLogSvcForName(admin, name);
 }
 
-static void celix_logAdmin_remLogSvcForName(celix_log_admin_t* admin, const 
char* name) {
-    celix_log_service_entry_t* remEntry = NULL;
+static void celix_logAdmin_freeLogEntry(void *data) {
+    celix_log_service_entry_t* entry = data;
+    if (celix_utils_stringEquals(entry->name, 
CELIX_LOG_ADMIN_FRAMEWORK_LOG_NAME)) {
+        celix_framework_t* fw = 
celix_bundleContext_getFramework(entry->admin->ctx);
+        celix_framework_setLogCallback(fw, NULL, NULL);
+    }
+    free(entry->name);
+    free(entry);
+}
 
+static void celix_logAdmin_remLogSvcForName(celix_log_admin_t* admin, const 
char* name) {
     celixThreadRwlock_writeLock(&admin->lock);
     celix_log_service_entry_t* found = hashMap_get(admin->loggers, name);
     if (found != NULL) {
         found->count -= 1;
         if (found->count == 0) {
             //remove
-            remEntry = found;
             hashMap_remove(admin->loggers, name);
+            celix_bundleContext_unregisterServiceAsync(admin->ctx, 
found->logSvcId, found, celix_logAdmin_freeLogEntry);
         }
     }
     celixThreadRwlock_unlock(&admin->lock);
-
-    if (remEntry != NULL) {
-        if (celix_utils_stringEquals(remEntry->name, 
CELIX_LOG_ADMIN_FRAMEWORK_LOG_NAME)) {
-            celix_framework_t* fw = 
celix_bundleContext_getFramework(admin->ctx);
-            celix_framework_setLogCallback(fw, NULL, NULL);
-        }
-
-        celix_bundleContext_unregisterService(admin->ctx, remEntry->logSvcId);
-        free(remEntry->name);
-        free(remEntry);
-    }
 }
 
 
@@ -591,10 +588,10 @@ celix_log_admin_t* 
celix_logAdmin_create(celix_bundle_context_t *ctx) {
         opts.callbackHandle = admin;
         opts.addWithProperties = celix_logAdmin_addSink;
         opts.removeWithProperties = celix_logAdmin_remSink;
-        admin->logWriterTrackerId = 
celix_bundleContext_trackServicesWithOptions(ctx, &opts);
+        admin->logWriterTrackerId = 
celix_bundleContext_trackServicesWithOptionsAsync(ctx, &opts);
     }
 
-    admin->logServiceMetaTrackerId = 
celix_bundleContext_trackServiceTrackers(ctx, CELIX_LOG_SERVICE_NAME, admin, 
celix_logAdmin_trackerAdd, celix_logAdmin_trackerRem);
+    admin->logServiceMetaTrackerId = 
celix_bundleContext_trackServiceTrackersAsync(ctx, CELIX_LOG_SERVICE_NAME, 
admin, celix_logAdmin_trackerAdd, celix_logAdmin_trackerRem, NULL, NULL);
 
     {
         admin->controlSvc.handle = admin;
@@ -612,7 +609,7 @@ celix_log_admin_t* 
celix_logAdmin_create(celix_bundle_context_t *ctx) {
         opts.serviceName = CELIX_LOG_CONTROL_NAME;
         opts.serviceVersion = CELIX_LOG_CONTROL_VERSION;
         opts.svc = &admin->controlSvc;
-        admin->controlSvcId = 
celix_bundleContext_registerServiceWithOptions(ctx, &opts);
+        admin->controlSvcId = 
celix_bundleContext_registerServiceWithOptionsAsync(ctx, &opts);
     }
 
     {
@@ -629,12 +626,11 @@ celix_log_admin_t* 
celix_logAdmin_create(celix_bundle_context_t *ctx) {
         opts.serviceVersion = CELIX_SHELL_COMMAND_SERVICE_VERSION;
         opts.properties = props;
         opts.svc = &admin->cmdSvc;
-        admin->cmdSvcId = celix_bundleContext_registerServiceWithOptions(ctx, 
&opts);
+        admin->cmdSvcId = 
celix_bundleContext_registerServiceWithOptionsAsync(ctx, &opts);
     }
 
     //add log service for the framework
     celix_logAdmin_addLogSvcForName(admin, CELIX_LOG_ADMIN_FRAMEWORK_LOG_NAME);
-
     return admin;
 }
 
@@ -642,10 +638,11 @@ void celix_logAdmin_destroy(celix_log_admin_t *admin) {
     if (admin != NULL) {
         celix_logAdmin_remLogSvcForName(admin, 
CELIX_LOG_ADMIN_FRAMEWORK_LOG_NAME);
 
-        celix_bundleContext_unregisterService(admin->ctx, admin->cmdSvcId);
-        celix_bundleContext_unregisterService(admin->ctx, admin->controlSvcId);
-        celix_bundleContext_stopTracker(admin->ctx, 
admin->logServiceMetaTrackerId);
-        celix_bundleContext_stopTracker(admin->ctx, admin->logWriterTrackerId);
+        celix_bundleContext_unregisterServiceAsync(admin->ctx, 
admin->cmdSvcId, NULL, NULL);
+        celix_bundleContext_unregisterServiceAsync(admin->ctx, 
admin->controlSvcId, NULL, NULL);
+        celix_bundleContext_stopTrackerAsync(admin->ctx, 
admin->logServiceMetaTrackerId, NULL, NULL);
+        celix_bundleContext_stopTrackerAsync(admin->ctx, 
admin->logWriterTrackerId, NULL, NULL);
+        celix_bundleContext_waitForEvents(admin->ctx);
 
         assert(hashMap_size(admin->loggers) == 0); //note stopping service 
tracker tracker should triggered all needed remove events
         hashMap_destroy(admin->loggers, false, false);
diff --git a/libs/framework/gtest/src/bundle_context_services_test.cpp 
b/libs/framework/gtest/src/bundle_context_services_test.cpp
index 96ba33c..9e5335f 100644
--- a/libs/framework/gtest/src/bundle_context_services_test.cpp
+++ b/libs/framework/gtest/src/bundle_context_services_test.cpp
@@ -1052,7 +1052,7 @@ TEST_F(CelixBundleContextServicesTests, 
floodEventLoopTest) {
         localData->cond.wait_for(lck, std::chrono::seconds{30}, [&]{ return 
localData->ready; }); //wait til ready.
         EXPECT_TRUE(localData->ready);
     };
-    long svcId = celix_bundleContext_registerServiceAsyncWithOptions(ctx, 
&opts);
+    long svcId = celix_bundleContext_registerServiceWithOptionsAsync(ctx, 
&opts);
     EXPECT_GE(svcId, 0);
 
     int nrOfAdditionalRegistrations = 300;
diff --git a/libs/framework/include/celix_bundle_context.h 
b/libs/framework/include/celix_bundle_context.h
index 90f733c..060a749 100644
--- a/libs/framework/include/celix_bundle_context.h
+++ b/libs/framework/include/celix_bundle_context.h
@@ -204,7 +204,7 @@ typedef struct celix_service_registration_options {
  * @param opts The pointer to the registration options. The options are only 
in the during registration call.
  * @return The serviceId (>= 0) or -1 if the registration was unsuccessful and 
-2 if the registration was cancelled (@see celix_bundleContext_reserveSvcId).
  */
-long 
celix_bundleContext_registerServiceAsyncWithOptions(celix_bundle_context_t 
*ctx, const celix_service_registration_options_t *opts);
+long 
celix_bundleContext_registerServiceWithOptionsAsync(celix_bundle_context_t 
*ctx, const celix_service_registration_options_t *opts);
 
 /**
  * Register a service to the Celix framework using the provided service 
registration options.
@@ -1109,6 +1109,12 @@ celix_dependency_manager_t* 
celix_bundleContext_getDependencyManager(celix_bundl
 
 
 /**
+ * Wait till there are event for the bundle of this bundle context.
+ */
+void celix_bundleContext_waitForEvents(celix_bundle_context_t* ctx);
+
+
+/**
  * Returns the bundle for this bundle context.
  */
 celix_bundle_t* celix_bundleContext_getBundle(const celix_bundle_context_t 
*ctx);
diff --git a/libs/framework/include/celix_framework.h 
b/libs/framework/include/celix_framework.h
index 7af1e2c..8b5482f 100644
--- a/libs/framework/include/celix_framework.h
+++ b/libs/framework/include/celix_framework.h
@@ -156,6 +156,12 @@ void 
celix_framework_waitForEmptyEventQueue(celix_framework_t *fw);
 void celix_framework_setLogCallback(celix_framework_t* fw, void* logHandle, 
void (*logFunction)(void* handle, celix_log_level_e level, const char* file, 
const char *function, int line, const char *format, va_list formatArgs));
 
 
+/**
+ * wait till all events for the bundle identified by the bndId are processed.
+ */
+void celix_framework_waitForEvents(celix_framework_t* fw, long bndId);
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libs/framework/src/bundle_context.c 
b/libs/framework/src/bundle_context.c
index 43a11cd..70aa37c 100644
--- a/libs/framework/src/bundle_context.c
+++ b/libs/framework/src/bundle_context.c
@@ -457,7 +457,7 @@ long 
celix_bundleContext_registerServiceAsync(celix_bundle_context_t *ctx, void
     opts.svc = svc;
     opts.serviceName = serviceName;
     opts.properties = properties;
-    return celix_bundleContext_registerServiceAsyncWithOptions(ctx, &opts);
+    return celix_bundleContext_registerServiceWithOptionsAsync(ctx, &opts);
 }
 
 long celix_bundleContext_registerService(bundle_context_t *ctx, void *svc, 
const char *serviceName, celix_properties_t *properties) {
@@ -474,7 +474,7 @@ long 
celix_bundleContext_registerServiceFactoryAsync(celix_bundle_context_t *ctx
     opts.factory = factory;
     opts.serviceName = serviceName;
     opts.properties = props;
-    return celix_bundleContext_registerServiceAsyncWithOptions(ctx, &opts);
+    return celix_bundleContext_registerServiceWithOptionsAsync(ctx, &opts);
 }
 
 long celix_bundleContext_registerServiceFactory(celix_bundle_context_t *ctx, 
celix_service_factory_t *factory, const char *serviceName, celix_properties_t 
*props) {
@@ -547,7 +547,7 @@ long 
celix_bundleContext_registerServiceWithOptions(bundle_context_t *ctx, const
     return celix_bundleContext_registerServiceWithOptionsInternal(ctx, opts, 
false);
 }
 
-long 
celix_bundleContext_registerServiceAsyncWithOptions(celix_bundle_context_t 
*ctx, const celix_service_registration_options_t *opts) {
+long 
celix_bundleContext_registerServiceWithOptionsAsync(celix_bundle_context_t 
*ctx, const celix_service_registration_options_t *opts) {
     return celix_bundleContext_registerServiceWithOptionsInternal(ctx, opts, 
true);
 }
 
@@ -1484,6 +1484,10 @@ long celix_bundleContext_trackServiceTrackersAsync(
     return celix_bundleContext_trackServiceTrackersInternal(ctx, serviceName, 
callbackHandle, trackerAdd, trackerRemove, true, doneCallbackData, 
doneCallback);
 }
 
+void celix_bundleContext_waitForEvents(celix_bundle_context_t* ctx) {
+    celix_framework_waitForEvents(ctx->framework, 
celix_bundle_getId(ctx->bundle));
+}
+
 celix_bundle_t* celix_bundleContext_getBundle(const celix_bundle_context_t 
*ctx) {
     celix_bundle_t *bnd = NULL;
     if (ctx != NULL) {
diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c
index 84eaf67..de19f63 100644
--- a/libs/framework/src/framework.c
+++ b/libs/framework/src/framework.c
@@ -2640,6 +2640,36 @@ void 
celix_framework_waitForEmptyEventQueue(celix_framework_t *fw) {
     celixThreadMutex_unlock(&fw->dispatcher.mutex);
 }
 
+void celix_framework_waitForEvents(celix_framework_t* fw, long bndId) {
+    assert(!celix_framework_isCurrentThreadTheEventLoop(fw));
+
+    celixThreadMutex_lock(&fw->dispatcher.mutex);
+    bool eventInProgress = true;
+    while (eventInProgress) {
+        eventInProgress = false;
+        for (int i = 0; i < fw->dispatcher.eventQueueSize; ++i) {
+            int index = (fw->dispatcher.eventQueueFirstEntry + i) % 
CELIX_FRAMEWORK_STATIC_EVENT_QUEUE_SIZE;
+            celix_framework_event_t* e = &fw->dispatcher.eventQueue[index];
+            if (e->bndEntry != NULL && e->bndEntry->bndId == bndId) {
+                eventInProgress = true;
+                break;
+            }
+        }
+        for (int i = 0; !eventInProgress && i < 
celix_arrayList_size(fw->dispatcher.dynamicEventQueue); ++i) {
+            celix_framework_event_t* e = 
celix_arrayList_get(fw->dispatcher.dynamicEventQueue, i);
+            if (e->bndEntry != NULL && e->bndEntry->bndId == bndId) {
+                eventInProgress = true;
+                break;
+            }
+        }
+        if (eventInProgress) {
+            celixThreadCondition_timedwaitRelative(&fw->dispatcher.cond, 
&fw->dispatcher.mutex, 5, 0);
+        }
+    }
+    celixThreadMutex_unlock(&fw->dispatcher.mutex);
+}
+
+
 void celix_framework_setLogCallback(celix_framework_t* fw, void* logHandle, 
void (*logFunction)(void* handle, celix_log_level_e level, const char* file, 
const char *function, int line, const char *format, va_list formatArgs)) {
     celix_frameworkLogger_setLogCallback(fw->logger, logHandle, logFunction);
 }

Reply via email to