From 98f187b9e40a3f774b1767f68e117dbf8f786464 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Wed, 31 May 2023 16:55:34 +0800 Subject: [PATCH 01/21] Fix race condition introduced by celix_framework_installBundleInternal. --- libs/framework/src/bundle_context.c | 8 ++++- libs/framework/src/framework.c | 46 +++++++++++++------------- libs/framework/src/framework_private.h | 5 ++- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/libs/framework/src/bundle_context.c b/libs/framework/src/bundle_context.c index d5bb0540d..8a802b7c9 100644 --- a/libs/framework/src/bundle_context.c +++ b/libs/framework/src/bundle_context.c @@ -141,10 +141,16 @@ celix_status_t bundleContext_installBundle(bundle_context_pt context, const char } celix_status_t bundleContext_installBundle2(bundle_context_pt context, const char *location, const char *inputFile, bundle_pt *bundle) { + celix_status_t status = CELIX_SUCCESS; + long id = -1L; if (context == NULL || location == NULL || bundle == NULL) { return CELIX_ILLEGAL_ARGUMENT; } - return celix_framework_installBundleInternal(context->framework, location, bundle); + status = celix_framework_installBundleInternal(context->framework, location, &id); + if (status == CELIX_SUCCESS) { + *bundle = framework_getBundleById(context->framework, id); + } + return status; } celix_status_t bundleContext_registerService(bundle_context_pt context, const char * serviceName, const void * svcObj, diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c index f87c3432d..ca6cc4e18 100644 --- a/libs/framework/src/framework.c +++ b/libs/framework/src/framework.c @@ -525,10 +525,10 @@ static void framework_autoInstallConfiguredBundlesForList(celix_framework_t* fw, char *location = strtok_r(autoStart, delims, &save_ptr); while (location != NULL) { //first install - bundle_t *bnd = NULL; - if (celix_framework_installBundleInternal(fw, location, &bnd) == CELIX_SUCCESS) { + long id = -1L; + if (celix_framework_installBundleInternal(fw, location, &id) == CELIX_SUCCESS) { if (installedBundles) { - celix_arrayList_add(installedBundles, bnd); + celix_arrayList_addLong(installedBundles, id); } } else { fw_log(fw->logger, CELIX_LOG_LEVEL_ERROR, "Could not install bundle from location '%s'.", location); @@ -544,8 +544,8 @@ static void framework_autoInstallConfiguredBundlesForList(celix_framework_t* fw, static void framework_autoStartConfiguredBundlesForList(celix_framework_t* fw, const celix_array_list_t *installedBundles) { assert(!celix_framework_isCurrentThreadTheEventLoop(fw)); for (int i = 0; i < celix_arrayList_size(installedBundles); ++i) { - bundle_t *bnd = celix_arrayList_get(installedBundles, i); - long bndId = celix_bundle_getId(bnd); + long bndId = celix_arrayList_getLong(installedBundles, i); + bundle_t* bnd = framework_getBundleById(fw, bndId); if (celix_bundle_getState(bnd) != OSGI_FRAMEWORK_BUNDLE_ACTIVE) { bool started = celix_framework_startBundle(fw, bndId); if (!started) { @@ -620,9 +620,11 @@ bool celix_framework_getConfigPropertyAsBool(celix_framework_t* framework, const return result; } -celix_status_t celix_framework_installBundleInternal(celix_framework_t *framework, const char *bndLoc, celix_bundle_t **bundleOut) { +celix_status_t +celix_framework_installBundleInternal(celix_framework_t* framework, const char* bndLoc, long* bundleOut) { celix_status_t status = CELIX_SUCCESS; celix_bundle_t* bundle = NULL; + long id = -1L; bundle_state_e state = CELIX_BUNDLE_STATE_UNKNOWN; @@ -634,24 +636,24 @@ celix_status_t celix_framework_installBundleInternal(celix_framework_t *framewor //increase use count of framework bundle to prevent a stop. celix_framework_bundle_entry_t *fwBundleEntry = celix_framework_bundleEntry_getBundleEntryAndIncreaseUseCount(framework, framework->bundleId); - status = CELIX_DO_IF(status, bundle_getState(framework->bundle, &state)); - if (status == CELIX_SUCCESS) { + status = CELIX_DO_IF(status, bundle_getState(framework->bundle, &state)); + if (status == CELIX_SUCCESS) { if (state == CELIX_BUNDLE_STATE_STOPPING || state == CELIX_BUNDLE_STATE_UNINSTALLED) { fw_log(framework->logger, CELIX_LOG_LEVEL_INFO, "The framework is being shutdown"); status = CELIX_FRAMEWORK_SHUTDOWN; } - } + } if (status == CELIX_SUCCESS) { - bundle = framework_getBundle(framework, bndLoc); - if (bundle != NULL) { + id = framework_getBundle(framework, bndLoc); + if (id != -1L) { celix_framework_bundleEntry_decreaseUseCount(fwBundleEntry); - *bundleOut = bundle; + *bundleOut = id; return CELIX_SUCCESS; } long alreadyExistingBndId = celix_bundleCache_findBundleIdForLocation(framework->cache, bndLoc); - long id = alreadyExistingBndId == -1 ? framework_getNextBundleId(framework) : alreadyExistingBndId; + id = alreadyExistingBndId == -1 ? framework_getNextBundleId(framework) : alreadyExistingBndId; bundle_archive_t* archive = NULL; status = CELIX_DO_IF(status, celix_bundleCache_createArchive(framework->cache, id, bndLoc, &archive)); status = CELIX_DO_IF(status, celix_bundle_createFromArchive(framework, archive, &bundle)); @@ -667,14 +669,14 @@ celix_status_t celix_framework_installBundleInternal(celix_framework_t *framewor } if (status == CELIX_SUCCESS) { - *bundleOut = bundle; + *bundleOut = id; } else { fw_logCode(framework->logger, CELIX_LOG_LEVEL_ERROR, status, "Could not install bundle"); } celix_framework_bundleEntry_decreaseUseCount(fwBundleEntry); - return status; + return status; } bool celix_framework_isBundleAlreadyInstalled(celix_framework_t* fw, const char* bundleSymbolicName) { @@ -1112,8 +1114,8 @@ array_list_pt framework_getBundles(framework_pt framework) { return bundles; } -bundle_pt framework_getBundle(framework_pt framework, const char* location) { - bundle_t *bnd = NULL; +long framework_getBundle(framework_pt framework, const char* location) { + long id = -1L; celixThreadMutex_lock(&framework->installedBundles.mutex); int size = celix_arrayList_size(framework->installedBundles.entries); @@ -1122,13 +1124,13 @@ bundle_pt framework_getBundle(framework_pt framework, const char* location) { const char *loc = NULL; bundle_getBundleLocation(entry->bnd, &loc); if (loc != NULL && location != NULL && strncmp(loc, location, strlen(loc)) == 0) { - bnd = entry->bnd; + id = entry->bndId; break; } } celixThreadMutex_unlock(&framework->installedBundles.mutex); - return bnd; + return id; } celix_status_t framework_waitForStop(framework_pt framework) { @@ -1833,12 +1835,10 @@ static void celix_framework_waitForBundleEvents(celix_framework_t *fw, long bndI static long celix_framework_installAndStartBundleInternal(celix_framework_t *fw, const char *bundleLoc, bool autoStart, bool forcedAsync) { long bundleId = -1; - bundle_t *bnd = NULL; celix_status_t status = CELIX_SUCCESS; - if (celix_framework_installBundleInternal(fw, bundleLoc, &bnd) == CELIX_SUCCESS) { - status = bundle_getBundleId(bnd, &bundleId); - if (status == CELIX_SUCCESS && autoStart) { + if (celix_framework_installBundleInternal(fw, bundleLoc, &bundleId) == CELIX_SUCCESS) { + if (autoStart) { celix_framework_bundle_entry_t* bndEntry = celix_framework_bundleEntry_getBundleEntryAndIncreaseUseCount(fw, bundleId); if (bndEntry != NULL) { diff --git a/libs/framework/src/framework_private.h b/libs/framework/src/framework_private.h index 47b22c8bd..e1da35896 100644 --- a/libs/framework/src/framework_private.h +++ b/libs/framework/src/framework_private.h @@ -249,8 +249,7 @@ double celix_framework_getConfigPropertyAsDouble(celix_framework_t* framework, c */ bool celix_framework_getConfigPropertyAsBool(celix_framework_t* framework, const char* name, bool defaultValue, bool* found); - -celix_status_t celix_framework_installBundleInternal(celix_framework_t *framework, const char *bndLoc, celix_bundle_t **bundleOut); +celix_status_t celix_framework_installBundleInternal(celix_framework_t* framework, const char* bndLoc, long* bundleOut); celix_status_t fw_registerService(framework_pt framework, service_registration_pt * registration, long bundleId, const char* serviceName, const void* svcObj, properties_pt properties); celix_status_t fw_registerServiceFactory(framework_pt framework, service_registration_pt * registration, long bundleId, const char* serviceName, service_factory_pt factory, properties_pt properties); @@ -271,7 +270,7 @@ celix_status_t fw_removeFrameworkListener(framework_pt framework, bundle_pt bund celix_status_t framework_markResolvedModules(framework_pt framework, linked_list_pt wires); array_list_pt framework_getBundles(framework_pt framework) __attribute__((deprecated("not thread safe, use celix_framework_useBundles instead"))); -bundle_pt framework_getBundle(framework_pt framework, const char* location); +long framework_getBundle(framework_pt framework, const char* location); bundle_pt framework_getBundleById(framework_pt framework, long id); From 063593cd81e9e79f411f86bd00e62fa8b0fec3c2 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Thu, 1 Jun 2023 16:13:25 +0800 Subject: [PATCH 02/21] Use read-write-lock to protect bundle state transition. It fixes #561, an ABBA deadlock in test, and a potential double-free. --- .../pubsub/integration/gtest/tst_activator.c | 6 +- libs/framework/src/framework.c | 144 ++++++++++-------- libs/framework/src/framework_private.h | 1 + 3 files changed, 81 insertions(+), 70 deletions(-) diff --git a/bundles/pubsub/integration/gtest/tst_activator.c b/bundles/pubsub/integration/gtest/tst_activator.c index 4084d5f0f..c5d2c1905 100644 --- a/bundles/pubsub/integration/gtest/tst_activator.c +++ b/bundles/pubsub/integration/gtest/tst_activator.c @@ -55,7 +55,7 @@ celix_status_t bnd_start(struct activator *act, celix_bundle_context_t *ctx) { celix_properties_set(props, PUBSUB_SUBSCRIBER_TOPIC, "ping"); act->subSvc1.handle = act; act->subSvc1.receive = tst_receive; - act->subSvcId1 = celix_bundleContext_registerService(ctx, &act->subSvc1, PUBSUB_SUBSCRIBER_SERVICE_NAME, props); + act->subSvcId1 = celix_bundleContext_registerServiceAsync(ctx, &act->subSvc1, PUBSUB_SUBSCRIBER_SERVICE_NAME, props); } { @@ -63,13 +63,13 @@ celix_status_t bnd_start(struct activator *act, celix_bundle_context_t *ctx) { celix_properties_set(props, PUBSUB_SUBSCRIBER_TOPIC, "ping"); act->subSvc2.handle = act; act->subSvc2.receive = tst_receive2; - act->subSvcId2 = celix_bundleContext_registerService(ctx, &act->subSvc2, PUBSUB_SUBSCRIBER_SERVICE_NAME, props); + act->subSvcId2 = celix_bundleContext_registerServiceAsync(ctx, &act->subSvc2, PUBSUB_SUBSCRIBER_SERVICE_NAME, props); } { act->countSvc.handle = act; act->countSvc.receiveCount = tst_count; - act->countSvcId = celix_bundleContext_registerService(ctx, &act->countSvc, CELIX_RECEIVE_COUNT_SERVICE_NAME, NULL); + act->countSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->countSvc, CELIX_RECEIVE_COUNT_SERVICE_NAME, NULL); } return CELIX_SUCCESS; diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c index ca6cc4e18..93138d138 100644 --- a/libs/framework/src/framework.c +++ b/libs/framework/src/framework.c @@ -54,10 +54,12 @@ struct celix_bundle_activator { celix_bundle_activator_destroy_fp destroy; }; +static celix_status_t celix_framework_stopBundleEntryInternal(celix_framework_t* framework, celix_framework_bundle_entry_t* bndEntry); + static inline celix_framework_bundle_entry_t* fw_bundleEntry_create(celix_bundle_t *bnd) { celix_framework_bundle_entry_t *entry = calloc(1, sizeof(*entry)); entry->bnd = bnd; - + celixThreadRwlock_create(&entry->fsmMutex, NULL); entry->bndId = celix_bundle_getId(bnd); entry->useCount = 0; celixThreadMutex_create(&entry->useMutex, NULL); @@ -92,6 +94,7 @@ static inline void fw_bundleEntry_destroy(celix_framework_bundle_entry_t *entry, //destroy celixThreadMutex_destroy(&entry->useMutex); celixThreadCondition_destroy(&entry->useCond); + celixThreadRwlock_destroy(&entry->fsmMutex); free(entry); } @@ -139,14 +142,13 @@ bool celix_framework_isBundleIdAlreadyUsed(celix_framework_t *fw, long bndId) { return found; } -static inline celix_framework_bundle_entry_t* fw_bundleEntry_removeBundleEntryAndIncreaseUseCount(celix_framework_t *fw, long bndId) { - celix_framework_bundle_entry_t* found = NULL; +static inline bool fw_bundleEntry_removeBundleEntry(celix_framework_t *fw, celix_framework_bundle_entry_t* bndEntry) { + bool found = false; celixThreadMutex_lock(&fw->installedBundles.mutex); for (int i = 0; i < celix_arrayList_size(fw->installedBundles.entries); ++i) { celix_framework_bundle_entry_t *entry = celix_arrayList_get(fw->installedBundles.entries, i); - if (entry->bndId == bndId) { - found = entry; - celix_framework_bundleEntry_increaseUseCount(entry); + if (entry == bndEntry) { + found = true; celix_arrayList_removeAt(fw->installedBundles.entries, i); break; } @@ -1545,6 +1547,7 @@ bool celix_framework_useBundle(framework_t *fw, bool onlyActive, long bundleId, bundleId); if (entry != NULL) { + celixThreadRwlock_readLock(&entry->fsmMutex); celix_bundle_state_e bndState = celix_bundle_getState(entry->bnd); if (onlyActive && (bndState == CELIX_BUNDLE_STATE_ACTIVE || bndState == CELIX_BUNDLE_STATE_STARTING)) { use(callbackHandle, entry->bnd); @@ -1553,6 +1556,7 @@ bool celix_framework_useBundle(framework_t *fw, bool onlyActive, long bundleId, use(callbackHandle, entry->bnd); called = true; } + celixThreadRwlock_unlock(&entry->fsmMutex); celix_framework_bundleEntry_decreaseUseCount(entry); } else { framework_logIfError(fw->logger, CELIX_FRAMEWORK_EXCEPTION, NULL, "Bundle with id %li is not installed", bundleId); @@ -1886,53 +1890,52 @@ void celix_framework_uninstallBundleAsync(celix_framework_t *fw, long bndId) { celix_status_t celix_framework_uninstallBundleEntry(celix_framework_t* framework, celix_framework_bundle_entry_t* bndEntry) { assert(!celix_framework_isCurrentThreadTheEventLoop(framework)); + celixThreadRwlock_writeLock(&bndEntry->fsmMutex); + celix_bundle_state_e bndState = celix_bundle_getState(bndEntry->bnd); if (bndState == CELIX_BUNDLE_STATE_ACTIVE) { - celix_framework_stopBundleEntry(framework, bndEntry); + celix_framework_stopBundleEntryInternal(framework, bndEntry); } - celix_framework_bundle_entry_t* removedEntry = fw_bundleEntry_removeBundleEntryAndIncreaseUseCount(framework, bndEntry->bndId); + if (!fw_bundleEntry_removeBundleEntry(framework, bndEntry)) { + celixThreadRwlock_unlock(&bndEntry->fsmMutex); + celix_framework_bundleEntry_decreaseUseCount(bndEntry); + return CELIX_ILLEGAL_STATE; + } - celix_framework_bundleEntry_decreaseUseCount(bndEntry); - if (removedEntry != NULL) { - celix_status_t status = CELIX_SUCCESS; - celix_bundle_t *bnd = removedEntry->bnd; + celix_status_t status = CELIX_SUCCESS; + celix_bundle_t *bnd = bndEntry->bnd; + bundle_archive_t *archive = NULL; + bundle_revision_t *revision = NULL; + celix_module_t* module = NULL; + status = CELIX_DO_IF(status, bundle_getArchive(bnd, &archive)); + status = CELIX_DO_IF(status, bundleArchive_getCurrentRevision(archive, &revision)); + status = CELIX_DO_IF(status, bundle_getCurrentModule(bnd, &module)); - if (status == CELIX_SUCCESS) { - bundle_archive_t *archive = NULL; - bundle_revision_t *revision = NULL; - celix_module_t* module = NULL; - status = CELIX_DO_IF(status, bundle_getArchive(bnd, &archive)); - status = CELIX_DO_IF(status, bundleArchive_getCurrentRevision(archive, &revision)); - status = CELIX_DO_IF(status, bundle_getCurrentModule(bnd, &module)); - - if (module) { - celix_module_closeLibraries(module); - } + if (module) { + celix_module_closeLibraries(module); + } - CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_UNRESOLVED, removedEntry)); + CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_UNRESOLVED, bndEntry)); - status = CELIX_DO_IF(status, bundle_setState(bnd, CELIX_BUNDLE_STATE_UNINSTALLED)); + status = CELIX_DO_IF(status, bundle_setState(bnd, CELIX_BUNDLE_STATE_UNINSTALLED)); - CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_UNINSTALLED, removedEntry)); + CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_UNINSTALLED, bndEntry)); - //NOTE wait outside installedBundles.mutex - celix_framework_bundleEntry_decreaseUseCount(removedEntry); - fw_bundleEntry_destroy(removedEntry , true); //wait till use count is 0 -> e.g. not used + celixThreadRwlock_unlock(&bndEntry->fsmMutex); - if (status == CELIX_SUCCESS) { - celix_framework_waitForEmptyEventQueue(framework); //to ensure that the uninstall event is triggered and handled - bundleArchive_destroy(archive); - status = CELIX_DO_IF(status, bundle_closeModules(bnd)); - status = CELIX_DO_IF(status, bundle_destroy(bnd)); - } - } - framework_logIfError(framework->logger, status, "", "Cannot uninstall bundle"); - return status; + //NOTE wait outside installedBundles.mutex + celix_framework_bundleEntry_decreaseUseCount(bndEntry); + fw_bundleEntry_destroy(bndEntry, true); //wait till use count is 0 -> e.g. not used - } else { - return CELIX_ILLEGAL_STATE; + if (status == CELIX_SUCCESS) { + celix_framework_waitForEmptyEventQueue(framework); //to ensure that the uninstall event is triggered and handled + (void)bundle_closeModules(bnd); + (void)bundle_destroy(bnd); + (void)bundleArchive_destroy(archive); } + framework_logIfError(framework->logger, status, "", "Cannot uninstall bundle"); + return status; } static bool celix_framework_stopBundleInternal(celix_framework_t* fw, long bndId, bool forcedAsync) { @@ -1962,9 +1965,7 @@ void celix_framework_stopBundleAsync(celix_framework_t* fw, long bndId) { celix_framework_stopBundleInternal(fw, bndId, true); } -celix_status_t celix_framework_stopBundleEntry(celix_framework_t* framework, celix_framework_bundle_entry_t* bndEntry) { - assert(!celix_framework_isCurrentThreadTheEventLoop(framework)); - +static celix_status_t celix_framework_stopBundleEntryInternal(celix_framework_t* framework, celix_framework_bundle_entry_t* bndEntry) { celix_bundle_activator_t *activator = NULL; bundle_context_t *context = NULL; bool wasActive = false; @@ -1973,28 +1974,28 @@ celix_status_t celix_framework_stopBundleEntry(celix_framework_t* framework, cel celix_status_t status = CELIX_SUCCESS; celix_bundle_state_e state = celix_bundle_getState(bndEntry->bnd); switch (state) { - case CELIX_BUNDLE_STATE_UNKNOWN: - status = CELIX_ILLEGAL_STATE; - error = "state is unknown"; - break; - case CELIX_BUNDLE_STATE_UNINSTALLED: - status = CELIX_ILLEGAL_STATE; - error = "bundle is uninstalled"; - break; - case CELIX_BUNDLE_STATE_STARTING: - status = CELIX_BUNDLE_EXCEPTION; - error = "bundle is starting"; - break; - case CELIX_BUNDLE_STATE_STOPPING: - status = CELIX_BUNDLE_EXCEPTION; - error = "bundle is stopping"; - break; - case CELIX_BUNDLE_STATE_INSTALLED: - case CELIX_BUNDLE_STATE_RESOLVED: - break; - case CELIX_BUNDLE_STATE_ACTIVE: - wasActive = true; - break; + case CELIX_BUNDLE_STATE_UNKNOWN: + status = CELIX_ILLEGAL_STATE; + error = "state is unknown"; + break; + case CELIX_BUNDLE_STATE_UNINSTALLED: + status = CELIX_ILLEGAL_STATE; + error = "bundle is uninstalled"; + break; + case CELIX_BUNDLE_STATE_STARTING: + status = CELIX_BUNDLE_EXCEPTION; + error = "bundle is starting"; + break; + case CELIX_BUNDLE_STATE_STOPPING: + status = CELIX_BUNDLE_EXCEPTION; + error = "bundle is stopping"; + break; + case CELIX_BUNDLE_STATE_INSTALLED: + case CELIX_BUNDLE_STATE_RESOLVED: + break; + case CELIX_BUNDLE_STATE_ACTIVE: + wasActive = true; + break; } @@ -2069,7 +2070,15 @@ celix_status_t celix_framework_stopBundleEntry(celix_framework_t* framework, cel } else { fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_STOPPED, bndEntry); } + return status; +} +celix_status_t celix_framework_stopBundleEntry(celix_framework_t* framework, celix_framework_bundle_entry_t* bndEntry) { + celix_status_t status = CELIX_SUCCESS; + assert(!celix_framework_isCurrentThreadTheEventLoop(framework)); + celixThreadRwlock_writeLock(&bndEntry->fsmMutex); + status = celix_framework_stopBundleEntryInternal(framework, bndEntry); + celixThreadRwlock_unlock(&bndEntry->fsmMutex); return status; } @@ -2106,6 +2115,7 @@ celix_status_t celix_framework_startBundleEntry(celix_framework_t* framework, ce celix_bundle_context_t* context = NULL; celix_bundle_activator_t* activator = NULL; + celixThreadRwlock_writeLock(&bndEntry->fsmMutex); celix_bundle_state_e state = celix_bundle_getState(bndEntry->bnd); switch (state) { @@ -2133,7 +2143,7 @@ celix_status_t celix_framework_startBundleEntry(celix_framework_t* framework, ce if (!module_isResolved(module)) { wires = resolver_resolve(module); if (wires == NULL) { - celix_framework_bundleEntry_decreaseUseCount(bndEntry); + celixThreadRwlock_unlock(&bndEntry->fsmMutex); return CELIX_BUNDLE_EXCEPTION; } status = framework_markResolvedModules(framework, wires); @@ -2217,7 +2227,7 @@ celix_status_t celix_framework_startBundleEntry(celix_framework_t* framework, ce fw_logCode(framework->logger, CELIX_LOG_LEVEL_ERROR, status, "Could not start bundle: %s [%ld]", symbolicName, id); } } - + celixThreadRwlock_unlock(&bndEntry->fsmMutex); return status; } diff --git a/libs/framework/src/framework_private.h b/libs/framework/src/framework_private.h index e1da35896..3d98c3d8a 100644 --- a/libs/framework/src/framework_private.h +++ b/libs/framework/src/framework_private.h @@ -51,6 +51,7 @@ typedef struct celix_framework_bundle_entry { celix_bundle_t *bnd; + celix_thread_rwlock_t fsmMutex; //protects bundle state transition long bndId; celix_thread_mutex_t useMutex; //protects useCount From 73dac42f05e86d8e5974d14c2a66d5d8b6865c7c Mon Sep 17 00:00:00 2001 From: PengZheng Date: Thu, 1 Jun 2023 19:16:21 +0800 Subject: [PATCH 03/21] Implement OSGi uninstall, and make install/uninstall thread-safe. --- .../gtest/src/BundleArchiveTestSuite.cc | 27 +++++++++++-- .../src/CelixBundleContextBundlesTestSuite.cc | 40 +++++++++++++++++-- libs/framework/src/framework.c | 21 +++++++--- .../src/framework_bundle_lifecycle_handler.c | 4 +- libs/framework/src/framework_private.h | 4 +- 5 files changed, 81 insertions(+), 15 deletions(-) diff --git a/libs/framework/gtest/src/BundleArchiveTestSuite.cc b/libs/framework/gtest/src/BundleArchiveTestSuite.cc index 98b376a82..59cc1c1c5 100644 --- a/libs/framework/gtest/src/BundleArchiveTestSuite.cc +++ b/libs/framework/gtest/src/BundleArchiveTestSuite.cc @@ -74,8 +74,18 @@ TEST_F(CxxBundleArchiveTestSuite, BundleArchiveReusedTest) { auto firstBundleRevisionTime = installTime; lock.unlock(); - //uninstall and reinstall - ctx->uninstallBundle(bndId1); + tracker.reset(); + fw = celix::createFramework({ + {"CELIX_LOGGING_DEFAULT_ACTIVE_LOG_LEVEL", "trace"}, + {CELIX_FRAMEWORK_CLEAN_CACHE_DIR_ON_CREATE, "false"} + }); + ctx = fw->getFrameworkBundleContext(); + tracker = ctx->trackBundles() + .addOnInstallCallback([&](const celix::Bundle& b) { + std::lock_guard lock{m}; + auto *archive = celix_bundle_getArchive(b.getCBundle()); + EXPECT_EQ(CELIX_SUCCESS, celix_bundleArchive_getLastModified(archive, &installTime)); + }).build(); std::this_thread::sleep_for(std::chrono::milliseconds{100}); //wait so that the zip <-> archive dir modification time is different long bndId2 = ctx->installBundle(SIMPLE_TEST_BUNDLE1_LOCATION); EXPECT_GT(bndId2, -1); @@ -89,7 +99,18 @@ TEST_F(CxxBundleArchiveTestSuite, BundleArchiveReusedTest) { auto secondBundleRevisionTime = installTime; - ctx->uninstallBundle(bndId1); + tracker.reset(); + fw = celix::createFramework({ + {"CELIX_LOGGING_DEFAULT_ACTIVE_LOG_LEVEL", "trace"}, + {CELIX_FRAMEWORK_CLEAN_CACHE_DIR_ON_CREATE, "false"} + }); + ctx = fw->getFrameworkBundleContext(); + tracker = ctx->trackBundles() + .addOnInstallCallback([&](const celix::Bundle& b) { + std::lock_guard lock{m}; + auto *archive = celix_bundle_getArchive(b.getCBundle()); + EXPECT_EQ(CELIX_SUCCESS, celix_bundleArchive_getLastModified(archive, &installTime)); + }).build(); std::this_thread::sleep_for(std::chrono::milliseconds{100}); //wait so that the zip <-> archive dir modification time is different celix_utils_touch(SIMPLE_TEST_BUNDLE1_LOCATION); //touch the bundle zip file to force an update long bndId3 = ctx->installBundle(SIMPLE_TEST_BUNDLE1_LOCATION); diff --git a/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc b/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc index cf9c08bf5..e62137662 100644 --- a/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc +++ b/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc @@ -28,6 +28,7 @@ #include #include "celix_api.h" +#include "celix_file_utils.h" class CelixBundleContextBundlesTestSuite : public ::testing::Test { public: @@ -46,7 +47,7 @@ class CelixBundleContextBundlesTestSuite : public ::testing::Test { CelixBundleContextBundlesTestSuite() { properties = properties_create(); properties_set(properties, "LOGHELPER_ENABLE_STDOUT_FALLBACK", "true"); - properties_set(properties, "org.osgi.framework.storage.clean", "onFirstInit"); + properties_set(properties, "org.osgi.framework.storage.clean", "true"); properties_set(properties, "org.osgi.framework.storage", ".cacheBundleContextTestFramework"); fw = celix_frameworkFactory_createFramework(properties); @@ -152,6 +153,29 @@ TEST_F(CelixBundleContextBundlesTestSuite, InstallAndUninstallBundlesTest) { ASSERT_FALSE(celix_bundleContext_isBundleActive(ctx, bndId2)); //not auto started ASSERT_TRUE(celix_bundleContext_isBundleActive(ctx, bndId3)); + char *bndRoot1 = nullptr; + ASSERT_TRUE(celix_bundleContext_useBundle(ctx, bndId1, &bndRoot1, [](void* handle, const celix_bundle_t* bnd) { + char **root = static_cast(handle); + *root = celix_bundle_getEntry(bnd, "/"); + })); + ASSERT_TRUE(bndRoot1 != nullptr); + char* bndRoot2 = nullptr; + ASSERT_TRUE(celix_bundleContext_useBundle(ctx, bndId2, &bndRoot2, [](void* handle, const celix_bundle_t* bnd) { + char **root = static_cast(handle); + *root = celix_bundle_getEntry(bnd, "/"); + })); + ASSERT_TRUE(bndRoot2 != nullptr); + char* bndRoot3 = nullptr; + ASSERT_TRUE(celix_bundleContext_useBundle(ctx, bndId3, &bndRoot3, [](void* handle, const celix_bundle_t* bnd) { + char **root = static_cast(handle); + *root = celix_bundle_getEntry(bnd, "/"); + })); + ASSERT_TRUE(bndRoot3 != nullptr); + + ASSERT_TRUE(celix_utils_directoryExists(bndRoot1)); + ASSERT_TRUE(celix_utils_directoryExists(bndRoot2)); + ASSERT_TRUE(celix_utils_directoryExists(bndRoot3)); + //uninstall bundles ASSERT_TRUE(celix_bundleContext_uninstallBundle(ctx, bndId1)); ASSERT_TRUE(celix_bundleContext_uninstallBundle(ctx, bndId2)); @@ -165,17 +189,25 @@ TEST_F(CelixBundleContextBundlesTestSuite, InstallAndUninstallBundlesTest) { ASSERT_FALSE(celix_bundleContext_isBundleActive(ctx, bndId2)); ASSERT_FALSE(celix_bundleContext_isBundleActive(ctx, bndId3)); + ASSERT_FALSE(celix_utils_directoryExists(bndRoot1)); + ASSERT_FALSE(celix_utils_directoryExists(bndRoot2)); + ASSERT_FALSE(celix_utils_directoryExists(bndRoot3)); + + free(bndRoot1); + free(bndRoot2); + free(bndRoot3); + //reinstall bundles long bndId4 = celix_bundleContext_installBundle(ctx, TEST_BND1_LOC, true); long bndId5 = celix_bundleContext_installBundle(ctx, TEST_BND2_LOC, false); long bndId6 = celix_bundleContext_installBundle(ctx, TEST_BND3_LOC, true); ASSERT_TRUE(bndId4 >= 0L); - ASSERT_TRUE(bndId1 == bndId4); //bundle cache -> reuse of bundle id. + ASSERT_FALSE(bndId1 == bndId4); //bundle cache -> reuse of bundle id. ASSERT_TRUE(bndId5 >= 0L); - ASSERT_TRUE(bndId2 == bndId5); //bundle cache -> reuse of bundle id. + ASSERT_FALSE(bndId2 == bndId5); //bundle cache -> reuse of bundle id. ASSERT_TRUE(bndId6 >= 0L); - ASSERT_TRUE(bndId3 == bndId6); //bundle cache -> reuse of bundle id. + ASSERT_FALSE(bndId3 == bndId6); //bundle cache -> reuse of bundle id. } TEST_F(CelixBundleContextBundlesTestSuite, StartBundleWithException) { diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c index 93138d138..823d3d19e 100644 --- a/libs/framework/src/framework.c +++ b/libs/framework/src/framework.c @@ -239,6 +239,7 @@ celix_status_t framework_create(framework_pt *out, celix_properties_t* config) { celixThreadMutex_create(&framework->dispatcher.mutex, NULL); celixThreadMutex_create(&framework->frameworkListenersLock, NULL); celixThreadMutex_create(&framework->bundleListenerLock, NULL); + celixThreadMutex_create(&framework->installLock, NULL); celixThreadMutex_create(&framework->installedBundles.mutex, NULL); celixThreadCondition_init(&framework->dispatcher.cond, NULL); framework->dispatcher.active = true; @@ -359,6 +360,7 @@ celix_status_t framework_destroy(framework_pt framework) { celixThreadMutex_unlock(&framework->installedBundles.mutex); celix_arrayList_destroy(framework->installedBundles.entries); celixThreadMutex_destroy(&framework->installedBundles.mutex); + celixThreadMutex_destroy(&framework->installLock); //teardown framework bundle lifecycle handling assert(celix_arrayList_size(framework->bundleLifecycleHandling.bundleLifecycleHandlers) == 0); @@ -646,11 +648,13 @@ celix_framework_installBundleInternal(celix_framework_t* framework, const char* } } + celixThreadMutex_lock(&framework->installLock); if (status == CELIX_SUCCESS) { id = framework_getBundle(framework, bndLoc); if (id != -1L) { celix_framework_bundleEntry_decreaseUseCount(fwBundleEntry); *bundleOut = id; + celixThreadMutex_unlock(&framework->installLock); return CELIX_SUCCESS; } @@ -677,7 +681,7 @@ celix_framework_installBundleInternal(celix_framework_t* framework, const char* } celix_framework_bundleEntry_decreaseUseCount(fwBundleEntry); - + celixThreadMutex_unlock(&framework->installLock); return status; } @@ -1177,7 +1181,7 @@ static void* framework_shutdown(void *framework) { } for (int i = size-1; i >= 0; --i) { //note loop in reverse order -> uninstall later installed bundle first celix_framework_bundle_entry_t *entry = celix_arrayList_get(stopEntries, i); - celix_framework_uninstallBundleEntry(fw, entry); + celix_framework_uninstallBundleEntry(fw, entry, false); } celix_arrayList_destroy(stopEntries); @@ -1888,10 +1892,11 @@ void celix_framework_uninstallBundleAsync(celix_framework_t *fw, long bndId) { celix_framework_uninstallBundleInternal(fw, bndId, true); } -celix_status_t celix_framework_uninstallBundleEntry(celix_framework_t* framework, celix_framework_bundle_entry_t* bndEntry) { +celix_status_t celix_framework_uninstallBundleEntry(celix_framework_t* framework, celix_framework_bundle_entry_t* bndEntry, bool permanent) { assert(!celix_framework_isCurrentThreadTheEventLoop(framework)); - celixThreadRwlock_writeLock(&bndEntry->fsmMutex); + celixThreadMutex_lock(&framework->installLock); + celixThreadRwlock_writeLock(&bndEntry->fsmMutex); celix_bundle_state_e bndState = celix_bundle_getState(bndEntry->bnd); if (bndState == CELIX_BUNDLE_STATE_ACTIVE) { celix_framework_stopBundleEntryInternal(framework, bndEntry); @@ -1900,6 +1905,7 @@ celix_status_t celix_framework_uninstallBundleEntry(celix_framework_t* framework if (!fw_bundleEntry_removeBundleEntry(framework, bndEntry)) { celixThreadRwlock_unlock(&bndEntry->fsmMutex); celix_framework_bundleEntry_decreaseUseCount(bndEntry); + celixThreadMutex_unlock(&framework->installLock); return CELIX_ILLEGAL_STATE; } @@ -1932,8 +1938,13 @@ celix_status_t celix_framework_uninstallBundleEntry(celix_framework_t* framework celix_framework_waitForEmptyEventQueue(framework); //to ensure that the uninstall event is triggered and handled (void)bundle_closeModules(bnd); (void)bundle_destroy(bnd); - (void)bundleArchive_destroy(archive); + if(permanent) { + (void)celix_bundleCache_destroyArchive(framework->cache, archive); + } else { + (void)bundleArchive_destroy(archive); + } } + celixThreadMutex_unlock(&framework->installLock); framework_logIfError(framework->logger, status, "", "Cannot uninstall bundle"); return status; } diff --git a/libs/framework/src/framework_bundle_lifecycle_handler.c b/libs/framework/src/framework_bundle_lifecycle_handler.c index c0851943e..669778d88 100644 --- a/libs/framework/src/framework_bundle_lifecycle_handler.c +++ b/libs/framework/src/framework_bundle_lifecycle_handler.c @@ -47,7 +47,7 @@ static void* celix_framework_BundleLifecycleHandlingThread(void *data) { break; case CELIX_BUNDLE_LIFECYCLE_UNINSTALL: celix_framework_bundleEntry_decreaseUseCount(handler->bndEntry); - celix_framework_uninstallBundleEntry(handler->framework, handler->bndEntry); + celix_framework_uninstallBundleEntry(handler->framework, handler->bndEntry, true); break; default: //update celix_framework_updateBundleEntry(handler->framework, handler->bndEntry, handler->updatedBundleUrl); @@ -143,7 +143,7 @@ celix_status_t celix_framework_uninstallBundleOnANonCelixEventThread(celix_frame celix_framework_createAndStartBundleLifecycleHandler(fw, bndEntry, CELIX_BUNDLE_LIFECYCLE_UNINSTALL, NULL); return CELIX_SUCCESS; } else { - return celix_framework_uninstallBundleEntry(fw, bndEntry); + return celix_framework_uninstallBundleEntry(fw, bndEntry, true); } } diff --git a/libs/framework/src/framework_private.h b/libs/framework/src/framework_private.h index 3d98c3d8a..f2944cac8 100644 --- a/libs/framework/src/framework_private.h +++ b/libs/framework/src/framework_private.h @@ -40,6 +40,7 @@ #include "celix_threads.h" #include "service_registry.h" +#include #ifndef CELIX_FRAMEWORK_DEFAULT_STATIC_EVENT_QUEUE_SIZE #define CELIX_FRAMEWORK_DEFAULT_STATIC_EVENT_QUEUE_SIZE 1024 @@ -147,6 +148,7 @@ struct celix_framework { celix_thread_t thread; } shutdown; + celix_thread_mutex_t installLock; // serialize install/uninstall struct { celix_array_list_t *entries; //value = celix_framework_bundle_entry_t*. Note ordered by installed bundle time //i.e. later installed bundle are last @@ -426,7 +428,7 @@ celix_status_t celix_framework_stopBundleEntry(celix_framework_t* fw, celix_fram /** * Uninstall a bundle. Cannot be called on the Celix event thread. */ -celix_status_t celix_framework_uninstallBundleEntry(celix_framework_t* fw, celix_framework_bundle_entry_t* bndEntry); +celix_status_t celix_framework_uninstallBundleEntry(celix_framework_t* fw, celix_framework_bundle_entry_t* bndEntry, bool permanent); /** * Uninstall a bundle. Cannot be called on the Celix event thread. From 6008b3d734a204711b98c4b588bcd51dfa0b2384 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Thu, 1 Jun 2023 21:40:26 +0800 Subject: [PATCH 04/21] Add support for bundle unload. Unloading a bundle from a framework instance will release all its resources but leave the bundle in cache so that it can be reloaded using `install`. --- bundles/shell/shell/CMakeLists.txt | 1 + .../shell/shell/gtest/src/ShellTestSuite.cc | 3 + bundles/shell/shell/src/std_commands.c | 9 +- bundles/shell/shell/src/std_commands.h | 2 + bundles/shell/shell/src/unload_command.c | 24 ++++++ .../src/CelixBundleContextBundlesTestSuite.cc | 82 ++++++++++++++++++- .../gtest/src/CelixFrameworkTestSuite.cc | 9 ++ libs/framework/include/celix_bundle_context.h | 16 ++++ libs/framework/include/celix_framework.h | 22 +++++ libs/framework/src/bundle.c | 4 +- libs/framework/src/bundle_context.c | 4 + libs/framework/src/framework.c | 16 +++- .../src/framework_bundle_lifecycle_handler.c | 14 ++-- libs/framework/src/framework_private.h | 6 +- 14 files changed, 195 insertions(+), 17 deletions(-) create mode 100644 bundles/shell/shell/src/unload_command.c diff --git a/bundles/shell/shell/CMakeLists.txt b/bundles/shell/shell/CMakeLists.txt index a07c76b6a..34914da88 100644 --- a/bundles/shell/shell/CMakeLists.txt +++ b/bundles/shell/shell/CMakeLists.txt @@ -41,6 +41,7 @@ if (SHELL) src/install_command.c src/update_command.c src/uninstall_command.c + src/unload_command.c src/help_command.c src/dm_shell_list_command.c src/query_command.c diff --git a/bundles/shell/shell/gtest/src/ShellTestSuite.cc b/bundles/shell/shell/gtest/src/ShellTestSuite.cc index 36d1f9c23..4117f0adc 100644 --- a/bundles/shell/shell/gtest/src/ShellTestSuite.cc +++ b/bundles/shell/shell/gtest/src/ShellTestSuite.cc @@ -104,11 +104,14 @@ TEST_F(ShellTestSuite, testAllCommandsAreCallable) { callCommand(ctx, "start", false); // incorrect number of arguments callCommand(ctx, "uninstall not-a-number", false); callCommand(ctx, "uninstall", false); // incorrect number of arguments + callCommand(ctx, "unload not-a-number", false); + callCommand(ctx, "unload", false); // incorrect number of arguments callCommand(ctx, "update not-a-number", false); callCommand(ctx, "update", false); // incorrect number of arguments callCommand(ctx, "stop 15", false); //non existing bundle id callCommand(ctx, "start 15", false); //non existing bundle id callCommand(ctx, "uninstall 15", false); //non existing bundle id + callCommand(ctx, "unload 15", false); //non existing bundle id callCommand(ctx, "update 15", false); //non existing bundle id } diff --git a/bundles/shell/shell/src/std_commands.c b/bundles/shell/shell/src/std_commands.c index dd3934adb..8edbf092f 100644 --- a/bundles/shell/shell/src/std_commands.c +++ b/bundles/shell/shell/src/std_commands.c @@ -82,7 +82,7 @@ celix_std_commands_t* celix_stdCommands_create(celix_bundle_context_t* ctx) { .exec = uninstallCommand_execute, .name = "celix::uninstall", .description = "uninstall bundle(s).", - .usage = "uninstall [ ...]" + .usage = "uninstall [ ...]" }; commands->std_commands[5] = (struct celix_shell_command_register_entry) { @@ -133,6 +133,13 @@ celix_std_commands_t* celix_stdCommands_create(celix_bundle_context_t* ctx) { .usage = "quit" }; commands->std_commands[11] = + (struct celix_shell_command_register_entry) { + .exec = unloadCommand_execute, + .name = "celix::unload", + .description = "unload bundle(s).", + .usage = "unload [ ...]" + }; + commands->std_commands[12] = (struct celix_shell_command_register_entry) { .exec = NULL }; diff --git a/bundles/shell/shell/src/std_commands.h b/bundles/shell/shell/src/std_commands.h index 6c0a8d06a..a2be10704 100644 --- a/bundles/shell/shell/src/std_commands.h +++ b/bundles/shell/shell/src/std_commands.h @@ -48,6 +48,8 @@ bool installCommand_execute(void *handle, const char *commandLine, FILE *outStre bool uninstallCommand_execute(void *handle, const char *commandLine, FILE *outStream, FILE *errStream); +bool unloadCommand_execute(void *handle, const char *commandLine, FILE *outStream, FILE *errStream); + bool updateCommand_execute(void *handle, const char *commandLine, FILE *outStream, FILE *errStream); bool helpCommand_execute(void *handle, const char *commandLine, FILE *outStream, FILE *errStream); diff --git a/bundles/shell/shell/src/unload_command.c b/bundles/shell/shell/src/unload_command.c new file mode 100644 index 000000000..b27a37e1e --- /dev/null +++ b/bundles/shell/shell/src/unload_command.c @@ -0,0 +1,24 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ + +#include "bundle_command.h" + +bool unloadCommand_execute(void *handle, const char* constCommandLine, FILE *outStream, FILE *errStream) { + return bundleCommand_execute(handle, constCommandLine, outStream, errStream, celix_framework_unloadBundleAsync); +} diff --git a/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc b/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc index e62137662..f76720878 100644 --- a/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc +++ b/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc @@ -203,11 +203,87 @@ TEST_F(CelixBundleContextBundlesTestSuite, InstallAndUninstallBundlesTest) { long bndId6 = celix_bundleContext_installBundle(ctx, TEST_BND3_LOC, true); ASSERT_TRUE(bndId4 >= 0L); - ASSERT_FALSE(bndId1 == bndId4); //bundle cache -> reuse of bundle id. + ASSERT_FALSE(bndId1 == bndId4); ASSERT_TRUE(bndId5 >= 0L); - ASSERT_FALSE(bndId2 == bndId5); //bundle cache -> reuse of bundle id. + ASSERT_FALSE(bndId2 == bndId5); ASSERT_TRUE(bndId6 >= 0L); - ASSERT_FALSE(bndId3 == bndId6); //bundle cache -> reuse of bundle id. + ASSERT_FALSE(bndId3 == bndId6); +} + +TEST_F(CelixBundleContextBundlesTestSuite, InstallAndUnloadBundlesTest) { + //install bundles + long bndId1 = celix_bundleContext_installBundle(ctx, TEST_BND1_LOC, true); + long bndId2 = celix_bundleContext_installBundle(ctx, TEST_BND2_LOC, false); + long bndId3 = celix_bundleContext_installBundle(ctx, TEST_BND3_LOC, true); + + ASSERT_TRUE(bndId1 >= 0L); + ASSERT_TRUE(bndId2 >= 0L); + ASSERT_TRUE(bndId3 >= 0L); + + ASSERT_TRUE(celix_bundleContext_isBundleInstalled(ctx, bndId1)); + ASSERT_TRUE(celix_bundleContext_isBundleInstalled(ctx, bndId2)); + ASSERT_TRUE(celix_bundleContext_isBundleInstalled(ctx, bndId3)); + + ASSERT_TRUE(celix_bundleContext_isBundleActive(ctx, bndId1)); + ASSERT_FALSE(celix_bundleContext_isBundleActive(ctx, bndId2)); //not auto started + ASSERT_TRUE(celix_bundleContext_isBundleActive(ctx, bndId3)); + + char *bndRoot1 = nullptr; + ASSERT_TRUE(celix_bundleContext_useBundle(ctx, bndId1, &bndRoot1, [](void* handle, const celix_bundle_t* bnd) { + char **root = static_cast(handle); + *root = celix_bundle_getEntry(bnd, "/"); + })); + ASSERT_TRUE(bndRoot1 != nullptr); + char* bndRoot2 = nullptr; + ASSERT_TRUE(celix_bundleContext_useBundle(ctx, bndId2, &bndRoot2, [](void* handle, const celix_bundle_t* bnd) { + char **root = static_cast(handle); + *root = celix_bundle_getEntry(bnd, "/"); + })); + ASSERT_TRUE(bndRoot2 != nullptr); + char* bndRoot3 = nullptr; + ASSERT_TRUE(celix_bundleContext_useBundle(ctx, bndId3, &bndRoot3, [](void* handle, const celix_bundle_t* bnd) { + char **root = static_cast(handle); + *root = celix_bundle_getEntry(bnd, "/"); + })); + ASSERT_TRUE(bndRoot3 != nullptr); + + ASSERT_TRUE(celix_utils_directoryExists(bndRoot1)); + ASSERT_TRUE(celix_utils_directoryExists(bndRoot2)); + ASSERT_TRUE(celix_utils_directoryExists(bndRoot3)); + + //unload bundles + ASSERT_TRUE(celix_bundleContext_unloadBundle(ctx, bndId1)); + ASSERT_TRUE(celix_bundleContext_unloadBundle(ctx, bndId2)); + ASSERT_TRUE(celix_bundleContext_unloadBundle(ctx, bndId3)); + + ASSERT_FALSE(celix_bundleContext_isBundleInstalled(ctx, bndId1)); + ASSERT_FALSE(celix_bundleContext_isBundleInstalled(ctx, bndId2)); + ASSERT_FALSE(celix_bundleContext_isBundleInstalled(ctx, bndId3)); + + ASSERT_FALSE(celix_bundleContext_isBundleActive(ctx, bndId1)); //not uninstall -> not active + ASSERT_FALSE(celix_bundleContext_isBundleActive(ctx, bndId2)); + ASSERT_FALSE(celix_bundleContext_isBundleActive(ctx, bndId3)); + + // bundle cache is NOT cleaned up + ASSERT_TRUE(celix_utils_directoryExists(bndRoot1)); + ASSERT_TRUE(celix_utils_directoryExists(bndRoot2)); + ASSERT_TRUE(celix_utils_directoryExists(bndRoot3)); + + free(bndRoot1); + free(bndRoot2); + free(bndRoot3); + + //reinstall bundles + long bndId4 = celix_bundleContext_installBundle(ctx, TEST_BND1_LOC, true); + long bndId5 = celix_bundleContext_installBundle(ctx, TEST_BND2_LOC, false); + long bndId6 = celix_bundleContext_installBundle(ctx, TEST_BND3_LOC, true); + + ASSERT_TRUE(bndId4 >= 0L); + ASSERT_TRUE(bndId1 == bndId4); //bundle cache -> reuse of bundle id. + ASSERT_TRUE(bndId5 >= 0L); + ASSERT_TRUE(bndId2 == bndId5); //bundle cache -> reuse of bundle id. + ASSERT_TRUE(bndId6 >= 0L); + ASSERT_TRUE(bndId3 == bndId6); //bundle cache -> reuse of bundle id. } TEST_F(CelixBundleContextBundlesTestSuite, StartBundleWithException) { diff --git a/libs/framework/gtest/src/CelixFrameworkTestSuite.cc b/libs/framework/gtest/src/CelixFrameworkTestSuite.cc index 1a3562c1f..89c20f619 100644 --- a/libs/framework/gtest/src/CelixFrameworkTestSuite.cc +++ b/libs/framework/gtest/src/CelixFrameworkTestSuite.cc @@ -93,6 +93,15 @@ TEST_F(CelixFrameworkTestSuite, AsyncInstallStartStopAndUninstallBundleTest) { std::this_thread::sleep_for(std::chrono::milliseconds{100}); EXPECT_FALSE(celix_framework_isBundleActive(framework.get(), bndId)); + celix_framework_unloadBundleAsync(framework.get(), bndId); + std::this_thread::sleep_for(std::chrono::milliseconds{100}); + EXPECT_FALSE(celix_framework_isBundleInstalled(framework.get(), bndId)); + + // reloaded bundle should reuse the same bundle id + EXPECT_EQ(bndId, celix_framework_installBundleAsync(framework.get(), SIMPLE_TEST_BUNDLE1_LOCATION, false)); + EXPECT_TRUE(celix_framework_isBundleInstalled(framework.get(), bndId)); + EXPECT_FALSE(celix_framework_isBundleActive(framework.get(), bndId)); + celix_framework_uninstallBundleAsync(framework.get(), bndId); std::this_thread::sleep_for(std::chrono::milliseconds{100}); EXPECT_FALSE(celix_framework_isBundleInstalled(framework.get(), bndId)); diff --git a/libs/framework/include/celix_bundle_context.h b/libs/framework/include/celix_bundle_context.h index 8b1ef2bc8..fc73b1805 100644 --- a/libs/framework/include/celix_bundle_context.h +++ b/libs/framework/include/celix_bundle_context.h @@ -905,6 +905,22 @@ CELIX_FRAMEWORK_EXPORT long celix_bundleContext_installBundle(celix_bundle_conte */ CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_uninstallBundle(celix_bundle_context_t *ctx, long bndId); +/** + * @brief Unload the bundle with the provided bundle id. If needed the bundle will be stopped first. + * Will silently ignore bundle ids < 0. + * Note that unloaded bundle is kept in bundle cache and can be reloaded with the celix_bundleContext_installBundle function. + * + * If this function is called on the Celix event thread, the actual stopping of the bundle will be done async and + * on a separate thread. + * If this function is called from a different thread than the Celix event thread, then the function will return after + * the bundle is stopped. + * + * @param ctx The bundle context + * @param bndId The bundle id to unload. + * @return true if the bundle is correctly unloaded. False if not. + */ +CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_unloadBundle(celix_bundle_context_t *ctx, long bndId); + /** * @brief Stop the bundle with the provided bundle id. * Will silently ignore bundle ids < 0. diff --git a/libs/framework/include/celix_framework.h b/libs/framework/include/celix_framework.h index e5beb0d2e..2bfbd114f 100644 --- a/libs/framework/include/celix_framework.h +++ b/libs/framework/include/celix_framework.h @@ -138,6 +138,17 @@ CELIX_FRAMEWORK_EXPORT long celix_framework_installBundle(celix_framework_t *fw, */ CELIX_FRAMEWORK_EXPORT bool celix_framework_uninstallBundle(celix_framework_t *fw, long bndId); +/** + * @brief Unload the bundle with the provided bundle id. If needed the bundle will be stopped first. + * Will silently ignore bundle ids < 0. + * Note that unloaded bundle is kept in bundle cache and can be reloaded with the celix_framework_installBundle function. + * + * @param fw The Celix framework + * @param bndId The bundle id to unload. + * @return true if the bundle is correctly unloaded. False if not. + */ +CELIX_FRAMEWORK_EXPORT bool celix_framework_unloadBundle(celix_framework_t *fw, long bndId); + /** * @brief Update the bundle with the provided bundle id. * @@ -221,6 +232,17 @@ CELIX_FRAMEWORK_EXPORT void celix_framework_updateBundleAsync(celix_framework_t */ CELIX_FRAMEWORK_EXPORT void celix_framework_uninstallBundleAsync(celix_framework_t *fw, long bndId); +/** + * @brief Unload the bundle with the provided bundle id async. If needed the bundle will be stopped first. + * Will silently ignore bundle ids < 0. + * Note that unloaded bundle is kept in bundle cache and can be reloaded with the celix_framework_installBundle function. + * The bundle will be unloaded on a separate spawned thread. + * + * @param fw The Celix framework + * @param bndId The bundle id to unload. + */ +CELIX_FRAMEWORK_EXPORT void celix_framework_unloadBundleAsync(celix_framework_t *fw, long bndId); + /** * @brief Stop the bundle with the provided bundle id async. * Will silently ignore bundle ids < 0. diff --git a/libs/framework/src/bundle.c b/libs/framework/src/bundle.c index 7f08f15eb..64eaa2410 100644 --- a/libs/framework/src/bundle.c +++ b/libs/framework/src/bundle.c @@ -238,8 +238,8 @@ celix_status_t bundle_update(bundle_pt bundle, const char* updatedBundleUrl) { } celix_status_t bundle_stop(bundle_pt bundle) { - //note deprecated call use celix_bundleContext_startBundle instead - return celix_framework_startBundle(bundle->framework, celix_bundle_getId(bundle)); + //note deprecated call use celix_bundleContext_stopBundle instead + return celix_framework_stopBundle(bundle->framework, celix_bundle_getId(bundle)); } celix_status_t bundle_uninstall(bundle_pt bundle) { diff --git a/libs/framework/src/bundle_context.c b/libs/framework/src/bundle_context.c index 8a802b7c9..b3f702322 100644 --- a/libs/framework/src/bundle_context.c +++ b/libs/framework/src/bundle_context.c @@ -995,6 +995,10 @@ bool celix_bundleContext_uninstallBundle(bundle_context_t *ctx, long bndId) { return celix_framework_uninstallBundle(ctx->framework, bndId); } +bool celix_bundleContext_unloadBundle(celix_bundle_context_t *ctx, long bndId) { + return celix_framework_unloadBundle(ctx->framework, bndId); +} + bool celix_bundleContext_useServiceWithId( bundle_context_t *ctx, long serviceId, diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c index 823d3d19e..8671abac9 100644 --- a/libs/framework/src/framework.c +++ b/libs/framework/src/framework.c @@ -1872,11 +1872,11 @@ long celix_framework_installBundleAsync(celix_framework_t *fw, const char *bundl return celix_framework_installAndStartBundleInternal(fw, bundleLoc, autoStart, true); } -static bool celix_framework_uninstallBundleInternal(celix_framework_t *fw, long bndId, bool forcedAsync) { +static bool celix_framework_uninstallBundleInternal(celix_framework_t *fw, long bndId, bool forcedAsync, bool permanent) { bool uninstalled = false; celix_framework_bundle_entry_t *bndEntry = celix_framework_bundleEntry_getBundleEntryAndIncreaseUseCount(fw, bndId); if (bndEntry != NULL) { - celix_status_t status = celix_framework_uninstallBundleOnANonCelixEventThread(fw, bndEntry, forcedAsync); + celix_status_t status = celix_framework_uninstallBundleOnANonCelixEventThread(fw, bndEntry, forcedAsync, permanent); celix_framework_waitForBundleEvents(fw, bndId); //note not decreasing bndEntry, because this entry should now be deleted (uninstalled) uninstalled = status == CELIX_SUCCESS; @@ -1885,11 +1885,19 @@ static bool celix_framework_uninstallBundleInternal(celix_framework_t *fw, long } bool celix_framework_uninstallBundle(celix_framework_t *fw, long bndId) { - return celix_framework_uninstallBundleInternal(fw, bndId, false); + return celix_framework_uninstallBundleInternal(fw, bndId, false, true); } void celix_framework_uninstallBundleAsync(celix_framework_t *fw, long bndId) { - celix_framework_uninstallBundleInternal(fw, bndId, true); + celix_framework_uninstallBundleInternal(fw, bndId, true, true); +} + +bool celix_framework_unloadBundle(celix_framework_t *fw, long bndId) { + return celix_framework_uninstallBundleInternal(fw, bndId, false, false); +} + +void celix_framework_unloadBundleAsync(celix_framework_t *fw, long bndId) { + celix_framework_uninstallBundleInternal(fw, bndId, true, false); } celix_status_t celix_framework_uninstallBundleEntry(celix_framework_t* framework, celix_framework_bundle_entry_t* bndEntry, bool permanent) { diff --git a/libs/framework/src/framework_bundle_lifecycle_handler.c b/libs/framework/src/framework_bundle_lifecycle_handler.c index 669778d88..6ffa9bb39 100644 --- a/libs/framework/src/framework_bundle_lifecycle_handler.c +++ b/libs/framework/src/framework_bundle_lifecycle_handler.c @@ -49,11 +49,15 @@ static void* celix_framework_BundleLifecycleHandlingThread(void *data) { celix_framework_bundleEntry_decreaseUseCount(handler->bndEntry); celix_framework_uninstallBundleEntry(handler->framework, handler->bndEntry, true); break; + case CELIX_BUNDLE_LIFECYCLE_UNLOAD: + celix_framework_bundleEntry_decreaseUseCount(handler->bndEntry); + celix_framework_uninstallBundleEntry(handler->framework, handler->bndEntry, false); + break; default: //update celix_framework_updateBundleEntry(handler->framework, handler->bndEntry, handler->updatedBundleUrl); break; } - if (handler->command != CELIX_BUNDLE_LIFECYCLE_UNINSTALL) { + if (handler->command != CELIX_BUNDLE_LIFECYCLE_UNINSTALL && handler->command != CELIX_BUNDLE_LIFECYCLE_UNLOAD) { celix_framework_bundleEntry_decreaseUseCount(handler->bndEntry); } celix_framework_cleanupBundleLifecycleHandler(handler->framework, handler); @@ -132,18 +136,18 @@ celix_status_t celix_framework_stopBundleOnANonCelixEventThread(celix_framework_ } } -celix_status_t celix_framework_uninstallBundleOnANonCelixEventThread(celix_framework_t* fw, celix_framework_bundle_entry_t* bndEntry, bool forceSpawnThread) { +celix_status_t celix_framework_uninstallBundleOnANonCelixEventThread(celix_framework_t* fw, celix_framework_bundle_entry_t* bndEntry, bool forceSpawnThread, bool permanent) { if (forceSpawnThread) { fw_log(fw->logger, CELIX_LOG_LEVEL_TRACE, "uninstall bundle from a separate thread"); - celix_framework_createAndStartBundleLifecycleHandler(fw, bndEntry, CELIX_BUNDLE_LIFECYCLE_UNINSTALL, NULL); + celix_framework_createAndStartBundleLifecycleHandler(fw, bndEntry, permanent ? CELIX_BUNDLE_LIFECYCLE_UNINSTALL : CELIX_BUNDLE_LIFECYCLE_UNLOAD, NULL); return CELIX_SUCCESS; } else if (celix_framework_isCurrentThreadTheEventLoop(fw)) { fw_log(fw->logger, CELIX_LOG_LEVEL_DEBUG, "Cannot uninstall bundle from Celix event thread. Using a separate thread to uninstall bundle. See celix_bundleContext_uninstall Bundle for more info."); - celix_framework_createAndStartBundleLifecycleHandler(fw, bndEntry, CELIX_BUNDLE_LIFECYCLE_UNINSTALL, NULL); + celix_framework_createAndStartBundleLifecycleHandler(fw, bndEntry, permanent ? CELIX_BUNDLE_LIFECYCLE_UNINSTALL : CELIX_BUNDLE_LIFECYCLE_UNLOAD, NULL); return CELIX_SUCCESS; } else { - return celix_framework_uninstallBundleEntry(fw, bndEntry, true); + return celix_framework_uninstallBundleEntry(fw, bndEntry, permanent); } } diff --git a/libs/framework/src/framework_private.h b/libs/framework/src/framework_private.h index f2944cac8..c506e94b3 100644 --- a/libs/framework/src/framework_private.h +++ b/libs/framework/src/framework_private.h @@ -113,7 +113,8 @@ enum celix_bundle_lifecycle_command { CELIX_BUNDLE_LIFECYCLE_START, CELIX_BUNDLE_LIFECYCLE_STOP, CELIX_BUNDLE_LIFECYCLE_UNINSTALL, - CELIX_BUNDLE_LIFECYCLE_UPDATE + CELIX_BUNDLE_LIFECYCLE_UPDATE, + CELIX_BUNDLE_LIFECYCLE_UNLOAD }; typedef struct celix_framework_bundle_lifecycle_handler { @@ -396,9 +397,10 @@ celix_status_t celix_framework_stopBundleOnANonCelixEventThread(celix_framework_ * @param fw The Celix framework * @param bndEntry A bnd entry * @param forceSpawnThread If the true, the start bundle will always be done on a spawn thread + * @param permanent If true, the bundle will be permanently uninstalled (e.g. the bundle archive will be removed). * @return CELIX_SUCCESS of the call went alright. */ -celix_status_t celix_framework_uninstallBundleOnANonCelixEventThread(celix_framework_t* fw, celix_framework_bundle_entry_t* bndEntry, bool forceSpawnThread); +celix_status_t celix_framework_uninstallBundleOnANonCelixEventThread(celix_framework_t* fw, celix_framework_bundle_entry_t* bndEntry, bool forceSpawnThread, bool permanent); /** * Update (and if needed stop and start) a bundle and ensure that this is not done on the Celix event thread. From 27383f6c7f7fe8b519bb9ebb9e6f6dc338294970 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Fri, 2 Jun 2023 11:40:51 +0800 Subject: [PATCH 05/21] Update all bundle activator to use async service registration. --- bundles/http_admin/gtest/src/sut_activator.c | 8 ++++---- bundles/http_admin/http_admin/src/http_admin.c | 2 +- .../pubsub/integration/gtest/loopback_activator.c | 2 +- .../integration/gtest/tst_endpoint_activator.c | 4 ++-- bundles/pubsub/pubsub_admin_tcp/src/psa_activator.c | 12 ++++++------ .../pubsub/pubsub_admin_udp_mc/src/psa_activator.c | 4 ++-- .../pubsub_admin_websocket/src/psa_activator.c | 4 ++-- .../src/pubsub_websocket_topic_receiver.c | 4 ++-- .../src/pubsub_websocket_topic_sender.c | 4 ++-- bundles/pubsub/pubsub_admin_zmq/src/psa_activator.c | 4 ++-- bundles/pubsub/pubsub_discovery/src/psd_activator.c | 4 ++-- .../src/ps_wire_protocol_activator.c | 2 +- .../src/ps_wire_v2_protocol_activator.c | 2 +- .../src/ps_avrobin_serializer_activator.c | 2 +- .../src/ps_json_serializer_activator.c | 2 +- .../pubsub_topology_manager/src/pstm_activator.c | 4 ++-- .../calculator_service/src/calculator_activator.c | 2 +- .../src/calculator_shell_activator.c | 6 +++--- .../src/remote_example_activator.c | 2 +- .../remote_example_service/src/remote_example_impl.c | 2 +- .../gtest/src/tst_activator.c | 2 +- .../src/remote_service_admin_activator.c | 2 +- .../shell/shell_wui/src/shell_wui_bundle_activator.c | 2 +- .../http_example/src/http_example_bundle_activator.c | 2 +- .../services_example_c/src/simple_provider_example.c | 2 +- .../track_tracker_example/src/activator.c | 2 +- 26 files changed, 44 insertions(+), 44 deletions(-) diff --git a/bundles/http_admin/gtest/src/sut_activator.c b/bundles/http_admin/gtest/src/sut_activator.c index 2c15da497..c35256cdd 100644 --- a/bundles/http_admin/gtest/src/sut_activator.c +++ b/bundles/http_admin/gtest/src/sut_activator.c @@ -45,23 +45,23 @@ celix_status_t bnd_start(struct activator *act, celix_bundle_context_t *ctx) { celix_properties_set(props, HTTP_ADMIN_URI, "/alias"); act->httpSvc.handle = act; act->httpSvc.doPut = alias_test_put; - act->httpSvcId = celix_bundleContext_registerService(ctx, &act->httpSvc, HTTP_ADMIN_SERVICE_NAME, props); + act->httpSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->httpSvc, HTTP_ADMIN_SERVICE_NAME, props); celix_properties_t *props2 = celix_properties_create(); celix_properties_set(props2, HTTP_ADMIN_URI, "/foo/bar"); act->httpSvc2.handle = act; - act->httpSvcId2 = celix_bundleContext_registerService(ctx, &act->httpSvc2, HTTP_ADMIN_SERVICE_NAME, props2); + act->httpSvcId2 = celix_bundleContext_registerServiceAsync(ctx, &act->httpSvc2, HTTP_ADMIN_SERVICE_NAME, props2); celix_properties_t *props3 = celix_properties_create(); celix_properties_set(props3, HTTP_ADMIN_URI, "/"); act->httpSvc3.handle = act; - act->httpSvcId3 = celix_bundleContext_registerService(ctx, &act->httpSvc3, HTTP_ADMIN_SERVICE_NAME, props3); + act->httpSvcId3 = celix_bundleContext_registerServiceAsync(ctx, &act->httpSvc3, HTTP_ADMIN_SERVICE_NAME, props3); celix_properties_t *props4 = celix_properties_create(); celix_properties_set(props4, WEBSOCKET_ADMIN_URI, "/"); act->sockSvc.handle = act; act->sockSvc.data = websocket_data_echo; - act->sockSvcId = celix_bundleContext_registerService(ctx, &act->sockSvc, WEBSOCKET_ADMIN_SERVICE_NAME, props4); + act->sockSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->sockSvc, WEBSOCKET_ADMIN_SERVICE_NAME, props4); return CELIX_SUCCESS; } diff --git a/bundles/http_admin/http_admin/src/http_admin.c b/bundles/http_admin/http_admin/src/http_admin.c index b28f7e440..e20060da7 100755 --- a/bundles/http_admin/http_admin/src/http_admin.c +++ b/bundles/http_admin/http_admin/src/http_admin.c @@ -374,7 +374,7 @@ static void httpAdmin_updateInfoSvc(http_admin_manager_t *admin) { if (resources_urls_size > 1) { celix_properties_set(properties, HTTP_ADMIN_INFO_RESOURCE_URLS, resources_urls); } - admin->infoSvcId = celix_bundleContext_registerService(admin->context, &admin->infoSvc, HTTP_ADMIN_INFO_SERVICE_NAME, properties); + admin->infoSvcId = celix_bundleContext_registerServiceAsync(admin->context, &admin->infoSvc, HTTP_ADMIN_INFO_SERVICE_NAME, properties); celixThreadMutex_unlock(&admin->admin_lock); diff --git a/bundles/pubsub/integration/gtest/loopback_activator.c b/bundles/pubsub/integration/gtest/loopback_activator.c index c718c4a71..a9d819c0b 100644 --- a/bundles/pubsub/integration/gtest/loopback_activator.c +++ b/bundles/pubsub/integration/gtest/loopback_activator.c @@ -58,7 +58,7 @@ celix_status_t bnd_start(struct activator *act, celix_bundle_context_t *ctx) { celix_properties_set(props, PUBSUB_SUBSCRIBER_TOPIC, "pong2"); act->subSvc.handle = act; act->subSvc.receive = tst_receive; - act->subSvcId = celix_bundleContext_registerService(ctx, &act->subSvc, PUBSUB_SUBSCRIBER_SERVICE_NAME, props); + act->subSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->subSvc, PUBSUB_SUBSCRIBER_SERVICE_NAME, props); return CELIX_SUCCESS; diff --git a/bundles/pubsub/integration/gtest/tst_endpoint_activator.c b/bundles/pubsub/integration/gtest/tst_endpoint_activator.c index e01a8ea83..bd8a23a6b 100644 --- a/bundles/pubsub/integration/gtest/tst_endpoint_activator.c +++ b/bundles/pubsub/integration/gtest/tst_endpoint_activator.c @@ -51,14 +51,14 @@ celix_status_t bnd_start(struct activator *act, celix_bundle_context_t *ctx) { celix_properties_set(props, PUBSUB_SUBSCRIBER_TOPIC, "pong3"); act->subSvc.handle = act; act->subSvc.receive = tst_receive; - act->subSvcId = celix_bundleContext_registerService(ctx, &act->subSvc, PUBSUB_SUBSCRIBER_SERVICE_NAME, props); + act->subSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->subSvc, PUBSUB_SUBSCRIBER_SERVICE_NAME, props); } { act->countSvc.handle = act; act->countSvc.receiveCount = tst_count; - act->countSvcId = celix_bundleContext_registerService(ctx, &act->countSvc, CELIX_RECEIVE_COUNT_SERVICE_NAME, NULL); + act->countSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->countSvc, CELIX_RECEIVE_COUNT_SERVICE_NAME, NULL); } diff --git a/bundles/pubsub/pubsub_admin_tcp/src/psa_activator.c b/bundles/pubsub/pubsub_admin_tcp/src/psa_activator.c index 008cb7ce5..cc13d7030 100644 --- a/bundles/pubsub/pubsub_admin_tcp/src/psa_activator.c +++ b/bundles/pubsub/pubsub_admin_tcp/src/psa_activator.c @@ -83,7 +83,7 @@ int psa_tcp_start(psa_tcp_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_t *props = celix_properties_create(); celix_properties_set(props, PUBSUB_ADMIN_SERVICE_TYPE, PUBSUB_TCP_ADMIN_TYPE); - act->adminSvcId = celix_bundleContext_registerService(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props); + act->adminSvcId = celix_bundleContext_registerServiceAsync(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props); } if (status == CELIX_SUCCESS) { @@ -94,10 +94,10 @@ int psa_tcp_start(psa_tcp_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_set(props, PUBSUB_ADMIN_SERVICE_TYPE, PUBSUB_TCP_ADMIN_TYPE); act->adminMetricsSvcId = - celix_bundleContext_registerService(ctx, - &act->adminMetricsService, - PUBSUB_ADMIN_METRICS_SERVICE_NAME, - props); + celix_bundleContext_registerServiceAsync(ctx, + &act->adminMetricsService, + PUBSUB_ADMIN_METRICS_SERVICE_NAME, + props); } //register shell command service @@ -108,7 +108,7 @@ int psa_tcp_start(psa_tcp_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psa_tcp"); celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psa_tcp"); celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the TCP PSA"); - act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + act->cmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); } return status; diff --git a/bundles/pubsub/pubsub_admin_udp_mc/src/psa_activator.c b/bundles/pubsub/pubsub_admin_udp_mc/src/psa_activator.c index 0cc543c5a..e9058a3a3 100644 --- a/bundles/pubsub/pubsub_admin_udp_mc/src/psa_activator.c +++ b/bundles/pubsub/pubsub_admin_udp_mc/src/psa_activator.c @@ -80,7 +80,7 @@ int psa_udpmc_start(psa_udpmc_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_t *props = celix_properties_create(); celix_properties_set(props, PUBSUB_ADMIN_SERVICE_TYPE, PUBSUB_UDPMC_ADMIN_TYPE); - act->adminSvcId = celix_bundleContext_registerService(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props); + act->adminSvcId = celix_bundleContext_registerServiceAsync(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props); } //register shell command service @@ -91,7 +91,7 @@ int psa_udpmc_start(psa_udpmc_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psa_udpmc"); celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psa_udpmc"); celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the UDPMC PSA"); - act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + act->cmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); } return status; diff --git a/bundles/pubsub/pubsub_admin_websocket/src/psa_activator.c b/bundles/pubsub/pubsub_admin_websocket/src/psa_activator.c index 33cc86f3f..2a41fa50d 100644 --- a/bundles/pubsub/pubsub_admin_websocket/src/psa_activator.c +++ b/bundles/pubsub/pubsub_admin_websocket/src/psa_activator.c @@ -70,7 +70,7 @@ int psa_websocket_start(psa_websocket_activator_t *act, celix_bundle_context_t * celix_properties_t *props = celix_properties_create(); celix_properties_set(props, PUBSUB_ADMIN_SERVICE_TYPE, PUBSUB_WEBSOCKET_ADMIN_TYPE); - act->adminSvcId = celix_bundleContext_registerService(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props); + act->adminSvcId = celix_bundleContext_registerServiceAsync(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props); } //register shell command service @@ -81,7 +81,7 @@ int psa_websocket_start(psa_websocket_activator_t *act, celix_bundle_context_t * celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psa_websocket"); celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psa_websocket"); celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the websocket PSA"); - act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + act->cmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); } return status; diff --git a/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_receiver.c b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_receiver.c index e163a7ca7..9dc5fd787 100644 --- a/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_receiver.c +++ b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_receiver.c @@ -193,8 +193,8 @@ pubsub_websocket_topic_receiver_t* pubsub_websocketTopicReceiver_create(celix_bu receiver->sockSvc.ready = psa_websocketTopicReceiver_ready; receiver->sockSvc.data = psa_websocketTopicReceiver_data; receiver->sockSvc.close = psa_websocketTopicReceiver_close; - receiver->svcId = celix_bundleContext_registerService(receiver->ctx, &receiver->sockSvc, - WEBSOCKET_ADMIN_SERVICE_NAME, props); + receiver->svcId = celix_bundleContext_registerServiceAsync(receiver->ctx, &receiver->sockSvc, + WEBSOCKET_ADMIN_SERVICE_NAME, props); } const char *staticConnects = pubsub_getEnvironmentVariableWithScopeTopic(ctx, PUBSUB_WEBSOCKET_STATIC_CONNECT_SOCKET_ADDRESSES_FOR, topic, scope); diff --git a/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_sender.c b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_sender.c index e8ab06233..eb1dc6b10 100644 --- a/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_sender.c +++ b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_sender.c @@ -115,8 +115,8 @@ pubsub_websocket_topic_sender_t* pubsub_websocketTopicSender_create( sender->websockSvc.handle = sender; sender->websockSvc.ready = psa_websocketTopicSender_ready; sender->websockSvc.close = psa_websocketTopicSender_close; - sender->websockSvcId = celix_bundleContext_registerService(ctx, &sender->websockSvc, - WEBSOCKET_ADMIN_SERVICE_NAME, props); + sender->websockSvcId = celix_bundleContext_registerServiceAsync(ctx, &sender->websockSvc, + WEBSOCKET_ADMIN_SERVICE_NAME, props); } else { sender->websockSvcId = -1; } diff --git a/bundles/pubsub/pubsub_admin_zmq/src/psa_activator.c b/bundles/pubsub/pubsub_admin_zmq/src/psa_activator.c index 913ad34df..3943ff785 100644 --- a/bundles/pubsub/pubsub_admin_zmq/src/psa_activator.c +++ b/bundles/pubsub/pubsub_admin_zmq/src/psa_activator.c @@ -84,7 +84,7 @@ int psa_zmq_start(psa_zmq_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_t *props = celix_properties_create(); celix_properties_set(props, PUBSUB_ADMIN_SERVICE_TYPE, PUBSUB_ZMQ_ADMIN_TYPE); - act->adminSvcId = celix_bundleContext_registerService(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props); + act->adminSvcId = celix_bundleContext_registerServiceAsync(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props); } //register shell command service @@ -95,7 +95,7 @@ int psa_zmq_start(psa_zmq_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psa_zmq"); celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psa_zmq"); celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the ZMQ PSA"); - act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + act->cmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); } return status; diff --git a/bundles/pubsub/pubsub_discovery/src/psd_activator.c b/bundles/pubsub/pubsub_discovery/src/psd_activator.c index d19cb0f1d..0aaa35938 100644 --- a/bundles/pubsub/pubsub_discovery/src/psd_activator.c +++ b/bundles/pubsub/pubsub_discovery/src/psd_activator.c @@ -76,11 +76,11 @@ static celix_status_t psd_start(psd_activator_t *act, celix_bundle_context_t *ct celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psd_etcd"); celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psd_etcd"); celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Overview of discovered/announced endpoints from/to ETCD"); - act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + act->cmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); } if (status == CELIX_SUCCESS) { - act->listenerSvcId = celix_bundleContext_registerService(ctx, &act->listenerSvc, PUBSUB_ANNOUNCE_ENDPOINT_LISTENER_SERVICE, NULL); + act->listenerSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->listenerSvc, PUBSUB_ANNOUNCE_ENDPOINT_LISTENER_SERVICE, NULL); } else { act->listenerSvcId = -1L; } diff --git a/bundles/pubsub/pubsub_protocol/pubsub_protocol_wire_v1/src/ps_wire_protocol_activator.c b/bundles/pubsub/pubsub_protocol/pubsub_protocol_wire_v1/src/ps_wire_protocol_activator.c index 64abebecf..03b130f8e 100644 --- a/bundles/pubsub/pubsub_protocol/pubsub_protocol_wire_v1/src/ps_wire_protocol_activator.c +++ b/bundles/pubsub/pubsub_protocol/pubsub_protocol_wire_v1/src/ps_wire_protocol_activator.c @@ -57,7 +57,7 @@ static int ps_wp_start(ps_wp_activator_t *act, celix_bundle_context_t *ctx) { act->protocolSvc.decodeMetadata = pubsubProtocol_v1_decodeMetadata; act->protocolSvc.decodeFooter = pubsubProtocol_decodeFooter; - act->wireProtocolSvcId = celix_bundleContext_registerService(ctx, &act->protocolSvc, PUBSUB_PROTOCOL_SERVICE_NAME, props); + act->wireProtocolSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->protocolSvc, PUBSUB_PROTOCOL_SERVICE_NAME, props); } return status; } diff --git a/bundles/pubsub/pubsub_protocol/pubsub_protocol_wire_v2/src/ps_wire_v2_protocol_activator.c b/bundles/pubsub/pubsub_protocol/pubsub_protocol_wire_v2/src/ps_wire_v2_protocol_activator.c index 86708eba4..0b8841230 100644 --- a/bundles/pubsub/pubsub_protocol/pubsub_protocol_wire_v2/src/ps_wire_v2_protocol_activator.c +++ b/bundles/pubsub/pubsub_protocol/pubsub_protocol_wire_v2/src/ps_wire_v2_protocol_activator.c @@ -58,7 +58,7 @@ static int ps_wp_start(ps_wp_activator_t *act, celix_bundle_context_t *ctx) { act->protocolSvc.decodeMetadata = pubsubProtocol_wire_v2_decodeMetadata; act->protocolSvc.decodeFooter = pubsubProtocol_wire_v2_decodeFooter; - act->wireProtocolSvcId = celix_bundleContext_registerService(ctx, &act->protocolSvc, PUBSUB_PROTOCOL_SERVICE_NAME, props); + act->wireProtocolSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->protocolSvc, PUBSUB_PROTOCOL_SERVICE_NAME, props); } return status; } diff --git a/bundles/pubsub/pubsub_serializer_avrobin/src/ps_avrobin_serializer_activator.c b/bundles/pubsub/pubsub_serializer_avrobin/src/ps_avrobin_serializer_activator.c index 275a72da7..11cfe1520 100644 --- a/bundles/pubsub/pubsub_serializer_avrobin/src/ps_avrobin_serializer_activator.c +++ b/bundles/pubsub/pubsub_serializer_avrobin/src/ps_avrobin_serializer_activator.c @@ -46,7 +46,7 @@ static int psav_start(psav_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_t *props = celix_properties_create(); celix_properties_set(props, PUBSUB_SERIALIZER_TYPE_KEY, PUBSUB_AVROBIN_SERIALIZER_TYPE); - act->serializerSvcId = celix_bundleContext_registerService(ctx, &act->serializerSvc, PUBSUB_SERIALIZER_SERVICE_NAME, props); + act->serializerSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->serializerSvc, PUBSUB_SERIALIZER_SERVICE_NAME, props); } return status; } diff --git a/bundles/pubsub/pubsub_serializer_json/src/ps_json_serializer_activator.c b/bundles/pubsub/pubsub_serializer_json/src/ps_json_serializer_activator.c index 9df8e13f2..afb62505e 100644 --- a/bundles/pubsub/pubsub_serializer_json/src/ps_json_serializer_activator.c +++ b/bundles/pubsub/pubsub_serializer_json/src/ps_json_serializer_activator.c @@ -44,7 +44,7 @@ static int psjs_start(psjs_activator_t *act, celix_bundle_context_t *ctx) { /* Set serializer type */ celix_properties_t *props = celix_properties_create(); celix_properties_set(props, PUBSUB_SERIALIZER_TYPE_KEY, PUBSUB_JSON_SERIALIZER_TYPE); - act->serializerSvcId = celix_bundleContext_registerService(ctx, &act->serializerSvc, PUBSUB_SERIALIZER_SERVICE_NAME, props); + act->serializerSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->serializerSvc, PUBSUB_SERIALIZER_SERVICE_NAME, props); } return status; diff --git a/bundles/pubsub/pubsub_topology_manager/src/pstm_activator.c b/bundles/pubsub/pubsub_topology_manager/src/pstm_activator.c index 347d6471b..1bdfc69f0 100644 --- a/bundles/pubsub/pubsub_topology_manager/src/pstm_activator.c +++ b/bundles/pubsub/pubsub_topology_manager/src/pstm_activator.c @@ -118,7 +118,7 @@ static int pstm_start(pstm_activator_t *act, celix_bundle_context_t *ctx) { act->discListenerSvc.handle = act->manager; act->discListenerSvc.addDiscoveredEndpoint = pubsub_topologyManager_addDiscoveredEndpoint; act->discListenerSvc.removeDiscoveredEndpoint = pubsub_topologyManager_removeDiscoveredEndpoint; - act->discListenerSvcId = celix_bundleContext_registerService(ctx, &act->discListenerSvc, PUBSUB_DISCOVERED_ENDPOINT_LISTENER_SERVICE, NULL); + act->discListenerSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->discListenerSvc, PUBSUB_DISCOVERED_ENDPOINT_LISTENER_SERVICE, NULL); } //register shell command @@ -129,7 +129,7 @@ static int pstm_start(pstm_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::pstm"); celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "pstm [topology|metrics]"); //TODO add search topic/scope option celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "pubsub_topology_info: Overview of Topology information for PubSub"); - act->shellCmdSvcId = celix_bundleContext_registerService(ctx, &act->shellCmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + act->shellCmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->shellCmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); } //TODO add tracker for pubsub_serializer and diff --git a/bundles/remote_services/examples/calculator_service/src/calculator_activator.c b/bundles/remote_services/examples/calculator_service/src/calculator_activator.c index 261169e0e..e39aa4840 100644 --- a/bundles/remote_services/examples/calculator_service/src/calculator_activator.c +++ b/bundles/remote_services/examples/calculator_service/src/calculator_activator.c @@ -44,7 +44,7 @@ celix_status_t calculatorBndStart(struct activator *act, celix_bundle_context_t celix_properties_set(properties, CELIX_FRAMEWORK_SERVICE_VERSION, CALCULATOR_SERVICE_VERSION); celix_properties_set(properties, OSGI_RSA_SERVICE_EXPORTED_CONFIGS, CALCULATOR_CONFIGURATION_TYPE); - act->svcId = celix_bundleContext_registerService(ctx, &act->service, CALCULATOR_SERVICE, properties); + act->svcId = celix_bundleContext_registerServiceAsync(ctx, &act->service, CALCULATOR_SERVICE, properties); } return CELIX_SUCCESS; } diff --git a/bundles/remote_services/examples/calculator_shell/src/calculator_shell_activator.c b/bundles/remote_services/examples/calculator_shell/src/calculator_shell_activator.c index 31e5c49a6..523dab099 100644 --- a/bundles/remote_services/examples/calculator_shell/src/calculator_shell_activator.c +++ b/bundles/remote_services/examples/calculator_shell/src/calculator_shell_activator.c @@ -42,19 +42,19 @@ static celix_status_t calcShell_start(calc_shell_activator_t *activator, celix_b activator->addCmd.executeCommand = addCommand_execute; celix_properties_t *props = celix_properties_create(); celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "add"); - activator->addCmdSvcId = celix_bundleContext_registerService(ctx, &activator->addCmd, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + activator->addCmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &activator->addCmd, CELIX_SHELL_COMMAND_SERVICE_NAME, props); activator->subCmd.handle = ctx; activator->subCmd.executeCommand = subCommand_execute; props = celix_properties_create(); celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "sub"); - activator->subCmdSvcId = celix_bundleContext_registerService(ctx, &activator->subCmd, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + activator->subCmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &activator->subCmd, CELIX_SHELL_COMMAND_SERVICE_NAME, props); activator->sqrtCmd.handle = ctx; activator->sqrtCmd.executeCommand = sqrtCommand_execute; props = celix_properties_create(); celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "sqrt"); - activator->sqrtCmdSvcId = celix_bundleContext_registerService(ctx, &activator->sqrtCmd, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + activator->sqrtCmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &activator->sqrtCmd, CELIX_SHELL_COMMAND_SERVICE_NAME, props); return CELIX_SUCCESS; } diff --git a/bundles/remote_services/examples/remote_example_service/src/remote_example_activator.c b/bundles/remote_services/examples/remote_example_service/src/remote_example_activator.c index 59522e30d..d40163eee 100644 --- a/bundles/remote_services/examples/remote_example_service/src/remote_example_activator.c +++ b/bundles/remote_services/examples/remote_example_service/src/remote_example_activator.c @@ -46,7 +46,7 @@ celix_status_t remoteExampleBndStart(struct activator *act, celix_bundle_context celix_properties_t *properties = celix_properties_create(); celix_properties_set(properties, OSGI_RSA_SERVICE_EXPORTED_INTERFACES, REMOTE_EXAMPLE_NAME); - act->svcId = celix_bundleContext_registerService(ctx, &act->service, REMOTE_EXAMPLE_NAME, properties); + act->svcId = celix_bundleContext_registerServiceAsync(ctx, &act->service, REMOTE_EXAMPLE_NAME, properties); } return CELIX_SUCCESS; } diff --git a/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.c b/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.c index f462d3427..a18b4d2d2 100644 --- a/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.c +++ b/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.c @@ -161,7 +161,7 @@ int remoteExample_createAdditionalRemoteService(remote_example_impl_t* impl) { } else { celix_properties_t *properties = celix_properties_create(); celix_properties_set(properties, OSGI_RSA_SERVICE_EXPORTED_INTERFACES, REMOTE_EXAMPLE_NAME); - long newSvcId = celix_bundleContext_registerService(impl->ctx, &impl->additionalSvc, REMOTE_EXAMPLE_NAME, properties); + long newSvcId = celix_bundleContext_registerServiceAsync(impl->ctx, &impl->additionalSvc, REMOTE_EXAMPLE_NAME, properties); pthread_mutex_lock(&impl->mutex); prevSvcId = impl->additionalSvcId; if (prevSvcId == -1L) { diff --git a/bundles/remote_services/remote_service_admin_dfi/gtest/src/tst_activator.c b/bundles/remote_services/remote_service_admin_dfi/gtest/src/tst_activator.c index a571f1d04..66a977e51 100644 --- a/bundles/remote_services/remote_service_admin_dfi/gtest/src/tst_activator.c +++ b/bundles/remote_services/remote_service_admin_dfi/gtest/src/tst_activator.c @@ -360,7 +360,7 @@ static celix_status_t bndStart(struct activator *act, celix_bundle_context_t* ct } //register test service - act->svcId = celix_bundleContext_registerService(ctx, &act->testSvc, TST_SERVICE_NAME, NULL); + act->svcId = celix_bundleContext_registerServiceAsync(ctx, &act->testSvc, TST_SERVICE_NAME, NULL); return CELIX_SUCCESS; } diff --git a/bundles/remote_services/remote_service_admin_dfi/src/remote_service_admin_activator.c b/bundles/remote_services/remote_service_admin_dfi/src/remote_service_admin_activator.c index 0b470da72..a81ea8153 100644 --- a/bundles/remote_services/remote_service_admin_dfi/src/remote_service_admin_activator.c +++ b/bundles/remote_services/remote_service_admin_dfi/src/remote_service_admin_activator.c @@ -56,7 +56,7 @@ static celix_status_t celix_rsa_start(celix_remote_service_admin_activator_t* ac activator->adminService.importRegistration_getException = importRegistration_getException; activator->adminService.importRegistration_getImportReference = importRegistration_getImportReference; - activator->svcIdRsa = celix_bundleContext_registerService(ctx, &activator->adminService, OSGI_RSA_REMOTE_SERVICE_ADMIN, NULL); + activator->svcIdRsa = celix_bundleContext_registerServiceAsync(ctx, &activator->adminService, OSGI_RSA_REMOTE_SERVICE_ADMIN, NULL); } return status; diff --git a/bundles/shell/shell_wui/src/shell_wui_bundle_activator.c b/bundles/shell/shell_wui/src/shell_wui_bundle_activator.c index d2bfac3bc..b9c46c865 100644 --- a/bundles/shell/shell_wui/src/shell_wui_bundle_activator.c +++ b/bundles/shell/shell_wui/src/shell_wui_bundle_activator.c @@ -77,7 +77,7 @@ static celix_status_t shellWui_activator_start(shell_wui_activator_data_t *data, celix_properties_set(props, WEBSOCKET_ADMIN_URI, "/shell/socket"); data->sockSvc.handle = data; data->sockSvc.data = websocket_data_handler; - data->sockSvcId = celix_bundleContext_registerService(ctx, &data->sockSvc, WEBSOCKET_ADMIN_SERVICE_NAME, props); + data->sockSvcId = celix_bundleContext_registerServiceAsync(ctx, &data->sockSvc, WEBSOCKET_ADMIN_SERVICE_NAME, props); return CELIX_SUCCESS; } diff --git a/examples/celix-examples/http_example/src/http_example_bundle_activator.c b/examples/celix-examples/http_example/src/http_example_bundle_activator.c index 923eda6b0..5142958be 100644 --- a/examples/celix-examples/http_example/src/http_example_bundle_activator.c +++ b/examples/celix-examples/http_example/src/http_example_bundle_activator.c @@ -47,7 +47,7 @@ static celix_status_t httpExample_activator_start(http_example_activator_data_t celix_properties_set(props, WEBSOCKET_ADMIN_URI, "/hello/socket"); data->sockSvc.handle = data; data->sockSvc.ready = websocket_ready_handler; - data->sockSvcId = celix_bundleContext_registerService(ctx, &data->sockSvc, WEBSOCKET_ADMIN_SERVICE_NAME, props); + data->sockSvcId = celix_bundleContext_registerServiceAsync(ctx, &data->sockSvc, WEBSOCKET_ADMIN_SERVICE_NAME, props); return CELIX_SUCCESS; } diff --git a/examples/celix-examples/services_example_c/src/simple_provider_example.c b/examples/celix-examples/services_example_c/src/simple_provider_example.c index 9f1b95c21..d23ac9b4b 100644 --- a/examples/celix-examples/services_example_c/src/simple_provider_example.c +++ b/examples/celix-examples/services_example_c/src/simple_provider_example.c @@ -40,7 +40,7 @@ static celix_status_t activator_start(activator_data_t *data, celix_bundle_conte data->seed = 42; data->svcId = -1L; - data->svcId = celix_bundleContext_registerService(ctx, &data->svc, EXAMPLE_CALC_NAME, NULL); + data->svcId = celix_bundleContext_registerServiceAsync(ctx, &data->svc, EXAMPLE_CALC_NAME, NULL); printf("Registered calc service with service id %li\n", data->svcId); return CELIX_SUCCESS; diff --git a/examples/celix-examples/track_tracker_example/src/activator.c b/examples/celix-examples/track_tracker_example/src/activator.c index c5a05e578..1334a7c2f 100644 --- a/examples/celix-examples/track_tracker_example/src/activator.c +++ b/examples/celix-examples/track_tracker_example/src/activator.c @@ -86,7 +86,7 @@ celix_status_t activator_start(activator_data_t* act, celix_bundle_context_t *ct act->svc.handle = act; act->svc.calc = calc; //note only triggers on calcTrk1, because of filter restrictions - act->svcId = celix_bundleContext_registerService(ctx, &act->svc, CALC_SERVICE_NAME, NULL); + act->svcId = celix_bundleContext_registerServiceAsync(ctx, &act->svc, CALC_SERVICE_NAME, NULL); return CELIX_SUCCESS; } From ea6a979c451b19d2b4ac8d123c7dedf79f725847 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Fri, 2 Jun 2023 14:31:18 +0800 Subject: [PATCH 06/21] Add useActiveBundles. It fixes thread-safety issue in dependency manager (see #561), a null string logging issue in pubsub's topology manager, and a potential crash in query_command.c. --- .../src/pubsub_topology_manager.c | 2 +- bundles/shell/shell/src/query_command.c | 3 +- libs/framework/include/celix_bundle.h | 2 + libs/framework/include/celix_framework.h | 41 +++++++++++++++++-- .../src/dm_dependency_manager_impl.c | 27 +++++------- libs/framework/src/framework.c | 22 +++++++--- 6 files changed, 69 insertions(+), 28 deletions(-) diff --git a/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c b/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c index a204668b8..c73cc5876 100644 --- a/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c +++ b/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c @@ -1344,7 +1344,7 @@ static celix_status_t pubsub_topologyManager_metrics(pubsub_topology_manager_t * if (sm->msgMetrics[j].nrOfMessagesSend == 0 && sm->msgMetrics[j].nrOfMessagesSendFailed == 0 && sm->msgMetrics[j].nrOfSerializationErrors == 0) { continue; } - const char *bndName = NULL; + const char *bndName = "inactive"; celix_bundleContext_useBundle(manager->context, sm->msgMetrics->bndId, &bndName, fetchBundleName); fprintf(os, " |- Message '%s' from bundle '%s' (%li):\n", sm->msgMetrics[j].typeFqn, bndName, sm->msgMetrics->bndId); fprintf(os, " |- msg type = 0x%X\n", sm->msgMetrics[j].typeId); diff --git a/bundles/shell/shell/src/query_command.c b/bundles/shell/shell/src/query_command.c index ff7f7a8a1..490513b92 100644 --- a/bundles/shell/shell/src/query_command.c +++ b/bundles/shell/shell/src/query_command.c @@ -20,6 +20,7 @@ #include #include +#include "celix_framework.h" #include "celix_shell_constants.h" #include "celix_bundle_context.h" #include "std_commands.h" @@ -129,7 +130,7 @@ static void queryCommand_callback(void *handle, const celix_bundle_t *bnd) { static void queryCommand_listServicesForBundle(celix_bundle_context_t *ctx, long bndId, struct bundle_callback_data *data, const struct query_options *opts, FILE *sout, FILE *serr) { - bool called = celix_bundleContext_useBundle(ctx, bndId, data, queryCommand_callback); + bool called = celix_framework_useBundle(celix_bundleContext_getFramework(ctx), true, bndId, data, queryCommand_callback); if (!called) { fprintf(serr, "Bundle %li not installed!", bndId); } diff --git a/libs/framework/include/celix_bundle.h b/libs/framework/include/celix_bundle.h index 63121eda8..fb3487094 100644 --- a/libs/framework/include/celix_bundle.h +++ b/libs/framework/include/celix_bundle.h @@ -177,6 +177,8 @@ typedef struct celix_bundle_service_tracker_list_entry { /** * Returns a array list of service tracker info entries for this bundle. * + * @warning It requires a valid bundle context. Calling it for an inactive bundle will lead to crash. + * * @param ctx The bundle context * @param bndId The bundle id for which the services should be listed * @return A celix array list with celix_bundle_service_tracker_list_entry_t*. Caller is owner of the celix array. diff --git a/libs/framework/include/celix_framework.h b/libs/framework/include/celix_framework.h index 2bfbd114f..5f3d338ae 100644 --- a/libs/framework/include/celix_framework.h +++ b/libs/framework/include/celix_framework.h @@ -74,22 +74,51 @@ CELIX_FRAMEWORK_EXPORT celix_bundle_context_t* celix_framework_getFrameworkConte CELIX_FRAMEWORK_EXPORT celix_bundle_t* celix_framework_getFrameworkBundle(const celix_framework_t *fw); /** - * @brief * @brief Use the currently installed bundles. + * @brief Use the currently installed bundles. * The provided callback will be called for all the currently installed bundles. * - * @param ctx The bundle context. + * @warning It is dangerous to use the provided bundle's context from the callback, since it may be invalid for an inactive bundle. + * + * @param fw The framework. * @param includeFrameworkBundle If true the callback will also be triggered for the framework bundle. * @param callbackHandle The data pointer, which will be used in the callbacks * @param use The callback which will be called for the currently installed bundles. * The bundle pointers are only guaranteed to be valid during the callback. * @return The number of times the use callback is called. */ -CELIX_FRAMEWORK_EXPORT size_t celix_framework_useBundles(celix_framework_t *fw, bool includeFrameworkBundle, void *callbackHandle, void(*use)(void *handle, const celix_bundle_t *bnd)); +CELIX_FRAMEWORK_EXPORT size_t celix_framework_useBundles(celix_framework_t* fw, + bool includeFrameworkBundle, + void* callbackHandle, + void (*use)(void* handle, const celix_bundle_t* bnd)); + +/** + * @brief Use the currently active bundles. + * The provided callback will be called for all the currently active bundles. + * + * @warning Calling synchronous bundle-state changing functions (e.g. celix_bundleContext_stopBundle) from the callback + * will lead to deadlocks. + * + * @param fw The framework. + * @param includeFrameworkBundle If true the callback will also be triggered for the framework bundle. + * @param callbackHandle The data pointer, which will be used in the callbacks + * @param use The callback which will be called for the currently active bundles. + * The bundle state is guaranteed to be active during the callback. + * @return The number of times the use callback is called. + */ +CELIX_FRAMEWORK_EXPORT size_t celix_framework_useActiveBundles(celix_framework_t* fw, + bool includeFrameworkBundle, + void* callbackHandle, + void (*use)(void* handle, const celix_bundle_t* bnd)); /** * @brief Use the bundle with the provided bundle id * The provided callback will be called if the bundle is found. * + * @warning Calling synchronous bundle-state changing functions (e.g. celix_bundleContext_stopBundle) with onlyActive=true + * from the callback will lead to deadlocks. Using a bundle's context, e.g. calling celix_bundle_listServiceTrackers, + * with onlyActive=false from the callback is generally dangerous. However, in some cases, the target bundle's context is guaranteed to be valid, + * e.g. the bundle is providing a service protected by a service tracker. + * * @param fw The framework. * @param onlyActive If true only starting and active bundles will trigger the callback. * @param bundleId The bundle id. @@ -98,7 +127,11 @@ CELIX_FRAMEWORK_EXPORT size_t celix_framework_useBundles(celix_framework_t *fw, * The bundle pointers are only guaranteed to be valid during the callback. * @return Returns true if the bundle is found and the callback is called. */ -CELIX_FRAMEWORK_EXPORT bool celix_framework_useBundle(celix_framework_t *fw, bool onlyActive, long bndId, void *callbackHandle, void(*use)(void *handle, const celix_bundle_t *bnd)); +CELIX_FRAMEWORK_EXPORT bool celix_framework_useBundle(celix_framework_t* fw, + bool onlyActive, + long bndId, + void* callbackHandle, + void (*use)(void* handle, const celix_bundle_t* bnd)); /** * @brief Check whether a bundle is installed. diff --git a/libs/framework/src/dm_dependency_manager_impl.c b/libs/framework/src/dm_dependency_manager_impl.c index 21a77d450..006f97d26 100644 --- a/libs/framework/src/dm_dependency_manager_impl.c +++ b/libs/framework/src/dm_dependency_manager_impl.c @@ -182,10 +182,6 @@ celix_status_t celix_dependencyManager_removeAllComponentsAsync(celix_dependency static void celix_dm_getInfoCallback(void *handle, const celix_bundle_t *bnd) { celix_dependency_manager_info_t **out = handle; - if (celix_bundle_getState(bnd) != CELIX_BUNDLE_STATE_ACTIVE) { - return; - } - celix_bundle_context_t *context = NULL; bundle_getContext((celix_bundle_t*)bnd, &context); celix_dependency_manager_t *mng = celix_bundleContext_getDependencyManager(context); @@ -211,18 +207,15 @@ static void celix_dm_getInfoCallback(void *handle, const celix_bundle_t *bnd) { } celix_dependency_manager_info_t* celix_dependencyManager_createInfo(celix_dependency_manager_t *manager, long bndId) { - celix_dependency_manager_info_t *info = NULL; - celix_bundleContext_useBundle(manager->ctx, bndId, &info, celix_dm_getInfoCallback); - return info; + celix_dependency_manager_info_t* info = NULL; + celix_framework_useBundle( + celix_bundleContext_getFramework(manager->ctx), true /*onlyActive*/, bndId, &info, celix_dm_getInfoCallback); + return info; } static void celix_dm_getInfosCallback(void* handle, const celix_bundle_t* bnd) { celix_array_list_t* infos = handle; - if (celix_bundle_getState(bnd) != CELIX_BUNDLE_STATE_ACTIVE) { - return; - } - celix_bundle_context_t* context = NULL; bundle_getContext((celix_bundle_t*)bnd, &context); celix_dependency_manager_t* mng = celix_bundleContext_getDependencyManager(context); @@ -253,14 +246,14 @@ static void celix_dependencyManager_destroyInfoCallback(void *data, celix_array_ } celix_array_list_t * celix_dependencyManager_createInfos(celix_dependency_manager_t* manager) { - celix_array_list_create_options_t opts = CELIX_EMPTY_ARRAY_LIST_CREATE_OPTIONS; - opts.removedCallbackData = manager; - opts.removedCallback = celix_dependencyManager_destroyInfoCallback; + celix_array_list_create_options_t opts = CELIX_EMPTY_ARRAY_LIST_CREATE_OPTIONS; + opts.removedCallbackData = manager; + opts.removedCallback = celix_dependencyManager_destroyInfoCallback; celix_array_list_t* infos = celix_arrayList_createWithOptions(&opts); - celix_framework_t* fw = celix_bundleContext_getFramework(manager->ctx); - celix_framework_useBundles(fw, true, infos, celix_dm_getInfosCallback); - return infos; + celix_framework_t* fw = celix_bundleContext_getFramework(manager->ctx); + celix_framework_useActiveBundles(fw, true, infos, celix_dm_getInfosCallback); + return infos; } static void celix_dm_allComponentsActiveCallback(void *handle, const celix_bundle_t *bnd) { diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c index 8671abac9..0c6c31b85 100644 --- a/libs/framework/src/framework.c +++ b/libs/framework/src/framework.c @@ -1513,8 +1513,7 @@ static celix_status_t frameworkActivator_destroy(void * userData, bundle_context ********************************************************************************************************************** **********************************************************************************************************************/ - -size_t celix_framework_useBundles(framework_t *fw, bool includeFrameworkBundle, void *callbackHandle, void(*use)(void *handle, const bundle_t *bnd)) { +static size_t celix_framework_useBundlesInternal(framework_t *fw, bool includeFrameworkBundle, bool onlyActive, void *callbackHandle, void(*use)(void *handle, const bundle_t *bnd)) { size_t count = 0; celix_array_list_t *bundleIds = celix_arrayList_create(); @@ -1534,7 +1533,7 @@ size_t celix_framework_useBundles(framework_t *fw, bool includeFrameworkBundle, size = celix_arrayList_size(bundleIds); for (int i = 0; i < size; ++i) { long bndId = celix_arrayList_getLong(bundleIds, i); - bool called = celix_framework_useBundle(fw, false, bndId, callbackHandle, use); + bool called = celix_framework_useBundle(fw, onlyActive, bndId, callbackHandle, use); if (called) { ++count; } @@ -1542,6 +1541,15 @@ size_t celix_framework_useBundles(framework_t *fw, bool includeFrameworkBundle, celix_arrayList_destroy(bundleIds); return count; + +} + +size_t celix_framework_useBundles(framework_t *fw, bool includeFrameworkBundle, void *callbackHandle, void(*use)(void *handle, const bundle_t *bnd)) { + return celix_framework_useBundlesInternal(fw, includeFrameworkBundle, false, callbackHandle, use); +} + +size_t celix_framework_useActiveBundles(framework_t *fw, bool includeFrameworkBundle, void *callbackHandle, void(*use)(void *handle, const bundle_t *bnd)) { + return celix_framework_useBundlesInternal(fw, includeFrameworkBundle, true, callbackHandle, use); } bool celix_framework_useBundle(framework_t *fw, bool onlyActive, long bundleId, void *callbackHandle, void(*use)(void *handle, const bundle_t *bnd)) { @@ -1551,7 +1559,9 @@ bool celix_framework_useBundle(framework_t *fw, bool onlyActive, long bundleId, bundleId); if (entry != NULL) { - celixThreadRwlock_readLock(&entry->fsmMutex); + if (onlyActive) { + celixThreadRwlock_readLock(&entry->fsmMutex); + } celix_bundle_state_e bndState = celix_bundle_getState(entry->bnd); if (onlyActive && (bndState == CELIX_BUNDLE_STATE_ACTIVE || bndState == CELIX_BUNDLE_STATE_STARTING)) { use(callbackHandle, entry->bnd); @@ -1560,7 +1570,9 @@ bool celix_framework_useBundle(framework_t *fw, bool onlyActive, long bundleId, use(callbackHandle, entry->bnd); called = true; } - celixThreadRwlock_unlock(&entry->fsmMutex); + if (onlyActive) { + celixThreadRwlock_unlock(&entry->fsmMutex); + } celix_framework_bundleEntry_decreaseUseCount(entry); } else { framework_logIfError(fw->logger, CELIX_FRAMEWORK_EXCEPTION, NULL, "Bundle with id %li is not installed", bundleId); From cccf30aac326a919727f0e164a474004921b9756 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Fri, 2 Jun 2023 23:00:57 +0800 Subject: [PATCH 07/21] Add full support of bundle update. It fixes #563 and #557. --- ...undleArchiveWithErrorInjectionTestSuite.cc | 42 +---- .../src/CelixBundleContextBundlesTestSuite.cc | 33 ++++ .../gtest/src/CelixFrameworkTestSuite.cc | 18 +- libs/framework/include/celix_bundle_context.h | 14 +- libs/framework/include/celix_framework.h | 32 ++-- libs/framework/src/bundle.c | 26 +-- libs/framework/src/bundle_archive.c | 39 +---- libs/framework/src/bundle_revision.c | 27 ++- libs/framework/src/framework.c | 157 ++++++++---------- .../src/framework_bundle_lifecycle_handler.c | 6 +- libs/framework/src/framework_private.h | 4 +- 11 files changed, 168 insertions(+), 230 deletions(-) diff --git a/libs/framework/gtest/src/BundleArchiveWithErrorInjectionTestSuite.cc b/libs/framework/gtest/src/BundleArchiveWithErrorInjectionTestSuite.cc index 6fc2118f7..d0363d027 100644 --- a/libs/framework/gtest/src/BundleArchiveWithErrorInjectionTestSuite.cc +++ b/libs/framework/gtest/src/BundleArchiveWithErrorInjectionTestSuite.cc @@ -229,44 +229,4 @@ TEST_F(CelixBundleArchiveErrorInjectionTestSuite, ArchiveCreateErrorTest) { teardownErrorInjectors(); EXPECT_EQ(CELIX_SUCCESS, celix_bundleCache_destroy(cache)); -} - -TEST_F(CelixBundleArchiveErrorInjectionTestSuite, ArchiveReviseErrorTest) { - celix_bundle_cache_t* cache = nullptr; - createCache(&cache); - bundle_archive_t* archive = nullptr; - - // revision creation failure - EXPECT_EQ(CELIX_SUCCESS, - celix_bundleArchive_create(&fw, TEST_ARCHIVE_ROOT, 1, SIMPLE_TEST_BUNDLE1_LOCATION, &archive)); - EXPECT_NE(nullptr, archive); - celix_ei_expect_calloc((void*)celix_bundleRevision_create, 0, nullptr); - EXPECT_EQ(CELIX_ENOMEM, bundleArchive_revise(archive, SIMPLE_TEST_BUNDLE1_LOCATION, nullptr)); - EXPECT_EQ(CELIX_SUCCESS, bundleArchive_destroy(archive)); - EXPECT_EQ(CELIX_SUCCESS, celix_utils_deleteDirectory(TEST_ARCHIVE_ROOT, nullptr)); - teardownErrorInjectors(); - - // manifest clone failure - EXPECT_EQ(CELIX_SUCCESS, - celix_bundleArchive_create(&fw, TEST_ARCHIVE_ROOT, 1, SIMPLE_TEST_BUNDLE1_LOCATION, &archive)); - EXPECT_NE(nullptr, archive); - celix_ei_expect_malloc((void*)manifest_clone, 1, nullptr); - EXPECT_EQ(CELIX_ENOMEM, bundleArchive_revise(archive, SIMPLE_TEST_BUNDLE1_LOCATION, nullptr)); - EXPECT_EQ(CELIX_SUCCESS, bundleArchive_destroy(archive)); - EXPECT_EQ(CELIX_SUCCESS, celix_utils_deleteDirectory(TEST_ARCHIVE_ROOT, nullptr)); - teardownErrorInjectors(); - - // extract zip data failure - EXPECT_EQ(CELIX_SUCCESS, - celix_bundleArchive_create(&fw, TEST_ARCHIVE_ROOT, 1, SIMPLE_TEST_BUNDLE1_LOCATION, &archive)); - EXPECT_NE(nullptr, archive); - celix_ei_expect_celix_utils_extractZipFile((void*)celix_framework_utils_extractBundle, 1, CELIX_FILE_IO_EXCEPTION); - usleep(10000); // sleep to ensure that the last modified time is different (otherwise the revision is not updated - celix_utils_touch(SIMPLE_TEST_BUNDLE1_LOCATION); - EXPECT_EQ(CELIX_FILE_IO_EXCEPTION, bundleArchive_revise(archive, SIMPLE_TEST_BUNDLE1_LOCATION, nullptr)); - EXPECT_EQ(CELIX_SUCCESS, bundleArchive_destroy(archive)); - EXPECT_EQ(CELIX_SUCCESS, celix_utils_deleteDirectory(TEST_ARCHIVE_ROOT, nullptr)); - teardownErrorInjectors(); - - EXPECT_EQ(CELIX_SUCCESS, celix_bundleCache_destroy(cache)); -} +} \ No newline at end of file diff --git a/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc b/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc index f76720878..0d222bb7d 100644 --- a/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc +++ b/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc @@ -286,6 +286,39 @@ TEST_F(CelixBundleContextBundlesTestSuite, InstallAndUnloadBundlesTest) { ASSERT_TRUE(bndId3 == bndId6); //bundle cache -> reuse of bundle id. } +TEST_F(CelixBundleContextBundlesTestSuite, UpdateBundlesTest) { + long bndId1 = celix_bundleContext_installBundle(ctx, TEST_BND1_LOC, true); + ASSERT_TRUE(bndId1 >= 0L); + ASSERT_TRUE(celix_bundleContext_isBundleInstalled(ctx, bndId1)); + ASSERT_TRUE(celix_bundleContext_isBundleActive(ctx, bndId1)); + + ASSERT_TRUE(celix_bundleContext_updateBundle(ctx, bndId1, NULL)); + ASSERT_TRUE(celix_bundleContext_isBundleInstalled(ctx, bndId1)); + ASSERT_TRUE(celix_bundleContext_isBundleActive(ctx, bndId1)); + + ASSERT_TRUE(celix_bundleContext_stopBundle(ctx, bndId1)); + ASSERT_TRUE(celix_bundleContext_updateBundle(ctx, bndId1, NULL)); + ASSERT_TRUE(celix_bundleContext_isBundleInstalled(ctx, bndId1)); + ASSERT_FALSE(celix_bundleContext_isBundleActive(ctx, bndId1)); + + long bndId2 = celix_bundleContext_installBundle(ctx, TEST_BND2_LOC, false); + ASSERT_TRUE(bndId2 >= 0L); + ASSERT_FALSE(celix_bundleContext_updateBundle(ctx, bndId1, TEST_BND2_LOC)); + ASSERT_TRUE(celix_bundleContext_isBundleInstalled(ctx, bndId1)); + ASSERT_EQ(bndId2, celix_bundleContext_installBundle(ctx, TEST_BND2_LOC, false)); + ASSERT_TRUE(celix_bundleContext_uninstallBundle(ctx, bndId2)); + + auto sn1 = celix_bundleContext_getBundleSymbolicName(ctx, bndId1); + ASSERT_TRUE(celix_bundleContext_updateBundle(ctx, bndId1, TEST_BND2_LOC)); + auto sn2 = celix_bundleContext_getBundleSymbolicName(ctx, bndId1); + ASSERT_STRNE(sn1, sn2); + free(sn2); + free(sn1); + + ASSERT_TRUE(celix_bundleContext_unloadBundle(ctx, bndId1)); + ASSERT_FALSE(celix_bundleContext_updateBundle(ctx, bndId1, NULL)); +} + TEST_F(CelixBundleContextBundlesTestSuite, StartBundleWithException) { long bndId = celix_bundleContext_installBundle(ctx, TEST_BND_WITH_EXCEPTION_LOC, true); ASSERT_TRUE(bndId > 0); //bundle is installed, but not started diff --git a/libs/framework/gtest/src/CelixFrameworkTestSuite.cc b/libs/framework/gtest/src/CelixFrameworkTestSuite.cc index 89c20f619..95e7d434a 100644 --- a/libs/framework/gtest/src/CelixFrameworkTestSuite.cc +++ b/libs/framework/gtest/src/CelixFrameworkTestSuite.cc @@ -79,17 +79,29 @@ TEST_F(CelixFrameworkTestSuite, EventQueueTest) { EXPECT_EQ(4, count); } -TEST_F(CelixFrameworkTestSuite, AsyncInstallStartStopAndUninstallBundleTest) { +TEST_F(CelixFrameworkTestSuite, AsyncInstallStartStopUpdateAndUninstallBundleTest) { long bndId = celix_framework_installBundleAsync(framework.get(), SIMPLE_TEST_BUNDLE1_LOCATION, false); EXPECT_GE(bndId, 0); EXPECT_TRUE(celix_framework_isBundleInstalled(framework.get(), bndId)); EXPECT_FALSE(celix_framework_isBundleActive(framework.get(), bndId)); - celix_framework_startBundle(framework.get(), bndId); + celix_framework_updateBundleAsync(framework.get(), bndId, NULL); + std::this_thread::sleep_for(std::chrono::milliseconds{100}); + EXPECT_FALSE(celix_framework_isBundleActive(framework.get(), bndId)); + + celix_framework_startBundleAsync(framework.get(), bndId); std::this_thread::sleep_for(std::chrono::milliseconds{100}); EXPECT_TRUE(celix_framework_isBundleActive(framework.get(), bndId)); - celix_framework_stopBundle(framework.get(), bndId); + celix_framework_updateBundleAsync(framework.get(), bndId, NULL); + std::this_thread::sleep_for(std::chrono::milliseconds{100}); + EXPECT_TRUE(celix_framework_isBundleActive(framework.get(), bndId)); + + celix_framework_stopBundleAsync(framework.get(), bndId); + std::this_thread::sleep_for(std::chrono::milliseconds{100}); + EXPECT_FALSE(celix_framework_isBundleActive(framework.get(), bndId)); + + celix_framework_updateBundleAsync(framework.get(), bndId, NULL); std::this_thread::sleep_for(std::chrono::milliseconds{100}); EXPECT_FALSE(celix_framework_isBundleActive(framework.get(), bndId)); diff --git a/libs/framework/include/celix_bundle_context.h b/libs/framework/include/celix_bundle_context.h index fc73b1805..3d3d71e1f 100644 --- a/libs/framework/include/celix_bundle_context.h +++ b/libs/framework/include/celix_bundle_context.h @@ -952,22 +952,23 @@ CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_stopBundle(celix_bundle_context_ CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_startBundle(celix_bundle_context_t *ctx, long bndId); /** - * @brief Update the bundle with the provided bundle id async. + * @brief Update the bundle with the provided bundle id. * * This will do the following: - * - stop the bundle (if needed); - * - update the bundle revision if a newer bundle zip if found; - * - start the bundle, if it was started before the update. + * - uninstall the bundle with the specified bundle id; + * - reinstall the bundle from the specified location with the specified bundle id; + * - start the bundle, if it was previously active. * * Will silently ignore bundle ids < 0. * + * Note if specified bundle location already exists in the bundle cache but with a different bundle id, the bundle + * will NOT be reinstalled, and the update is cancelled. + * * If this function is called on the Celix event thread, the actual updating of the bundle will be done async and * on a separate thread. * If this function is called from a different thread than the Celix event thread, then the function will * return after the bundle update is completed. * - * @warning Update bundle is not yet fully supported. Use at your own risk. - * * @param ctx The bundle context * @param bndId The bundle id to update. * @param updatedBundleUrl The optional updated bundle url to the bundle zip file. If NULL, the existing bundle url @@ -986,7 +987,6 @@ CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_updateBundle(celix_bundle_contex */ CELIX_FRAMEWORK_EXPORT char* celix_bundleContext_getBundleSymbolicName(celix_bundle_context_t *ctx, long bndId); - /** * @brief Track bundles. * diff --git a/libs/framework/include/celix_framework.h b/libs/framework/include/celix_framework.h index 5f3d338ae..ad833ce5d 100644 --- a/libs/framework/include/celix_framework.h +++ b/libs/framework/include/celix_framework.h @@ -186,18 +186,19 @@ CELIX_FRAMEWORK_EXPORT bool celix_framework_unloadBundle(celix_framework_t *fw, * @brief Update the bundle with the provided bundle id. * * This will do the following: - * - stop the bundle (if needed); - * - update the bundle revision if a newer bundle zip if found; - * - start the bundle, if it was started. + * - uninstall the bundle with the specified bundle id; + * - reinstall the bundle from the specified location with the specified bundle id; + * - start the bundle, if it was previously active. * * Will silently ignore bundle ids < 0. * - * @warning Update bundle is not yet fully supported. Use at your own risk. + * Note if specified bundle location already exists in the bundle cache but with a different bundle id, the bundle + * will NOT be reinstalled, and the update is cancelled. * - * @param fw The Celix framework - * @parma bndId the bundle id to update. - * @param updatedBundleUrl The optional updated bundle url to the bundle zip file. If NULL, the existing bundle url - * from the bundle cache will be used. + * @param [in] fw The Celix framework + * @param [in] bndId the bundle id to update. + * @param [in] updatedBundleUrl The optional updated bundle url to the bundle zip file. + * If NULL, the existing bundle url from the bundle cache will be used. * @return true if the bundle is correctly updated. False if not. */ CELIX_FRAMEWORK_EXPORT bool celix_framework_updateBundle(celix_framework_t *fw, long bndId, const char* updatedBundleUrl); @@ -239,17 +240,18 @@ CELIX_FRAMEWORK_EXPORT long celix_framework_installBundleAsync(celix_framework_t * @brief Update the bundle with the provided bundle id async. * * This will do the following: - * - stop the bundle (if needed); - * - update the bundle revision if a newer bundle zip if found; - * - start the bundle, if it was started. + * - uninstall the bundle with the specified bundle id; + * - reinstall the bundle from the specified location with the specified bundle id; + * - start the bundle, if it was previously active. * * Will silently ignore bundle ids < 0. * - * @warning Update bundle is not yet fully supported. Use at your own risk. + * Note if specified bundle location already exists in the bundle cache but with a different bundle id, the bundle + * will NOT be reinstalled, and the update is cancelled. * - * @param fw The Celix framework - * @parma bndId the bundle id to update. - * @param updatedBundleUrl The optional updated bundle url to the bundle zip file. If NULL, the existing bundle url + * @param [in] fw The Celix framework + * @param [in] bndId the bundle id to update. + * @param [in] updatedBundleUrl The optional updated bundle url to the bundle zip file. If NULL, the existing bundle url * from the bundle cache will be used. */ CELIX_FRAMEWORK_EXPORT void celix_framework_updateBundleAsync(celix_framework_t *fw, long bndId, const char* updatedBundleUrl); diff --git a/libs/framework/src/bundle.c b/libs/framework/src/bundle.c index 64eaa2410..083a69447 100644 --- a/libs/framework/src/bundle.c +++ b/libs/framework/src/bundle.c @@ -280,30 +280,8 @@ celix_status_t bundle_setPersistentStateUninstalled(bundle_pt bundle) { } celix_status_t bundle_revise(bundle_pt bundle, const char * location, const char *inputFile) { - celix_status_t status; - - bundle_archive_pt archive = NULL; - status = bundle_getArchive(bundle, &archive); - if (status == CELIX_SUCCESS) { - status = bundleArchive_revise(archive, location, inputFile); - if (status == CELIX_SUCCESS) { - module_pt module; - status = bundle_createModule(bundle, &module); - if (status == CELIX_SUCCESS) { - status = bundle_addModule(bundle, module); - } else { - bool rolledback; - status = bundleArchive_rollbackRevise(archive, &rolledback); - if (status == CELIX_SUCCESS) { - status = CELIX_BUNDLE_EXCEPTION; - } - } - } - } - - framework_logIfError(bundle->framework->logger, status, NULL, "Failed to revise bundle"); - - return status; + fw_log(bundle->framework->logger, CELIX_LOG_LEVEL_DEBUG, "Usage of bundle_revise is deprecated and no longer needed. Called for bundle %s", bundle->symbolicName); + return CELIX_SUCCESS; } celix_status_t bundle_addModule(bundle_pt bundle, module_pt module) { diff --git a/libs/framework/src/bundle_archive.c b/libs/framework/src/bundle_archive.c index aec52ce41..818d03a6c 100644 --- a/libs/framework/src/bundle_archive.c +++ b/libs/framework/src/bundle_archive.c @@ -433,46 +433,11 @@ celix_status_t bundleArchive_setLastModified(bundle_archive_pt archive __attribu celix_utils_freeStringIfNotEqual(manifestPathBuffer, manifestPath); return status; } -//LCOV_EXCL_STOP celix_status_t bundleArchive_revise(bundle_archive_pt archive, const char * location __attribute__((unused)), const char *updatedBundleUrl) { - celixThreadMutex_lock(&archive->lock); - - const char* updateUrl = archive->location; - if (updatedBundleUrl != NULL && strcmp(updateUrl, updatedBundleUrl) != 0) { - fw_log(archive->fw->logger, CELIX_LOG_LEVEL_INFO, "Updating bundle archive bundle url location to %s", updatedBundleUrl); - updateUrl = updatedBundleUrl; - } - - const char* reason = NULL; - celix_status_t status = celix_bundleArchive_extractBundle(archive, updateUrl); - if (status == CELIX_SUCCESS) { - bundle_revision_t* current = archive->revision; - bundle_revision_t* revised = bundleRevision_revise(current, updateUrl); - if (revised != NULL) { - archive->revision = revised; - bundleRevision_destroy(current); - } else { - status = CELIX_ENOMEM; - reason = "bundle revision creation"; - } - } else { - reason = "bundle extraction"; - } - if (status != CELIX_SUCCESS) { - goto revise_finished; - } - if (archive->location != updateUrl) { - free(archive->location); - archive->location = celix_utils_strdup(updateUrl); - } -revise_finished: - celixThreadMutex_unlock(&archive->lock); - framework_logIfError(archive->fw->logger, status, reason, "Cannot update bundle archive %s", updateUrl); - return status; + fw_log(archive->fw->logger, CELIX_LOG_LEVEL_ERROR, "Revise not supported."); + return CELIX_BUNDLE_EXCEPTION; } - -//LCOV_EXCL_START celix_status_t bundleArchive_rollbackRevise(bundle_archive_pt archive, bool* rolledback) { *rolledback = true; fw_log(archive->fw->logger, CELIX_LOG_LEVEL_ERROR, "Revise rollback not supported."); diff --git a/libs/framework/src/bundle_revision.c b/libs/framework/src/bundle_revision.c index b0bdbbdef..8b0a68b7e 100644 --- a/libs/framework/src/bundle_revision.c +++ b/libs/framework/src/bundle_revision.c @@ -52,15 +52,6 @@ celix_status_t celix_bundleRevision_create(celix_framework_t* fw, const char *ro return status; } -bundle_revision_t* bundleRevision_revise(const bundle_revision_t* rev, const char* updatedBundleUrl) { - bundle_revision_pt newRev = NULL; - manifest_pt clonedManifest = manifest_clone(rev->manifest); - if (clonedManifest) { - celix_bundleRevision_create(rev->fw, rev->root, updatedBundleUrl, clonedManifest, &newRev); - } - return newRev; -} - celix_status_t bundleRevision_destroy(bundle_revision_pt revision) { if (revision != NULL) { manifest_destroy(revision->manifest); @@ -71,6 +62,18 @@ celix_status_t bundleRevision_destroy(bundle_revision_pt revision) { return CELIX_SUCCESS; } +celix_status_t bundleRevision_getManifest(const bundle_revision_t* revision, manifest_pt* manifest) { + *manifest = revision->manifest; + return CELIX_SUCCESS; +} + +//LCOV_EXCL_START +bundle_revision_t* bundleRevision_revise(const bundle_revision_t* rev, const char* updatedBundleUrl) { + fw_log(rev->fw->logger, CELIX_LOG_LEVEL_ERROR, "Revision revise unsupported."); + return NULL; +} + + celix_status_t bundleRevision_getNumber(const bundle_revision_t* revision, long *revisionNr) { *revisionNr = 1; //note revision nr is deprecated return CELIX_SUCCESS; @@ -86,11 +89,6 @@ celix_status_t bundleRevision_getRoot(const bundle_revision_t* revision, const c return CELIX_SUCCESS; } -celix_status_t bundleRevision_getManifest(const bundle_revision_t* revision, manifest_pt* manifest) { - *manifest = revision->manifest; - return CELIX_SUCCESS; -} - celix_status_t bundleRevision_getHandles(const bundle_revision_t* revision __attribute__((unused)), celix_array_list_t** handles) { //nop, usage deprecated if (handles) { @@ -98,4 +96,5 @@ celix_status_t bundleRevision_getHandles(const bundle_revision_t* revision __att } return CELIX_SUCCESS; } +//LCOV_EXCL_STOP diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c index 0c6c31b85..e730133c9 100644 --- a/libs/framework/src/framework.c +++ b/libs/framework/src/framework.c @@ -239,7 +239,11 @@ celix_status_t framework_create(framework_pt *out, celix_properties_t* config) { celixThreadMutex_create(&framework->dispatcher.mutex, NULL); celixThreadMutex_create(&framework->frameworkListenersLock, NULL); celixThreadMutex_create(&framework->bundleListenerLock, NULL); - celixThreadMutex_create(&framework->installLock, NULL); + celix_thread_mutexattr_t muAttr; + celixThreadMutexAttr_create(&muAttr); + celixThreadMutexAttr_settype(&muAttr, CELIX_THREAD_MUTEX_RECURSIVE); + celixThreadMutex_create(&framework->installLock, &muAttr); + celixThreadMutexAttr_destroy(&muAttr); celixThreadMutex_create(&framework->installedBundles.mutex, NULL); celixThreadCondition_init(&framework->dispatcher.cond, NULL); framework->dispatcher.active = true; @@ -625,7 +629,7 @@ bool celix_framework_getConfigPropertyAsBool(celix_framework_t* framework, const } celix_status_t -celix_framework_installBundleInternal(celix_framework_t* framework, const char* bndLoc, long* bundleOut) { +celix_framework_installBundleInternal(celix_framework_t* framework, const char* bndLoc, long* bndId) { celix_status_t status = CELIX_SUCCESS; celix_bundle_t* bundle = NULL; long id = -1L; @@ -650,16 +654,19 @@ celix_framework_installBundleInternal(celix_framework_t* framework, const char* celixThreadMutex_lock(&framework->installLock); if (status == CELIX_SUCCESS) { - id = framework_getBundle(framework, bndLoc); - if (id != -1L) { - celix_framework_bundleEntry_decreaseUseCount(fwBundleEntry); - *bundleOut = id; - celixThreadMutex_unlock(&framework->installLock); - return CELIX_SUCCESS; + if (*bndId == -1L) { + id = framework_getBundle(framework, bndLoc); + if (id != -1L) { + celix_framework_bundleEntry_decreaseUseCount(fwBundleEntry); + celixThreadMutex_unlock(&framework->installLock); + *bndId = id; + return CELIX_SUCCESS; + } + long alreadyExistingBndId = celix_bundleCache_findBundleIdForLocation(framework->cache, bndLoc); + id = alreadyExistingBndId == -1 ? framework_getNextBundleId(framework) : alreadyExistingBndId; + } else { + id = *bndId; } - - long alreadyExistingBndId = celix_bundleCache_findBundleIdForLocation(framework->cache, bndLoc); - id = alreadyExistingBndId == -1 ? framework_getNextBundleId(framework) : alreadyExistingBndId; bundle_archive_t* archive = NULL; status = CELIX_DO_IF(status, celix_bundleCache_createArchive(framework->cache, id, bndLoc, &archive)); status = CELIX_DO_IF(status, celix_bundle_createFromArchive(framework, archive, &bundle)); @@ -675,7 +682,7 @@ celix_framework_installBundleInternal(celix_framework_t* framework, const char* } if (status == CELIX_SUCCESS) { - *bundleOut = id; + *bndId = id; } else { fw_logCode(framework->logger, CELIX_LOG_LEVEL_ERROR, status, "Could not install bundle"); } @@ -2267,89 +2274,71 @@ static bool celix_framework_updateBundleInternal(celix_framework_t *fw, long bnd fw_log(fw->logger, CELIX_LOG_LEVEL_INFO, "Cannot update framework bundle. Ignore update cmd."); return true; } - - fw_log(fw->logger, CELIX_LOG_LEVEL_WARNING, "Update bundle is not yet fully supported. Use at your own risk."); - bool updated = false; celix_framework_bundle_entry_t *bndEntry = celix_framework_bundleEntry_getBundleEntryAndIncreaseUseCount(fw, bndId); if (bndEntry != NULL) { celix_status_t rc = celix_framework_updateBundleOnANonCelixEventThread(fw, bndEntry, updatedBundleUrl, forcedAsync); + //note not decreasing bndEntry, because this entry should now be deleted (uninstalled) updated = rc == CELIX_SUCCESS; - celix_framework_bundleEntry_decreaseUseCount(bndEntry); celix_framework_waitForBundleEvents(fw, bndId); } return updated; } - -celix_status_t celix_framework_bundleEntry_refreshBundleEntry(celix_framework_t* framework, celix_framework_bundle_entry_t *entry, const char* updatedBundleUrl) { +celix_status_t celix_framework_updateBundleEntry(celix_framework_t* framework, + celix_framework_bundle_entry_t* bndEntry, + const char* updatedBundleUrl) { celix_status_t status = CELIX_SUCCESS; - celix_bundle_state_e state = celix_bundle_getState(entry->bnd); - if (state != CELIX_BUNDLE_STATE_RESOLVED) { - fw_log(framework->logger, CELIX_LOG_LEVEL_ERROR, "Cannot refresh bundle %s (id=%li), bundle is not in the resolved state", - celix_bundle_getSymbolicName(entry->bnd), - entry->bndId); - return CELIX_ILLEGAL_STATE; - } - - bundle_archive_t* archive = NULL; - celix_module_t* module = NULL; - status = CELIX_DO_IF(status, bundle_getArchive(entry->bnd, &archive)); - status = CELIX_DO_IF(status, bundle_getCurrentModule(entry->bnd, &module)); - - if (!archive || !module) { - fw_log(framework->logger, CELIX_LOG_LEVEL_ERROR, "Cannot refresh bundle %s (id=%li), bundle has no archive or module", - celix_bundle_getSymbolicName(entry->bnd), - entry->bndId); - return status; - } - - status = celix_module_closeLibraries(module); - if (status != CELIX_SUCCESS) { - fw_log(framework->logger, CELIX_LOG_LEVEL_ERROR, "Cannot refresh bundle %s (id=%li), cannot close libraries", - celix_bundle_getSymbolicName(entry->bnd), - entry->bndId); - return status; - } - - status = bundleArchive_revise(archive, NULL, updatedBundleUrl); - if (status != CELIX_SUCCESS) { - fw_log(framework->logger, CELIX_LOG_LEVEL_ERROR, "Cannot refresh bundle %s (id=%li), bundle archive revision failed", - celix_bundle_getSymbolicName(entry->bnd), - entry->bndId); - return status; - } - - status = celix_module_loadLibraries(module); - if (status != CELIX_SUCCESS) { - fw_log(framework->logger, CELIX_LOG_LEVEL_ERROR, "Cannot refresh bundle %s (id=%li), cannot load libraries", - celix_bundle_getSymbolicName(entry->bnd), - entry->bndId); - return status; - } - - return status; -} - -celix_status_t celix_framework_updateBundleEntry(celix_framework_t* framework, celix_framework_bundle_entry_t* bndEntry, const char* updatedBundleUrl) { - celix_status_t status = celix_framework_stopBundleEntry(framework, bndEntry); - if (status != CELIX_SUCCESS) { - fw_logCode(framework->logger, CELIX_LOG_LEVEL_ERROR, status, "Could not stop bundle for update"); - return status; - } - - status = celix_framework_bundleEntry_refreshBundleEntry(framework, bndEntry, updatedBundleUrl); - if (status != CELIX_SUCCESS) { - fw_logCode(framework->logger, CELIX_LOG_LEVEL_ERROR, status, "Could not refresh bundle for update"); - return status; - } - - status = celix_framework_startBundleEntry(framework, bndEntry); - if (status != CELIX_SUCCESS) { - fw_logCode(framework->logger, CELIX_LOG_LEVEL_ERROR, status, "Could not start bundle after update"); - } - - fw_log(framework->logger, CELIX_LOG_LEVEL_DEBUG, "Update bundle %s done", celix_bundle_getSymbolicName(bndEntry->bnd)); + long bundleId = bndEntry->bndId; + const char* errMsg; + fw_log(framework->logger, CELIX_LOG_LEVEL_DEBUG, "Updating bundle %s", celix_bundle_getSymbolicName(bndEntry->bnd)); + celix_bundle_state_e bndState = celix_bundle_getState(bndEntry->bnd); + char *location = celix_bundle_getLocation(bndEntry->bnd); + do { + // lock to reuse the bundle id + celixThreadMutex_lock(&framework->installLock); + if (updatedBundleUrl == NULL) { + updatedBundleUrl = location; + } else if (strcmp(location, updatedBundleUrl) != 0) { + long alreadyExistingBndId = celix_bundleCache_findBundleIdForLocation(framework->cache, updatedBundleUrl); + if (alreadyExistingBndId != -1 && alreadyExistingBndId != bundleId) { + errMsg = "specified bundle location exists in cache with a different id"; + celix_framework_bundleEntry_decreaseUseCount(bndEntry); + celixThreadMutex_unlock(&framework->installLock); + status = CELIX_ILLEGAL_STATE; + break; + } + } + status = celix_framework_uninstallBundleEntry(framework, bndEntry, true); + if (status != CELIX_SUCCESS) { + errMsg = "uninstall failure"; + celixThreadMutex_unlock(&framework->installLock); + break; + } + // bndEntry is now invalid + status = celix_framework_installBundleInternal(framework, updatedBundleUrl, &bundleId); + if (status != CELIX_SUCCESS) { + errMsg = "reinstall failure"; + celixThreadMutex_unlock(&framework->installLock); + break; + } + if (bndState != CELIX_BUNDLE_STATE_STARTING && bndState != CELIX_BUNDLE_STATE_ACTIVE) { + // no need to restart the updated bundle + celixThreadMutex_unlock(&framework->installLock); + break; + } + celix_framework_bundle_entry_t* entry = celix_framework_bundleEntry_getBundleEntryAndIncreaseUseCount(framework, bundleId); + celixThreadMutex_unlock(&framework->installLock); + // assert(entry != NULL); + status = celix_framework_startBundleEntry(framework, entry); + celix_framework_bundleEntry_decreaseUseCount(entry); + if (status != CELIX_SUCCESS) { + errMsg = "restart failure"; + break; + } + } while(0); + framework_logIfError(framework->logger, status, errMsg, "Could not update bundle from %s", updatedBundleUrl); + free(location); return status; } diff --git a/libs/framework/src/framework_bundle_lifecycle_handler.c b/libs/framework/src/framework_bundle_lifecycle_handler.c index 6ffa9bb39..40caeb283 100644 --- a/libs/framework/src/framework_bundle_lifecycle_handler.c +++ b/libs/framework/src/framework_bundle_lifecycle_handler.c @@ -41,9 +41,11 @@ static void* celix_framework_BundleLifecycleHandlingThread(void *data) { switch (handler->command) { case CELIX_BUNDLE_LIFECYCLE_START: celix_framework_startBundleEntry(handler->framework, handler->bndEntry); + celix_framework_bundleEntry_decreaseUseCount(handler->bndEntry); break; case CELIX_BUNDLE_LIFECYCLE_STOP: celix_framework_stopBundleEntry(handler->framework, handler->bndEntry); + celix_framework_bundleEntry_decreaseUseCount(handler->bndEntry); break; case CELIX_BUNDLE_LIFECYCLE_UNINSTALL: celix_framework_bundleEntry_decreaseUseCount(handler->bndEntry); @@ -54,12 +56,10 @@ static void* celix_framework_BundleLifecycleHandlingThread(void *data) { celix_framework_uninstallBundleEntry(handler->framework, handler->bndEntry, false); break; default: //update + celix_framework_bundleEntry_decreaseUseCount(handler->bndEntry); celix_framework_updateBundleEntry(handler->framework, handler->bndEntry, handler->updatedBundleUrl); break; } - if (handler->command != CELIX_BUNDLE_LIFECYCLE_UNINSTALL && handler->command != CELIX_BUNDLE_LIFECYCLE_UNLOAD) { - celix_framework_bundleEntry_decreaseUseCount(handler->bndEntry); - } celix_framework_cleanupBundleLifecycleHandler(handler->framework, handler); return NULL; } diff --git a/libs/framework/src/framework_private.h b/libs/framework/src/framework_private.h index c506e94b3..d2a36cfc0 100644 --- a/libs/framework/src/framework_private.h +++ b/libs/framework/src/framework_private.h @@ -253,7 +253,7 @@ double celix_framework_getConfigPropertyAsDouble(celix_framework_t* framework, c */ bool celix_framework_getConfigPropertyAsBool(celix_framework_t* framework, const char* name, bool defaultValue, bool* found); -celix_status_t celix_framework_installBundleInternal(celix_framework_t* framework, const char* bndLoc, long* bundleOut); +celix_status_t celix_framework_installBundleInternal(celix_framework_t* framework, const char* bndLoc, long* bndId); celix_status_t fw_registerService(framework_pt framework, service_registration_pt * registration, long bundleId, const char* serviceName, const void* svcObj, properties_pt properties); celix_status_t fw_registerServiceFactory(framework_pt framework, service_registration_pt * registration, long bundleId, const char* serviceName, service_factory_pt factory, properties_pt properties); @@ -433,7 +433,7 @@ celix_status_t celix_framework_stopBundleEntry(celix_framework_t* fw, celix_fram celix_status_t celix_framework_uninstallBundleEntry(celix_framework_t* fw, celix_framework_bundle_entry_t* bndEntry, bool permanent); /** - * Uninstall a bundle. Cannot be called on the Celix event thread. + * Update a bundle. Cannot be called on the Celix event thread. */ celix_status_t celix_framework_updateBundleEntry(celix_framework_t* fw, celix_framework_bundle_entry_t* bndEntry, const char* updatedBundleUrl); From 415b8eb38ec98650c6f87a42fdd56d2ce2cc5fd6 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Sat, 3 Jun 2023 15:13:31 +0800 Subject: [PATCH 08/21] Implement bundle update as bundle unload plus bundle install. --- ...CelixBundleCacheErrorInjectionTestSuite.cc | 2 +- .../gtest/src/CelixBundleCacheTestSuite.cc | 16 +++++- .../src/CelixBundleContextBundlesTestSuite.cc | 3 +- libs/framework/include/celix_bundle_context.h | 8 +-- libs/framework/include/celix_framework.h | 16 +++--- libs/framework/src/celix_bundle_cache.c | 6 ++- libs/framework/src/celix_bundle_cache.h | 11 ++-- libs/framework/src/framework.c | 51 ++++++++++--------- 8 files changed, 68 insertions(+), 45 deletions(-) diff --git a/libs/framework/gtest/src/CelixBundleCacheErrorInjectionTestSuite.cc b/libs/framework/gtest/src/CelixBundleCacheErrorInjectionTestSuite.cc index 38aa3b3c6..7f0896c54 100644 --- a/libs/framework/gtest/src/CelixBundleCacheErrorInjectionTestSuite.cc +++ b/libs/framework/gtest/src/CelixBundleCacheErrorInjectionTestSuite.cc @@ -154,7 +154,7 @@ TEST_F(CelixBundleCacheErrorInjectionTestSuite, ArchiveDestroyErrorTest) { EXPECT_EQ(CELIX_SUCCESS, celix_bundleCache_createArchive(cache, 1, SIMPLE_TEST_BUNDLE1_LOCATION, &archive)); celix_ei_expect_celix_utils_deleteDirectory((void*)celix_bundleCache_destroyArchive, 1, CELIX_FILE_IO_EXCEPTION); std::string storeRoot = celix_bundleArchive_getPersistentStoreRoot(archive); - EXPECT_EQ(CELIX_FILE_IO_EXCEPTION, celix_bundleCache_destroyArchive(cache, archive)); + EXPECT_EQ(CELIX_FILE_IO_EXCEPTION, celix_bundleCache_destroyArchive(cache, archive, true)); EXPECT_TRUE(celix_utils_directoryExists(storeRoot.c_str())); EXPECT_EQ(CELIX_SUCCESS, celix_bundleCache_destroy(cache)); } diff --git a/libs/framework/gtest/src/CelixBundleCacheTestSuite.cc b/libs/framework/gtest/src/CelixBundleCacheTestSuite.cc index 945242db3..c37ef142d 100644 --- a/libs/framework/gtest/src/CelixBundleCacheTestSuite.cc +++ b/libs/framework/gtest/src/CelixBundleCacheTestSuite.cc @@ -58,12 +58,24 @@ TEST_F(CelixBundleCacheTestSuite, ArchiveCreateDestroyTest) { EXPECT_TRUE(celix_bundleCache_isBundleIdAlreadyUsed(fw.cache, 1)); std::string loc = celix_bundleArchive_getPersistentStoreRoot(archive); EXPECT_TRUE(celix_utils_directoryExists(loc.c_str())); - EXPECT_EQ(CELIX_SUCCESS, celix_bundleCache_destroyArchive(fw.cache, archive)); + EXPECT_EQ(CELIX_SUCCESS, celix_bundleCache_destroyArchive(fw.cache, archive, true)); EXPECT_EQ(-1, celix_bundleCache_findBundleIdForLocation(fw.cache, SIMPLE_TEST_BUNDLE1_LOCATION)); EXPECT_FALSE(celix_bundleCache_isBundleIdAlreadyUsed(fw.cache, 1)); EXPECT_FALSE(celix_utils_directoryExists(loc.c_str())); } +TEST_F(CelixBundleCacheTestSuite, NonPermanentDestroyTest) { + bundle_archive_t* archive = nullptr; + EXPECT_EQ(CELIX_SUCCESS, celix_bundleCache_createArchive(fw.cache, 1, SIMPLE_TEST_BUNDLE1_LOCATION, &archive)); + EXPECT_NE(nullptr, archive); + std::string loc = celix_bundleArchive_getPersistentStoreRoot(archive); + EXPECT_TRUE(celix_utils_directoryExists(loc.c_str())); + EXPECT_EQ(CELIX_SUCCESS, celix_bundleCache_destroyArchive(fw.cache, archive, false)); + EXPECT_EQ(1, celix_bundleCache_findBundleIdForLocation(fw.cache, SIMPLE_TEST_BUNDLE1_LOCATION)); + EXPECT_TRUE(celix_bundleCache_isBundleIdAlreadyUsed(fw.cache, 1)); + EXPECT_TRUE(celix_utils_directoryExists(loc.c_str())); +} + TEST_F(CelixBundleCacheTestSuite, SystemArchiveCreateDestroyTest) { bundle_archive_t* archive = nullptr; const char* archiveRoot = nullptr; @@ -73,7 +85,7 @@ TEST_F(CelixBundleCacheTestSuite, SystemArchiveCreateDestroyTest) { EXPECT_EQ(CELIX_SUCCESS, bundleArchive_getArchiveRoot(archive, &archiveRoot)); EXPECT_EQ(nullptr, archiveRoot); EXPECT_EQ(nullptr, celix_bundleArchive_getLocation(archive)); - EXPECT_EQ(CELIX_SUCCESS, celix_bundleCache_destroyArchive(fw.cache, archive)); + EXPECT_EQ(CELIX_SUCCESS, celix_bundleCache_destroyArchive(fw.cache, archive, true)); } TEST_F(CelixBundleCacheTestSuite, CreateBundleArchivesCacheTest) { diff --git a/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc b/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc index 0d222bb7d..c3b3df939 100644 --- a/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc +++ b/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc @@ -305,9 +305,10 @@ TEST_F(CelixBundleContextBundlesTestSuite, UpdateBundlesTest) { ASSERT_TRUE(bndId2 >= 0L); ASSERT_FALSE(celix_bundleContext_updateBundle(ctx, bndId1, TEST_BND2_LOC)); ASSERT_TRUE(celix_bundleContext_isBundleInstalled(ctx, bndId1)); + + // remove it from cache before updating ASSERT_EQ(bndId2, celix_bundleContext_installBundle(ctx, TEST_BND2_LOC, false)); ASSERT_TRUE(celix_bundleContext_uninstallBundle(ctx, bndId2)); - auto sn1 = celix_bundleContext_getBundleSymbolicName(ctx, bndId1); ASSERT_TRUE(celix_bundleContext_updateBundle(ctx, bndId1, TEST_BND2_LOC)); auto sn2 = celix_bundleContext_getBundleSymbolicName(ctx, bndId1); diff --git a/libs/framework/include/celix_bundle_context.h b/libs/framework/include/celix_bundle_context.h index 3d3d71e1f..40430d284 100644 --- a/libs/framework/include/celix_bundle_context.h +++ b/libs/framework/include/celix_bundle_context.h @@ -955,8 +955,8 @@ CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_startBundle(celix_bundle_context * @brief Update the bundle with the provided bundle id. * * This will do the following: - * - uninstall the bundle with the specified bundle id; - * - reinstall the bundle from the specified location with the specified bundle id; + * - unload the bundle with the specified bundle id; + * - reload the bundle from the specified location with the specified bundle id; * - start the bundle, if it was previously active. * * Will silently ignore bundle ids < 0. @@ -971,8 +971,8 @@ CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_startBundle(celix_bundle_context * * @param ctx The bundle context * @param bndId The bundle id to update. - * @param updatedBundleUrl The optional updated bundle url to the bundle zip file. If NULL, the existing bundle url - * from the bundle cache will be used. + * @param updatedBundleUrl The optional updated bundle url to the bundle zip file. + * If NULL, the existing bundle url from the bundle cache will be used, and the cache will only be updated if the zip file is newer. * @return true if the bundle is found & correctly started. False if not. */ CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_updateBundle(celix_bundle_context_t *ctx, long bndId, const char* updatedBundleUrl); diff --git a/libs/framework/include/celix_framework.h b/libs/framework/include/celix_framework.h index ad833ce5d..16da33c43 100644 --- a/libs/framework/include/celix_framework.h +++ b/libs/framework/include/celix_framework.h @@ -186,19 +186,19 @@ CELIX_FRAMEWORK_EXPORT bool celix_framework_unloadBundle(celix_framework_t *fw, * @brief Update the bundle with the provided bundle id. * * This will do the following: - * - uninstall the bundle with the specified bundle id; - * - reinstall the bundle from the specified location with the specified bundle id; + * - unload the bundle with the specified bundle id; + * - reload the bundle from the specified location with the specified bundle id; * - start the bundle, if it was previously active. * * Will silently ignore bundle ids < 0. * * Note if specified bundle location already exists in the bundle cache but with a different bundle id, the bundle - * will NOT be reinstalled, and the update is cancelled. + * will NOT be reloaded, and the update is cancelled. * * @param [in] fw The Celix framework * @param [in] bndId the bundle id to update. * @param [in] updatedBundleUrl The optional updated bundle url to the bundle zip file. - * If NULL, the existing bundle url from the bundle cache will be used. + * If NULL, the existing bundle url from the bundle cache will be used, and the cache will only be updated if the zip file is newer. * @return true if the bundle is correctly updated. False if not. */ CELIX_FRAMEWORK_EXPORT bool celix_framework_updateBundle(celix_framework_t *fw, long bndId, const char* updatedBundleUrl); @@ -240,8 +240,8 @@ CELIX_FRAMEWORK_EXPORT long celix_framework_installBundleAsync(celix_framework_t * @brief Update the bundle with the provided bundle id async. * * This will do the following: - * - uninstall the bundle with the specified bundle id; - * - reinstall the bundle from the specified location with the specified bundle id; + * - unload the bundle with the specified bundle id; + * - reload the bundle from the specified location with the specified bundle id; * - start the bundle, if it was previously active. * * Will silently ignore bundle ids < 0. @@ -251,8 +251,8 @@ CELIX_FRAMEWORK_EXPORT long celix_framework_installBundleAsync(celix_framework_t * * @param [in] fw The Celix framework * @param [in] bndId the bundle id to update. - * @param [in] updatedBundleUrl The optional updated bundle url to the bundle zip file. If NULL, the existing bundle url - * from the bundle cache will be used. + * @param [in] updatedBundleUrl The optional updated bundle url to the bundle zip file. + * If NULL, the existing bundle url from the bundle cache will be used, and the cache will only be updated if the zip file is newer. */ CELIX_FRAMEWORK_EXPORT void celix_framework_updateBundleAsync(celix_framework_t *fw, long bndId, const char* updatedBundleUrl); diff --git a/libs/framework/src/celix_bundle_cache.c b/libs/framework/src/celix_bundle_cache.c index aa0bbce86..94a5933d9 100644 --- a/libs/framework/src/celix_bundle_cache.c +++ b/libs/framework/src/celix_bundle_cache.c @@ -230,13 +230,15 @@ celix_status_t celix_bundleCache_createSystemArchive(celix_framework_t* fw, bund return celix_bundleCache_createArchive(fw->cache, CELIX_FRAMEWORK_BUNDLE_ID, NULL, archive); } -celix_status_t celix_bundleCache_destroyArchive(celix_bundle_cache_t* cache, bundle_archive_pt archive) { +celix_status_t celix_bundleCache_destroyArchive(celix_bundle_cache_t* cache, bundle_archive_pt archive, bool permanent) { celix_status_t status = CELIX_SUCCESS; const char* loc = NULL; celixThreadMutex_lock(&cache->mutex); (void) bundleArchive_getLocation(archive, &loc); (void) celix_stringHashMap_remove(cache->locationToBundleIdLookupMap, loc); - status = bundleArchive_closeAndDelete(archive); + if (permanent) { + status = bundleArchive_closeAndDelete(archive); + } celixThreadMutex_unlock(&cache->mutex); (void) bundleArchive_destroy(archive); return status; diff --git a/libs/framework/src/celix_bundle_cache.h b/libs/framework/src/celix_bundle_cache.h index 14f5ea860..fb0937056 100644 --- a/libs/framework/src/celix_bundle_cache.h +++ b/libs/framework/src/celix_bundle_cache.h @@ -20,12 +20,14 @@ #ifndef CELIX_BUNDLE_CACHE_H_ #define CELIX_BUNDLE_CACHE_H_ +#include -#include "bundle_archive.h" -#include "celix_framework.h" #include "celix_array_list.h" +#include "celix_framework.h" #include "celix_long_hash_map.h" +#include "bundle_archive.h" + #ifdef __cplusplus extern "C" { #endif @@ -89,15 +91,16 @@ celix_status_t celix_bundleCache_createSystemArchive(celix_framework_t* fw, bund /** * @brief Destroy the archive from the cache. - * It releases all resources allocated in celix_bundleCache_createArchive and deletes the archive directory. + * It releases all resources allocated in celix_bundleCache_createArchive and deletes the archive directory if requested. * @param [in] cache The bundle cache to destroy archive from. * @param [in] archive The archive to destroy. + * @param [in] permanent Whether the archive directory should be deleted or not. * @return Status code indication failure or success: * - CELIX_SUCCESS when no errors are encountered. * - CELIX_FILE_IO_EXCEPTION when root of the archive is not a directory. * - errno when the directory cannot be deleted for other reasons, check error codes of fts_open/fts_read/remove. */ -celix_status_t celix_bundleCache_destroyArchive(celix_bundle_cache_t* cache, bundle_archive_pt archive); +celix_status_t celix_bundleCache_destroyArchive(celix_bundle_cache_t* cache, bundle_archive_pt archive, bool permanent); /** * @brief Deletes the entire bundle cache. diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c index e730133c9..0c3983eb4 100644 --- a/libs/framework/src/framework.c +++ b/libs/framework/src/framework.c @@ -17,33 +17,35 @@ * under the License. */ -#include +#include +#include +#include #include +#include #include #include -#include #include -#include -#include +#include "celix_build_assert.h" +#include "celix_bundle_context.h" +#include "celix_constants.h" +#include "celix_convert_utils.h" #include "celix_dependency_manager.h" +#include "celix_file_utils.h" +#include "celix_framework_utils_private.h" +#include "celix_libloader.h" +#include "celix_log_constants.h" +#include "celix_module_private.h" + +#include "bundle_archive_private.h" +#include "bundle_context_private.h" +#include "bundle_private.h" #include "framework_private.h" -#include "celix_constants.h" -#include "resolver.h" -#include "utils.h" #include "linked_list_iterator.h" +#include "resolver.h" #include "service_reference_private.h" #include "service_registration_private.h" -#include "bundle_private.h" -#include "celix_bundle_context.h" -#include "bundle_context_private.h" -#include "celix_libloader.h" -#include "celix_log_constants.h" -#include "celix_framework_utils_private.h" -#include "bundle_archive_private.h" -#include "celix_module_private.h" -#include "celix_convert_utils.h" -#include "celix_build_assert.h" +#include "utils.h" struct celix_bundle_activator { void * userData; @@ -1965,11 +1967,7 @@ celix_status_t celix_framework_uninstallBundleEntry(celix_framework_t* framework celix_framework_waitForEmptyEventQueue(framework); //to ensure that the uninstall event is triggered and handled (void)bundle_closeModules(bnd); (void)bundle_destroy(bnd); - if(permanent) { - (void)celix_bundleCache_destroyArchive(framework->cache, archive); - } else { - (void)bundleArchive_destroy(archive); - } + (void)celix_bundleCache_destroyArchive(framework->cache, archive, permanent); } celixThreadMutex_unlock(&framework->installLock); framework_logIfError(framework->logger, status, "", "Cannot uninstall bundle"); @@ -2291,6 +2289,7 @@ celix_status_t celix_framework_updateBundleEntry(celix_framework_t* framework, celix_status_t status = CELIX_SUCCESS; long bundleId = bndEntry->bndId; const char* errMsg; + char *bndRoot = NULL; fw_log(framework->logger, CELIX_LOG_LEVEL_DEBUG, "Updating bundle %s", celix_bundle_getSymbolicName(bndEntry->bnd)); celix_bundle_state_e bndState = celix_bundle_getState(bndEntry->bnd); char *location = celix_bundle_getLocation(bndEntry->bnd); @@ -2308,14 +2307,19 @@ celix_status_t celix_framework_updateBundleEntry(celix_framework_t* framework, status = CELIX_ILLEGAL_STATE; break; } + bndRoot = celix_bundle_getEntry(bndEntry->bnd, NULL); } - status = celix_framework_uninstallBundleEntry(framework, bndEntry, true); + status = celix_framework_uninstallBundleEntry(framework, bndEntry, false); if (status != CELIX_SUCCESS) { errMsg = "uninstall failure"; celixThreadMutex_unlock(&framework->installLock); break; } // bndEntry is now invalid + if (bndRoot) { + // the bundle is updated with a new location, so the old bundle root can be removed + celix_utils_deleteDirectory(bndRoot, NULL); + } status = celix_framework_installBundleInternal(framework, updatedBundleUrl, &bundleId); if (status != CELIX_SUCCESS) { errMsg = "reinstall failure"; @@ -2338,6 +2342,7 @@ celix_status_t celix_framework_updateBundleEntry(celix_framework_t* framework, } } while(0); framework_logIfError(framework->logger, status, errMsg, "Could not update bundle from %s", updatedBundleUrl); + free(bndRoot); free(location); return status; } From 55cd88149b7011c052600cc98a3ce70dcbef5049 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Tue, 6 Jun 2023 16:10:30 +0800 Subject: [PATCH 09/21] Fix misuse of DEPENDS in add_custom_target for a target rather than a file. --- cmake/cmake_celix/BundlePackaging.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/cmake_celix/BundlePackaging.cmake b/cmake/cmake_celix/BundlePackaging.cmake index 972df6cb1..51f4f35c5 100644 --- a/cmake/cmake_celix/BundlePackaging.cmake +++ b/cmake/cmake_celix/BundlePackaging.cmake @@ -266,8 +266,9 @@ function(add_celix_bundle) ) endif() add_custom_target(${BUNDLE_TARGET_NAME}_bundle - DEPENDS ${BUNDLE_TARGET_NAME} "$" + DEPENDS "$" ) + add_dependencies(${BUNDLE_TARGET_NAME}_bundle ${BUNDLE_TARGET_NAME}) add_dependencies(celix-bundles ${BUNDLE_TARGET_NAME}_bundle) ####################################################################### From 7319b48fb0571498a4e6e709f2e029574172bedc Mon Sep 17 00:00:00 2001 From: PengZheng Date: Wed, 7 Jun 2023 15:28:15 +0800 Subject: [PATCH 10/21] Make cleanup of BUNDLE_GEN_DIR work again. --- cmake/cmake_celix/BundlePackaging.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/cmake_celix/BundlePackaging.cmake b/cmake/cmake_celix/BundlePackaging.cmake index 51f4f35c5..c3b1faac7 100644 --- a/cmake/cmake_celix/BundlePackaging.cmake +++ b/cmake/cmake_celix/BundlePackaging.cmake @@ -318,7 +318,7 @@ function(add_celix_bundle) ################################### ##### Additional Cleanup info ##### ################################### - set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "$;$") + set_target_properties(${BUNDLE_TARGET_NAME}_bundle PROPERTIES "ADDITIONAL_CLEAN_FILES" "$;$") ############################# ### BUNDLE TARGET PROPERTIES From cfd6b440828512fa03eb8a778b9d9fd3d0dcf5b2 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Wed, 7 Jun 2023 17:46:08 +0800 Subject: [PATCH 11/21] Fix several typos. --- cmake/cmake_celix/BundlePackaging.cmake | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmake/cmake_celix/BundlePackaging.cmake b/cmake/cmake_celix/BundlePackaging.cmake index c3b1faac7..d7afab4c8 100644 --- a/cmake/cmake_celix/BundlePackaging.cmake +++ b/cmake/cmake_celix/BundlePackaging.cmake @@ -324,7 +324,7 @@ function(add_celix_bundle) ### BUNDLE TARGET PROPERTIES ############################# #already set - # BUNDLE_TARGET_IS_LIB -> true (can be use to test if target is bundle target + # BUNDLE_TARGET_IS_LIB -> true (can be use to test if target is library target # BUNDLE_TARGET -> refers to the _bundle target which is responsible for building the zip file #internal use set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_IS_BUNDLE_TARGET" TRUE) #indicate that this is a bundle target @@ -836,7 +836,7 @@ endfunction() function(bundle_name) message(DEPRECATION "bundle_name is deprecated, use celix_bundle_name instead.") - celix_bundle_symbolic_name(${ARGN}) + celix_bundle_name(${ARGN}) endfunction() #[[ @@ -852,7 +852,7 @@ endfunction() function(bundle_version) message(DEPRECATION "bundle_version is deprecated, use celix_bundle_version instead.") - celix_bundle_symbolic_name(${ARGN}) + celix_bundle_version(${ARGN}) endfunction() #[[ @@ -868,7 +868,7 @@ endfunction() function(bundle_description) message(DEPRECATION "bundle_description is deprecated, use celix_bundle_description instead.") - celix_bundle_symbolic_name(${ARGN}) + celix_bundle_description(${ARGN}) endfunction() #[[ @@ -1162,7 +1162,7 @@ endfunction() #[[ -extract the BUNDLE_FILENAME and BUNDLE_FILE from a imported bundle target taking into account the used CMAKE_BUILD_TYPE +extract the BUNDLE_FILENAME, BUNDLE_FILE, and BUNDLE_SYMBOLIC_NAME from a imported bundle target taking into account the used CMAKE_BUILD_TYPE and if configured the MAP_IMPORTED_CONFIG_* or CMAKE_MAP_IMPORTED_CONFIG_* ```CMake From eccbb7f9be7958b5724e8569164e8c14052abcae Mon Sep 17 00:00:00 2001 From: PengZheng Date: Thu, 8 Jun 2023 19:01:51 +0800 Subject: [PATCH 12/21] Fix inconvenience brought about by BUILD_WITH_INSTALL_RPATH when building bundles (#571). --- bundles/remote_services/remote_service_admin_dfi/CMakeLists.txt | 1 - bundles/remote_services/rsa_rpc_json/CMakeLists.txt | 1 - cmake/cmake_celix/BundlePackaging.cmake | 1 - 3 files changed, 3 deletions(-) diff --git a/bundles/remote_services/remote_service_admin_dfi/CMakeLists.txt b/bundles/remote_services/remote_service_admin_dfi/CMakeLists.txt index 2eeb8c396..27dee5838 100644 --- a/bundles/remote_services/remote_service_admin_dfi/CMakeLists.txt +++ b/bundles/remote_services/remote_service_admin_dfi/CMakeLists.txt @@ -33,7 +33,6 @@ if (RSA_REMOTE_SERVICE_ADMIN_DFI) src/export_registration_dfi.c src/import_registration_dfi.c ) - celix_bundle_private_libs(rsa_dfi Celix::dfi) target_link_libraries(rsa_dfi PRIVATE Celix::rsa_dfi_utils Celix::dfi diff --git a/bundles/remote_services/rsa_rpc_json/CMakeLists.txt b/bundles/remote_services/rsa_rpc_json/CMakeLists.txt index 8fab9f3e6..779b7e864 100644 --- a/bundles/remote_services/rsa_rpc_json/CMakeLists.txt +++ b/bundles/remote_services/rsa_rpc_json/CMakeLists.txt @@ -58,7 +58,6 @@ if (RSA_JSON_RPC) add_library(Celix::rsa_json_rpc ALIAS rsa_json_rpc) if (ENABLE_TESTING) - celix_bundle_private_libs(rsa_json_rpc Celix::dfi) add_library(rsa_json_rpc_cut STATIC ${RSA_JSON_RPC_SRC}) celix_deprecated_utils_headers(rsa_json_rpc_cut) target_include_directories(rsa_json_rpc_cut PUBLIC src) diff --git a/cmake/cmake_celix/BundlePackaging.cmake b/cmake/cmake_celix/BundlePackaging.cmake index d7afab4c8..81b9cb4a6 100644 --- a/cmake/cmake_celix/BundlePackaging.cmake +++ b/cmake/cmake_celix/BundlePackaging.cmake @@ -357,7 +357,6 @@ function(add_celix_bundle) if(BUNDLE_SOURCES) celix_bundle_libs(${BUNDLE_TARGET_NAME} "PRIVATE" TRUE ${BUNDLE_TARGET_NAME}) set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUNDLE_ACTIVATOR" "$") - set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES "BUILD_WITH_INSTALL_RPATH" true) if(APPLE) set_target_properties(${BUNDLE_TARGET_NAME} PROPERTIES INSTALL_RPATH "@loader_path") From 514a71e8fc55501976f2867bc5359d9635d484d2 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Thu, 8 Jun 2023 19:09:25 +0800 Subject: [PATCH 13/21] Remove redundant target_link_libraries to work around BUILD_WITH_INSTALL_RPATH. --- libs/framework/gtest/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/framework/gtest/CMakeLists.txt b/libs/framework/gtest/CMakeLists.txt index 7828126b2..e84fdd0e9 100644 --- a/libs/framework/gtest/CMakeLists.txt +++ b/libs/framework/gtest/CMakeLists.txt @@ -61,8 +61,7 @@ set(CELIX_FRAMEWORK_TEST_SOURCES add_executable(test_framework ${CELIX_FRAMEWORK_TEST_SOURCES}) # framework_cut makes error injector work -# Celix::framework makes bundles loadable (otherwise we need an copy of framework in each bundle, celix_bundle_private_libs) -target_link_libraries(test_framework PRIVATE framework_cut Celix::framework CURL::libcurl GTest::gtest GTest::gtest_main) +target_link_libraries(test_framework PRIVATE framework_cut CURL::libcurl GTest::gtest GTest::gtest_main) celix_deprecated_framework_headers(test_framework) From 40df914a5a4e00697a8ef9d0d0dbb014f43ec883 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Fri, 9 Jun 2023 11:12:05 +0800 Subject: [PATCH 14/21] A better workaround of the issue of private linking of transitive dependencies. See https://github.com/conan-io/conan/issues/13302 --- conanfile.py | 10 +++++----- examples/conan_test_package/conanfile.py | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/conanfile.py b/conanfile.py index 604fafd46..5b47ee1c3 100644 --- a/conanfile.py +++ b/conanfile.py @@ -272,16 +272,16 @@ def _configure_cmake(self): self._enable_error_injectors() self._cmake.definitions["CELIX_ERR_BUFFER_SIZE"] = self.options.celix_err_buffer_size self._cmake.definitions["CMAKE_PROJECT_Celix_INCLUDE"] = os.path.join(self.build_folder, "conan_paths.cmake") - # the following is workaround for https://github.com/conan-io/conan/issues/7192 - if self.settings.os == "Linux": - self._cmake.definitions["CMAKE_EXE_LINKER_FLAGS"] = "-Wl,--unresolved-symbols=ignore-in-shared-libs" - elif self.settings.os == "Macos": - self._cmake.definitions["CMAKE_EXE_LINKER_FLAGS"] = "-Wl,-undefined -Wl,dynamic_lookup" + # the following together with the imports method is a workaround https://github.com/conan-io/conan/issues/7192 + self._cmake.definitions["CMAKE_BUILD_RPATH"] = os.path.join(self.build_folder, "lib") self.output.info(self._cmake.definitions) v = tools.Version(self.version) self._cmake.configure(defs={'CELIX_MAJOR': v.major, 'CELIX_MINOR': v.minor, 'CELIX_MICRO': v.patch}) return self._cmake + def imports(self): + self.copy("*.so*", "lib", "lib") + def build(self): # self._patch_sources() cmake = self._configure_cmake() diff --git a/examples/conan_test_package/conanfile.py b/examples/conan_test_package/conanfile.py index 327a61a74..39ae8e3c7 100644 --- a/examples/conan_test_package/conanfile.py +++ b/examples/conan_test_package/conanfile.py @@ -52,14 +52,14 @@ def build(self): cmake.definitions["TEST_PROMISES"] = self.options["celix"].build_promises cmake.definitions["TEST_PUSHSTREAMS"] = self.options["celix"].build_pushstreams cmake.definitions["CMAKE_PROJECT_test_package_INCLUDE"] = os.path.join(self.build_folder, "conan_paths.cmake") - # the following is workaround https://github.com/conan-io/conan/issues/7192 - if self.settings.os == "Linux": - cmake.definitions["CMAKE_EXE_LINKER_FLAGS"] = "-Wl,--unresolved-symbols=ignore-in-shared-libs" - elif self.settings.os == "Macos": - cmake.definitions["CMAKE_EXE_LINKER_FLAGS"] = "-Wl,-undefined -Wl,dynamic_lookup" + # the following together with the imports method is a workaround https://github.com/conan-io/conan/issues/7192 + cmake.definitions["CMAKE_BUILD_RPATH"] = os.path.join(self.build_folder, "lib") cmake.configure() cmake.build() + def imports(self): + self.copy("*.so*", "lib", "lib") + def test(self): if not tools.cross_building(self, skip_x64_x86=True): self.run("./use_framework", run_environment=True) From c7c818e293b000eda183a8ea6dddf139b4acd0e4 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Fri, 9 Jun 2023 17:53:30 +0800 Subject: [PATCH 15/21] Fix missing `DEPENDS` in `celix_bundle_libs` and typos. --- cmake/cmake_celix/BundlePackaging.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/cmake_celix/BundlePackaging.cmake b/cmake/cmake_celix/BundlePackaging.cmake index 81b9cb4a6..2c0ee2696 100644 --- a/cmake/cmake_celix/BundlePackaging.cmake +++ b/cmake/cmake_celix/BundlePackaging.cmake @@ -459,7 +459,7 @@ function(celix_bundle_libs) #0 is bundle TARGET #1 is TYPE, e.g PRIVATE,EXPORT or IMPORT #2 is ADD_TO_MANIFEST - #2..n is libs + #3..n is libs list(GET ARGN 0 BUNDLE) list(REMOVE_AT ARGN 0) @@ -484,7 +484,8 @@ function(celix_bundle_libs) get_filename_component(LIB_NAME ${LIB} NAME) set(OUT "${BUNDLE_DIR}/${LIB_NAME}") add_custom_command(OUTPUT ${OUT} - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LIB} ${OUT} + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LIB} ${OUT} + DEPENDS ${LIB} ) if (ADD_TO_MANIFEST) list(APPEND LIBS ${LIB_NAME}) @@ -520,7 +521,7 @@ function(celix_bundle_libs) get_target_property(IS_LIB ${BUNDLE} "BUNDLE_TARGET_IS_LIB") if ("${LIB}" STREQUAL "${BUNDLE}") - #ignore. Do not have to link agaist own lib + #ignore. Do not have to link against itself elseif(IS_LIB) target_link_libraries(${BUNDLE} PRIVATE ${LIB}) endif() @@ -551,7 +552,6 @@ function(celix_bundle_import_libs) check_bundle(${BUNDLE}) get_target_property(LIBS ${BUNDLE} "BUNDLE_IMPORT_LIBS") - set(LIBS ) foreach(LIB IN ITEMS ${ARGN}) message(WARNING "Bundle with import libs in Celix is not complete and still experimental.") From e62187d364a82000de59aba181aad526ff077a22 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Mon, 12 Jun 2023 20:14:27 +0800 Subject: [PATCH 16/21] Fix a minor typo. --- cmake/cmake_celix/BundlePackaging.cmake | 40 ++++++++++++++----------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/cmake/cmake_celix/BundlePackaging.cmake b/cmake/cmake_celix/BundlePackaging.cmake index 2c0ee2696..8fe0f5fd4 100644 --- a/cmake/cmake_celix/BundlePackaging.cmake +++ b/cmake/cmake_celix/BundlePackaging.cmake @@ -662,18 +662,18 @@ function(celix_bundle_add_dir) if (NOT DEFINED COPY_DESTINATION) set(DESTINATION "${BUNDLE_DIR}") else() - set(DESTINATION "${BUNDLE_DIR}/${COPY_DESTINATION}") + set(DESTINATION "${BUNDLE_DIR}/${COPY_DESTINATION}") endif() string(UUID COPY_ID NAMESPACE "661ee07c-842d-11e8-adfc-80fa5b02e11b" NAME "${INPUT_DIR}" TYPE MD5) set(COPY_CMAKE_SCRIPT "${CMAKE_BINARY_DIR}/celix/gen/bundles/${BUNDLE}/copy-dir-${COPY_ID}.cmake") if (IS_ABSOLUTE ${INPUT_DIR}) - file(WRITE ${COPY_CMAKE_SCRIPT} - "file(COPY ${INPUT_DIR} DESTINATION ${DESTINATION})") + file(WRITE ${COPY_CMAKE_SCRIPT} + "file(COPY ${INPUT_DIR} DESTINATION ${DESTINATION})") else() - file(WRITE ${COPY_CMAKE_SCRIPT} - "file(COPY ${CMAKE_CURRENT_LIST_DIR}/${INPUT_DIR} DESTINATION ${DESTINATION})") + file(WRITE ${COPY_CMAKE_SCRIPT} + "file(COPY ${CMAKE_CURRENT_LIST_DIR}/${INPUT_DIR} DESTINATION ${DESTINATION})") endif() set(TIMESTAMP "${CMAKE_BINARY_DIR}/celix/gen/bundles/${BUNDLE}/copy-dir-${COPY_ID}.timestamp") @@ -683,7 +683,7 @@ function(celix_bundle_add_dir) COMMAND ${CMAKE_COMMAND} -P ${COPY_CMAKE_SCRIPT} DEPENDS ${DIR_FILES} COMMENT "Copying dir ${INPUT_DIR} to ${DESTINATION}" - ) + ) get_target_property(DEPS ${BUNDLE} "BUNDLE_DEPEND_TARGETS") list(APPEND DEPS "${TIMESTAMP}") @@ -691,7 +691,7 @@ function(celix_bundle_add_dir) endfunction() #[[ -Copy to the content of a directory to a bundle. +Copy specified files to a bundle. ```CMake celix_bundle_add_files( @@ -725,7 +725,7 @@ function(celix_bundle_add_files) if (NOT DEFINED COPY_DESTINATION) set(DESTINATION "${BUNDLE_DIR}") else() - set(DESTINATION "${BUNDLE_DIR}/${COPY_DESTINATION}") + set(DESTINATION "${BUNDLE_DIR}/${COPY_DESTINATION}") endif() string(UUID COPY_ID NAMESPACE "661ee07c-842d-11e8-adfc-80fa5b02e11b" NAME "${COPY_FILES}" TYPE MD5) @@ -733,21 +733,21 @@ function(celix_bundle_add_files) set(TIMESTAMP "${CMAKE_BINARY_DIR}/celix/gen/bundles/${BUNDLE}/copy-files-${COPY_ID}.timestamp") set(COPY_CMAKE_SCRIPT "${CMAKE_BINARY_DIR}/celix/gen/bundles/${BUNDLE}/copy-files-${COPY_ID}.cmake") file(WRITE ${COPY_CMAKE_SCRIPT} - "#Copy script, copies the file on a file per file base\n") + "#Copy script, copies the file on a file per file base\n") foreach(FILE IN ITEMS ${COPY_FILES}) - if (IS_ABSOLUTE ${FILE}) - file(APPEND ${COPY_CMAKE_SCRIPT} - "file(COPY ${FILE} DESTINATION ${DESTINATION})\n") - else() - file(APPEND ${COPY_CMAKE_SCRIPT} - "file(COPY ${CMAKE_CURRENT_LIST_DIR}/${FILE} DESTINATION ${DESTINATION})\n") - endif() + if (IS_ABSOLUTE ${FILE}) + file(APPEND ${COPY_CMAKE_SCRIPT} + "file(COPY ${FILE} DESTINATION ${DESTINATION})\n") + else() + file(APPEND ${COPY_CMAKE_SCRIPT} + "file(COPY ${CMAKE_CURRENT_LIST_DIR}/${FILE} DESTINATION ${DESTINATION})\n") + endif() endforeach() add_custom_command(OUTPUT ${TIMESTAMP} COMMAND ${CMAKE_COMMAND} -E touch ${TIMESTAMP} COMMAND ${CMAKE_COMMAND} -P ${COPY_CMAKE_SCRIPT} - DEPENDS ${COPY_FILES} - COMMENT "Copying files to ${DESTINATION}" + DEPENDS ${COPY_FILES} + COMMENT "Copying files to ${DESTINATION}" ) get_target_property(DEPS ${BUNDLE} "BUNDLE_DEPEND_TARGETS") @@ -911,6 +911,9 @@ function(celix_get_bundle_filename) if (_IMP) _celix_extract_imported_bundle_info(${ARGV0}) set(${ARGV1} ${BUNDLE_FILENAME} PARENT_SCOPE) + unset(BUNDLE_FILE) + unset(BUNDLE_FILENAME) + unset(BUNDLE_SYMBOLIC_NAME) else () get_target_property(BF ${ARGV0} BUNDLE_FILENAME) set(${ARGV1} ${BF} PARENT_SCOPE) @@ -942,6 +945,7 @@ function(celix_get_bundle_file) set(${ARGV1} ${BUNDLE_FILE} PARENT_SCOPE) unset(BUNDLE_FILE) unset(BUNDLE_FILENAME) + unset(BUNDLE_SYMBOLIC_NAME) else () get_target_property(BF ${ARGV0} BUNDLE_FILE) set(${ARGV1} ${BF} PARENT_SCOPE) From 52227e6524681a6a9913f10c43d6f668506472d0 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Tue, 13 Jun 2023 11:57:44 +0800 Subject: [PATCH 17/21] Minor typo fix and documentation improvement. --- cmake/cmake_celix/BundlePackaging.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/cmake_celix/BundlePackaging.cmake b/cmake/cmake_celix/BundlePackaging.cmake index 8fe0f5fd4..7adcce9f9 100644 --- a/cmake/cmake_celix/BundlePackaging.cmake +++ b/cmake/cmake_celix/BundlePackaging.cmake @@ -1032,7 +1032,7 @@ endfunction() #[[ Generate and install a Celix Targets cmake file which contains CMake commands to create imported targets for the bundles -install using the provided . These imported CMake targets can be used in in CMake project using the installed +install using the provided . These imported CMake targets can be used in CMake project using the installed bundles. ```CMake @@ -1041,6 +1041,7 @@ install_celix_targets( [FILE ] [PROJECT_NAME ] [DESTINATION ] + [COMPONENT ] ) ``` @@ -1053,6 +1054,7 @@ Optional Arguments: - FILE: The Celix Targets cmake filename to used, without the cmake extension. Default is BundleTargets - PROJECT_NAME: The project name to used for the share location. Default is the cmake project name. - DESTINATION: The (relative) location to install the Celix Targets cmake file to. Default is share//cmake. +- COMPONENT: Specify an installation component name with which the install rule is associated. ]] function(install_celix_bundle_targets) @@ -1140,7 +1142,7 @@ set_target_properties(${TN} PROPERTIES file(GENERATE OUTPUT "${CONF_FILE}" INPUT "${CONF_IN_FILE}") - #Generate not build type specific targets file + #Generate build-type independent targets file set(GENERIC_CONF_FILE "${CMAKE_BINARY_DIR}/celix/gen/cmake/${EXPORT_NAME}-BundleTargets.cmake") file(GENERATE OUTPUT ${GENERIC_CONF_FILE} CONTENT " # Load bundle information for each installed configuration. From f9403df01bb59cda13626fddd2a50d839306f969 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Fri, 16 Jun 2023 10:03:56 +0800 Subject: [PATCH 18/21] Replace recursive mutex by normal one. --- libs/framework/src/framework.c | 42 +++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c index 0c3983eb4..0a2d1dc6a 100644 --- a/libs/framework/src/framework.c +++ b/libs/framework/src/framework.c @@ -241,11 +241,7 @@ celix_status_t framework_create(framework_pt *out, celix_properties_t* config) { celixThreadMutex_create(&framework->dispatcher.mutex, NULL); celixThreadMutex_create(&framework->frameworkListenersLock, NULL); celixThreadMutex_create(&framework->bundleListenerLock, NULL); - celix_thread_mutexattr_t muAttr; - celixThreadMutexAttr_create(&muAttr); - celixThreadMutexAttr_settype(&muAttr, CELIX_THREAD_MUTEX_RECURSIVE); - celixThreadMutex_create(&framework->installLock, &muAttr); - celixThreadMutexAttr_destroy(&muAttr); + celixThreadMutex_create(&framework->installLock, NULL); celixThreadMutex_create(&framework->installedBundles.mutex, NULL); celixThreadCondition_init(&framework->dispatcher.cond, NULL); framework->dispatcher.active = true; @@ -630,8 +626,8 @@ bool celix_framework_getConfigPropertyAsBool(celix_framework_t* framework, const return result; } -celix_status_t -celix_framework_installBundleInternal(celix_framework_t* framework, const char* bndLoc, long* bndId) { +static celix_status_t +celix_framework_installBundleInternalImpl(celix_framework_t* framework, const char* bndLoc, long* bndId) { celix_status_t status = CELIX_SUCCESS; celix_bundle_t* bundle = NULL; long id = -1L; @@ -645,7 +641,7 @@ celix_framework_installBundleInternal(celix_framework_t* framework, const char* //increase use count of framework bundle to prevent a stop. celix_framework_bundle_entry_t *fwBundleEntry = celix_framework_bundleEntry_getBundleEntryAndIncreaseUseCount(framework, - framework->bundleId); + framework->bundleId); status = CELIX_DO_IF(status, bundle_getState(framework->bundle, &state)); if (status == CELIX_SUCCESS) { if (state == CELIX_BUNDLE_STATE_STOPPING || state == CELIX_BUNDLE_STATE_UNINSTALLED) { @@ -654,13 +650,11 @@ celix_framework_installBundleInternal(celix_framework_t* framework, const char* } } - celixThreadMutex_lock(&framework->installLock); if (status == CELIX_SUCCESS) { if (*bndId == -1L) { id = framework_getBundle(framework, bndLoc); if (id != -1L) { celix_framework_bundleEntry_decreaseUseCount(fwBundleEntry); - celixThreadMutex_unlock(&framework->installLock); *bndId = id; return CELIX_SUCCESS; } @@ -690,6 +684,14 @@ celix_framework_installBundleInternal(celix_framework_t* framework, const char* } celix_framework_bundleEntry_decreaseUseCount(fwBundleEntry); + return status; +} + +celix_status_t +celix_framework_installBundleInternal(celix_framework_t* framework, const char* bndLoc, long* bndId) { + celix_status_t status = CELIX_SUCCESS; + celixThreadMutex_lock(&framework->installLock); + status = celix_framework_installBundleInternalImpl(framework, bndLoc, bndId); celixThreadMutex_unlock(&framework->installLock); return status; } @@ -1921,10 +1923,11 @@ void celix_framework_unloadBundleAsync(celix_framework_t *fw, long bndId) { celix_framework_uninstallBundleInternal(fw, bndId, true, false); } -celix_status_t celix_framework_uninstallBundleEntry(celix_framework_t* framework, celix_framework_bundle_entry_t* bndEntry, bool permanent) { +static celix_status_t celix_framework_uninstallBundleEntryImpl(celix_framework_t* framework, + celix_framework_bundle_entry_t* bndEntry, + bool permanent) { assert(!celix_framework_isCurrentThreadTheEventLoop(framework)); - celixThreadMutex_lock(&framework->installLock); celixThreadRwlock_writeLock(&bndEntry->fsmMutex); celix_bundle_state_e bndState = celix_bundle_getState(bndEntry->bnd); if (bndState == CELIX_BUNDLE_STATE_ACTIVE) { @@ -1934,7 +1937,6 @@ celix_status_t celix_framework_uninstallBundleEntry(celix_framework_t* framework if (!fw_bundleEntry_removeBundleEntry(framework, bndEntry)) { celixThreadRwlock_unlock(&bndEntry->fsmMutex); celix_framework_bundleEntry_decreaseUseCount(bndEntry); - celixThreadMutex_unlock(&framework->installLock); return CELIX_ILLEGAL_STATE; } @@ -1969,9 +1971,17 @@ celix_status_t celix_framework_uninstallBundleEntry(celix_framework_t* framework (void)bundle_destroy(bnd); (void)celix_bundleCache_destroyArchive(framework->cache, archive, permanent); } - celixThreadMutex_unlock(&framework->installLock); framework_logIfError(framework->logger, status, "", "Cannot uninstall bundle"); return status; + +} + +celix_status_t celix_framework_uninstallBundleEntry(celix_framework_t* framework, celix_framework_bundle_entry_t* bndEntry, bool permanent) { + celix_status_t status = CELIX_SUCCESS; + celixThreadMutex_lock(&framework->installLock); + status = celix_framework_uninstallBundleEntryImpl(framework, bndEntry, permanent); + celixThreadMutex_unlock(&framework->installLock); + return status; } static bool celix_framework_stopBundleInternal(celix_framework_t* fw, long bndId, bool forcedAsync) { @@ -2309,7 +2319,7 @@ celix_status_t celix_framework_updateBundleEntry(celix_framework_t* framework, } bndRoot = celix_bundle_getEntry(bndEntry->bnd, NULL); } - status = celix_framework_uninstallBundleEntry(framework, bndEntry, false); + status = celix_framework_uninstallBundleEntryImpl(framework, bndEntry, false); if (status != CELIX_SUCCESS) { errMsg = "uninstall failure"; celixThreadMutex_unlock(&framework->installLock); @@ -2320,7 +2330,7 @@ celix_status_t celix_framework_updateBundleEntry(celix_framework_t* framework, // the bundle is updated with a new location, so the old bundle root can be removed celix_utils_deleteDirectory(bndRoot, NULL); } - status = celix_framework_installBundleInternal(framework, updatedBundleUrl, &bundleId); + status = celix_framework_installBundleInternalImpl(framework, updatedBundleUrl, &bundleId); if (status != CELIX_SUCCESS) { errMsg = "reinstall failure"; celixThreadMutex_unlock(&framework->installLock); From ff0c44cd05d20b1f65519fd2c3383aea90c615ee Mon Sep 17 00:00:00 2001 From: PengZheng Date: Fri, 16 Jun 2023 10:10:11 +0800 Subject: [PATCH 19/21] Revert "Update all bundle activator to use async service registration." This reverts commit 27383f6c7f7fe8b519bb9ebb9e6f6dc338294970. --- bundles/http_admin/gtest/src/sut_activator.c | 8 ++++---- bundles/http_admin/http_admin/src/http_admin.c | 2 +- .../pubsub/integration/gtest/loopback_activator.c | 2 +- .../integration/gtest/tst_endpoint_activator.c | 4 ++-- bundles/pubsub/pubsub_admin_tcp/src/psa_activator.c | 12 ++++++------ .../pubsub/pubsub_admin_udp_mc/src/psa_activator.c | 4 ++-- .../pubsub_admin_websocket/src/psa_activator.c | 4 ++-- .../src/pubsub_websocket_topic_receiver.c | 4 ++-- .../src/pubsub_websocket_topic_sender.c | 4 ++-- bundles/pubsub/pubsub_admin_zmq/src/psa_activator.c | 4 ++-- bundles/pubsub/pubsub_discovery/src/psd_activator.c | 4 ++-- .../src/ps_wire_protocol_activator.c | 2 +- .../src/ps_wire_v2_protocol_activator.c | 2 +- .../src/ps_avrobin_serializer_activator.c | 2 +- .../src/ps_json_serializer_activator.c | 2 +- .../pubsub_topology_manager/src/pstm_activator.c | 4 ++-- .../calculator_service/src/calculator_activator.c | 2 +- .../src/calculator_shell_activator.c | 6 +++--- .../src/remote_example_activator.c | 2 +- .../remote_example_service/src/remote_example_impl.c | 2 +- .../gtest/src/tst_activator.c | 2 +- .../src/remote_service_admin_activator.c | 2 +- .../shell/shell_wui/src/shell_wui_bundle_activator.c | 2 +- .../http_example/src/http_example_bundle_activator.c | 2 +- .../services_example_c/src/simple_provider_example.c | 2 +- .../track_tracker_example/src/activator.c | 2 +- 26 files changed, 44 insertions(+), 44 deletions(-) diff --git a/bundles/http_admin/gtest/src/sut_activator.c b/bundles/http_admin/gtest/src/sut_activator.c index c35256cdd..2c15da497 100644 --- a/bundles/http_admin/gtest/src/sut_activator.c +++ b/bundles/http_admin/gtest/src/sut_activator.c @@ -45,23 +45,23 @@ celix_status_t bnd_start(struct activator *act, celix_bundle_context_t *ctx) { celix_properties_set(props, HTTP_ADMIN_URI, "/alias"); act->httpSvc.handle = act; act->httpSvc.doPut = alias_test_put; - act->httpSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->httpSvc, HTTP_ADMIN_SERVICE_NAME, props); + act->httpSvcId = celix_bundleContext_registerService(ctx, &act->httpSvc, HTTP_ADMIN_SERVICE_NAME, props); celix_properties_t *props2 = celix_properties_create(); celix_properties_set(props2, HTTP_ADMIN_URI, "/foo/bar"); act->httpSvc2.handle = act; - act->httpSvcId2 = celix_bundleContext_registerServiceAsync(ctx, &act->httpSvc2, HTTP_ADMIN_SERVICE_NAME, props2); + act->httpSvcId2 = celix_bundleContext_registerService(ctx, &act->httpSvc2, HTTP_ADMIN_SERVICE_NAME, props2); celix_properties_t *props3 = celix_properties_create(); celix_properties_set(props3, HTTP_ADMIN_URI, "/"); act->httpSvc3.handle = act; - act->httpSvcId3 = celix_bundleContext_registerServiceAsync(ctx, &act->httpSvc3, HTTP_ADMIN_SERVICE_NAME, props3); + act->httpSvcId3 = celix_bundleContext_registerService(ctx, &act->httpSvc3, HTTP_ADMIN_SERVICE_NAME, props3); celix_properties_t *props4 = celix_properties_create(); celix_properties_set(props4, WEBSOCKET_ADMIN_URI, "/"); act->sockSvc.handle = act; act->sockSvc.data = websocket_data_echo; - act->sockSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->sockSvc, WEBSOCKET_ADMIN_SERVICE_NAME, props4); + act->sockSvcId = celix_bundleContext_registerService(ctx, &act->sockSvc, WEBSOCKET_ADMIN_SERVICE_NAME, props4); return CELIX_SUCCESS; } diff --git a/bundles/http_admin/http_admin/src/http_admin.c b/bundles/http_admin/http_admin/src/http_admin.c index e20060da7..b28f7e440 100755 --- a/bundles/http_admin/http_admin/src/http_admin.c +++ b/bundles/http_admin/http_admin/src/http_admin.c @@ -374,7 +374,7 @@ static void httpAdmin_updateInfoSvc(http_admin_manager_t *admin) { if (resources_urls_size > 1) { celix_properties_set(properties, HTTP_ADMIN_INFO_RESOURCE_URLS, resources_urls); } - admin->infoSvcId = celix_bundleContext_registerServiceAsync(admin->context, &admin->infoSvc, HTTP_ADMIN_INFO_SERVICE_NAME, properties); + admin->infoSvcId = celix_bundleContext_registerService(admin->context, &admin->infoSvc, HTTP_ADMIN_INFO_SERVICE_NAME, properties); celixThreadMutex_unlock(&admin->admin_lock); diff --git a/bundles/pubsub/integration/gtest/loopback_activator.c b/bundles/pubsub/integration/gtest/loopback_activator.c index a9d819c0b..c718c4a71 100644 --- a/bundles/pubsub/integration/gtest/loopback_activator.c +++ b/bundles/pubsub/integration/gtest/loopback_activator.c @@ -58,7 +58,7 @@ celix_status_t bnd_start(struct activator *act, celix_bundle_context_t *ctx) { celix_properties_set(props, PUBSUB_SUBSCRIBER_TOPIC, "pong2"); act->subSvc.handle = act; act->subSvc.receive = tst_receive; - act->subSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->subSvc, PUBSUB_SUBSCRIBER_SERVICE_NAME, props); + act->subSvcId = celix_bundleContext_registerService(ctx, &act->subSvc, PUBSUB_SUBSCRIBER_SERVICE_NAME, props); return CELIX_SUCCESS; diff --git a/bundles/pubsub/integration/gtest/tst_endpoint_activator.c b/bundles/pubsub/integration/gtest/tst_endpoint_activator.c index bd8a23a6b..e01a8ea83 100644 --- a/bundles/pubsub/integration/gtest/tst_endpoint_activator.c +++ b/bundles/pubsub/integration/gtest/tst_endpoint_activator.c @@ -51,14 +51,14 @@ celix_status_t bnd_start(struct activator *act, celix_bundle_context_t *ctx) { celix_properties_set(props, PUBSUB_SUBSCRIBER_TOPIC, "pong3"); act->subSvc.handle = act; act->subSvc.receive = tst_receive; - act->subSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->subSvc, PUBSUB_SUBSCRIBER_SERVICE_NAME, props); + act->subSvcId = celix_bundleContext_registerService(ctx, &act->subSvc, PUBSUB_SUBSCRIBER_SERVICE_NAME, props); } { act->countSvc.handle = act; act->countSvc.receiveCount = tst_count; - act->countSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->countSvc, CELIX_RECEIVE_COUNT_SERVICE_NAME, NULL); + act->countSvcId = celix_bundleContext_registerService(ctx, &act->countSvc, CELIX_RECEIVE_COUNT_SERVICE_NAME, NULL); } diff --git a/bundles/pubsub/pubsub_admin_tcp/src/psa_activator.c b/bundles/pubsub/pubsub_admin_tcp/src/psa_activator.c index cc13d7030..008cb7ce5 100644 --- a/bundles/pubsub/pubsub_admin_tcp/src/psa_activator.c +++ b/bundles/pubsub/pubsub_admin_tcp/src/psa_activator.c @@ -83,7 +83,7 @@ int psa_tcp_start(psa_tcp_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_t *props = celix_properties_create(); celix_properties_set(props, PUBSUB_ADMIN_SERVICE_TYPE, PUBSUB_TCP_ADMIN_TYPE); - act->adminSvcId = celix_bundleContext_registerServiceAsync(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props); + act->adminSvcId = celix_bundleContext_registerService(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props); } if (status == CELIX_SUCCESS) { @@ -94,10 +94,10 @@ int psa_tcp_start(psa_tcp_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_set(props, PUBSUB_ADMIN_SERVICE_TYPE, PUBSUB_TCP_ADMIN_TYPE); act->adminMetricsSvcId = - celix_bundleContext_registerServiceAsync(ctx, - &act->adminMetricsService, - PUBSUB_ADMIN_METRICS_SERVICE_NAME, - props); + celix_bundleContext_registerService(ctx, + &act->adminMetricsService, + PUBSUB_ADMIN_METRICS_SERVICE_NAME, + props); } //register shell command service @@ -108,7 +108,7 @@ int psa_tcp_start(psa_tcp_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psa_tcp"); celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psa_tcp"); celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the TCP PSA"); - act->cmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); } return status; diff --git a/bundles/pubsub/pubsub_admin_udp_mc/src/psa_activator.c b/bundles/pubsub/pubsub_admin_udp_mc/src/psa_activator.c index e9058a3a3..0cc543c5a 100644 --- a/bundles/pubsub/pubsub_admin_udp_mc/src/psa_activator.c +++ b/bundles/pubsub/pubsub_admin_udp_mc/src/psa_activator.c @@ -80,7 +80,7 @@ int psa_udpmc_start(psa_udpmc_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_t *props = celix_properties_create(); celix_properties_set(props, PUBSUB_ADMIN_SERVICE_TYPE, PUBSUB_UDPMC_ADMIN_TYPE); - act->adminSvcId = celix_bundleContext_registerServiceAsync(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props); + act->adminSvcId = celix_bundleContext_registerService(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props); } //register shell command service @@ -91,7 +91,7 @@ int psa_udpmc_start(psa_udpmc_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psa_udpmc"); celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psa_udpmc"); celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the UDPMC PSA"); - act->cmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); } return status; diff --git a/bundles/pubsub/pubsub_admin_websocket/src/psa_activator.c b/bundles/pubsub/pubsub_admin_websocket/src/psa_activator.c index 2a41fa50d..33cc86f3f 100644 --- a/bundles/pubsub/pubsub_admin_websocket/src/psa_activator.c +++ b/bundles/pubsub/pubsub_admin_websocket/src/psa_activator.c @@ -70,7 +70,7 @@ int psa_websocket_start(psa_websocket_activator_t *act, celix_bundle_context_t * celix_properties_t *props = celix_properties_create(); celix_properties_set(props, PUBSUB_ADMIN_SERVICE_TYPE, PUBSUB_WEBSOCKET_ADMIN_TYPE); - act->adminSvcId = celix_bundleContext_registerServiceAsync(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props); + act->adminSvcId = celix_bundleContext_registerService(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props); } //register shell command service @@ -81,7 +81,7 @@ int psa_websocket_start(psa_websocket_activator_t *act, celix_bundle_context_t * celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psa_websocket"); celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psa_websocket"); celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the websocket PSA"); - act->cmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); } return status; diff --git a/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_receiver.c b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_receiver.c index 9dc5fd787..e163a7ca7 100644 --- a/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_receiver.c +++ b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_receiver.c @@ -193,8 +193,8 @@ pubsub_websocket_topic_receiver_t* pubsub_websocketTopicReceiver_create(celix_bu receiver->sockSvc.ready = psa_websocketTopicReceiver_ready; receiver->sockSvc.data = psa_websocketTopicReceiver_data; receiver->sockSvc.close = psa_websocketTopicReceiver_close; - receiver->svcId = celix_bundleContext_registerServiceAsync(receiver->ctx, &receiver->sockSvc, - WEBSOCKET_ADMIN_SERVICE_NAME, props); + receiver->svcId = celix_bundleContext_registerService(receiver->ctx, &receiver->sockSvc, + WEBSOCKET_ADMIN_SERVICE_NAME, props); } const char *staticConnects = pubsub_getEnvironmentVariableWithScopeTopic(ctx, PUBSUB_WEBSOCKET_STATIC_CONNECT_SOCKET_ADDRESSES_FOR, topic, scope); diff --git a/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_sender.c b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_sender.c index eb1dc6b10..e8ab06233 100644 --- a/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_sender.c +++ b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_topic_sender.c @@ -115,8 +115,8 @@ pubsub_websocket_topic_sender_t* pubsub_websocketTopicSender_create( sender->websockSvc.handle = sender; sender->websockSvc.ready = psa_websocketTopicSender_ready; sender->websockSvc.close = psa_websocketTopicSender_close; - sender->websockSvcId = celix_bundleContext_registerServiceAsync(ctx, &sender->websockSvc, - WEBSOCKET_ADMIN_SERVICE_NAME, props); + sender->websockSvcId = celix_bundleContext_registerService(ctx, &sender->websockSvc, + WEBSOCKET_ADMIN_SERVICE_NAME, props); } else { sender->websockSvcId = -1; } diff --git a/bundles/pubsub/pubsub_admin_zmq/src/psa_activator.c b/bundles/pubsub/pubsub_admin_zmq/src/psa_activator.c index 3943ff785..913ad34df 100644 --- a/bundles/pubsub/pubsub_admin_zmq/src/psa_activator.c +++ b/bundles/pubsub/pubsub_admin_zmq/src/psa_activator.c @@ -84,7 +84,7 @@ int psa_zmq_start(psa_zmq_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_t *props = celix_properties_create(); celix_properties_set(props, PUBSUB_ADMIN_SERVICE_TYPE, PUBSUB_ZMQ_ADMIN_TYPE); - act->adminSvcId = celix_bundleContext_registerServiceAsync(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props); + act->adminSvcId = celix_bundleContext_registerService(ctx, psaSvc, PUBSUB_ADMIN_SERVICE_NAME, props); } //register shell command service @@ -95,7 +95,7 @@ int psa_zmq_start(psa_zmq_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psa_zmq"); celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psa_zmq"); celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the ZMQ PSA"); - act->cmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); } return status; diff --git a/bundles/pubsub/pubsub_discovery/src/psd_activator.c b/bundles/pubsub/pubsub_discovery/src/psd_activator.c index 0aaa35938..d19cb0f1d 100644 --- a/bundles/pubsub/pubsub_discovery/src/psd_activator.c +++ b/bundles/pubsub/pubsub_discovery/src/psd_activator.c @@ -76,11 +76,11 @@ static celix_status_t psd_start(psd_activator_t *act, celix_bundle_context_t *ct celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psd_etcd"); celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psd_etcd"); celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Overview of discovered/announced endpoints from/to ETCD"); - act->cmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); } if (status == CELIX_SUCCESS) { - act->listenerSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->listenerSvc, PUBSUB_ANNOUNCE_ENDPOINT_LISTENER_SERVICE, NULL); + act->listenerSvcId = celix_bundleContext_registerService(ctx, &act->listenerSvc, PUBSUB_ANNOUNCE_ENDPOINT_LISTENER_SERVICE, NULL); } else { act->listenerSvcId = -1L; } diff --git a/bundles/pubsub/pubsub_protocol/pubsub_protocol_wire_v1/src/ps_wire_protocol_activator.c b/bundles/pubsub/pubsub_protocol/pubsub_protocol_wire_v1/src/ps_wire_protocol_activator.c index 03b130f8e..64abebecf 100644 --- a/bundles/pubsub/pubsub_protocol/pubsub_protocol_wire_v1/src/ps_wire_protocol_activator.c +++ b/bundles/pubsub/pubsub_protocol/pubsub_protocol_wire_v1/src/ps_wire_protocol_activator.c @@ -57,7 +57,7 @@ static int ps_wp_start(ps_wp_activator_t *act, celix_bundle_context_t *ctx) { act->protocolSvc.decodeMetadata = pubsubProtocol_v1_decodeMetadata; act->protocolSvc.decodeFooter = pubsubProtocol_decodeFooter; - act->wireProtocolSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->protocolSvc, PUBSUB_PROTOCOL_SERVICE_NAME, props); + act->wireProtocolSvcId = celix_bundleContext_registerService(ctx, &act->protocolSvc, PUBSUB_PROTOCOL_SERVICE_NAME, props); } return status; } diff --git a/bundles/pubsub/pubsub_protocol/pubsub_protocol_wire_v2/src/ps_wire_v2_protocol_activator.c b/bundles/pubsub/pubsub_protocol/pubsub_protocol_wire_v2/src/ps_wire_v2_protocol_activator.c index 0b8841230..86708eba4 100644 --- a/bundles/pubsub/pubsub_protocol/pubsub_protocol_wire_v2/src/ps_wire_v2_protocol_activator.c +++ b/bundles/pubsub/pubsub_protocol/pubsub_protocol_wire_v2/src/ps_wire_v2_protocol_activator.c @@ -58,7 +58,7 @@ static int ps_wp_start(ps_wp_activator_t *act, celix_bundle_context_t *ctx) { act->protocolSvc.decodeMetadata = pubsubProtocol_wire_v2_decodeMetadata; act->protocolSvc.decodeFooter = pubsubProtocol_wire_v2_decodeFooter; - act->wireProtocolSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->protocolSvc, PUBSUB_PROTOCOL_SERVICE_NAME, props); + act->wireProtocolSvcId = celix_bundleContext_registerService(ctx, &act->protocolSvc, PUBSUB_PROTOCOL_SERVICE_NAME, props); } return status; } diff --git a/bundles/pubsub/pubsub_serializer_avrobin/src/ps_avrobin_serializer_activator.c b/bundles/pubsub/pubsub_serializer_avrobin/src/ps_avrobin_serializer_activator.c index 11cfe1520..275a72da7 100644 --- a/bundles/pubsub/pubsub_serializer_avrobin/src/ps_avrobin_serializer_activator.c +++ b/bundles/pubsub/pubsub_serializer_avrobin/src/ps_avrobin_serializer_activator.c @@ -46,7 +46,7 @@ static int psav_start(psav_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_t *props = celix_properties_create(); celix_properties_set(props, PUBSUB_SERIALIZER_TYPE_KEY, PUBSUB_AVROBIN_SERIALIZER_TYPE); - act->serializerSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->serializerSvc, PUBSUB_SERIALIZER_SERVICE_NAME, props); + act->serializerSvcId = celix_bundleContext_registerService(ctx, &act->serializerSvc, PUBSUB_SERIALIZER_SERVICE_NAME, props); } return status; } diff --git a/bundles/pubsub/pubsub_serializer_json/src/ps_json_serializer_activator.c b/bundles/pubsub/pubsub_serializer_json/src/ps_json_serializer_activator.c index afb62505e..9df8e13f2 100644 --- a/bundles/pubsub/pubsub_serializer_json/src/ps_json_serializer_activator.c +++ b/bundles/pubsub/pubsub_serializer_json/src/ps_json_serializer_activator.c @@ -44,7 +44,7 @@ static int psjs_start(psjs_activator_t *act, celix_bundle_context_t *ctx) { /* Set serializer type */ celix_properties_t *props = celix_properties_create(); celix_properties_set(props, PUBSUB_SERIALIZER_TYPE_KEY, PUBSUB_JSON_SERIALIZER_TYPE); - act->serializerSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->serializerSvc, PUBSUB_SERIALIZER_SERVICE_NAME, props); + act->serializerSvcId = celix_bundleContext_registerService(ctx, &act->serializerSvc, PUBSUB_SERIALIZER_SERVICE_NAME, props); } return status; diff --git a/bundles/pubsub/pubsub_topology_manager/src/pstm_activator.c b/bundles/pubsub/pubsub_topology_manager/src/pstm_activator.c index 1bdfc69f0..347d6471b 100644 --- a/bundles/pubsub/pubsub_topology_manager/src/pstm_activator.c +++ b/bundles/pubsub/pubsub_topology_manager/src/pstm_activator.c @@ -118,7 +118,7 @@ static int pstm_start(pstm_activator_t *act, celix_bundle_context_t *ctx) { act->discListenerSvc.handle = act->manager; act->discListenerSvc.addDiscoveredEndpoint = pubsub_topologyManager_addDiscoveredEndpoint; act->discListenerSvc.removeDiscoveredEndpoint = pubsub_topologyManager_removeDiscoveredEndpoint; - act->discListenerSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->discListenerSvc, PUBSUB_DISCOVERED_ENDPOINT_LISTENER_SERVICE, NULL); + act->discListenerSvcId = celix_bundleContext_registerService(ctx, &act->discListenerSvc, PUBSUB_DISCOVERED_ENDPOINT_LISTENER_SERVICE, NULL); } //register shell command @@ -129,7 +129,7 @@ static int pstm_start(pstm_activator_t *act, celix_bundle_context_t *ctx) { celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::pstm"); celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "pstm [topology|metrics]"); //TODO add search topic/scope option celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "pubsub_topology_info: Overview of Topology information for PubSub"); - act->shellCmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &act->shellCmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + act->shellCmdSvcId = celix_bundleContext_registerService(ctx, &act->shellCmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props); } //TODO add tracker for pubsub_serializer and diff --git a/bundles/remote_services/examples/calculator_service/src/calculator_activator.c b/bundles/remote_services/examples/calculator_service/src/calculator_activator.c index e39aa4840..261169e0e 100644 --- a/bundles/remote_services/examples/calculator_service/src/calculator_activator.c +++ b/bundles/remote_services/examples/calculator_service/src/calculator_activator.c @@ -44,7 +44,7 @@ celix_status_t calculatorBndStart(struct activator *act, celix_bundle_context_t celix_properties_set(properties, CELIX_FRAMEWORK_SERVICE_VERSION, CALCULATOR_SERVICE_VERSION); celix_properties_set(properties, OSGI_RSA_SERVICE_EXPORTED_CONFIGS, CALCULATOR_CONFIGURATION_TYPE); - act->svcId = celix_bundleContext_registerServiceAsync(ctx, &act->service, CALCULATOR_SERVICE, properties); + act->svcId = celix_bundleContext_registerService(ctx, &act->service, CALCULATOR_SERVICE, properties); } return CELIX_SUCCESS; } diff --git a/bundles/remote_services/examples/calculator_shell/src/calculator_shell_activator.c b/bundles/remote_services/examples/calculator_shell/src/calculator_shell_activator.c index 523dab099..31e5c49a6 100644 --- a/bundles/remote_services/examples/calculator_shell/src/calculator_shell_activator.c +++ b/bundles/remote_services/examples/calculator_shell/src/calculator_shell_activator.c @@ -42,19 +42,19 @@ static celix_status_t calcShell_start(calc_shell_activator_t *activator, celix_b activator->addCmd.executeCommand = addCommand_execute; celix_properties_t *props = celix_properties_create(); celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "add"); - activator->addCmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &activator->addCmd, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + activator->addCmdSvcId = celix_bundleContext_registerService(ctx, &activator->addCmd, CELIX_SHELL_COMMAND_SERVICE_NAME, props); activator->subCmd.handle = ctx; activator->subCmd.executeCommand = subCommand_execute; props = celix_properties_create(); celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "sub"); - activator->subCmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &activator->subCmd, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + activator->subCmdSvcId = celix_bundleContext_registerService(ctx, &activator->subCmd, CELIX_SHELL_COMMAND_SERVICE_NAME, props); activator->sqrtCmd.handle = ctx; activator->sqrtCmd.executeCommand = sqrtCommand_execute; props = celix_properties_create(); celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "sqrt"); - activator->sqrtCmdSvcId = celix_bundleContext_registerServiceAsync(ctx, &activator->sqrtCmd, CELIX_SHELL_COMMAND_SERVICE_NAME, props); + activator->sqrtCmdSvcId = celix_bundleContext_registerService(ctx, &activator->sqrtCmd, CELIX_SHELL_COMMAND_SERVICE_NAME, props); return CELIX_SUCCESS; } diff --git a/bundles/remote_services/examples/remote_example_service/src/remote_example_activator.c b/bundles/remote_services/examples/remote_example_service/src/remote_example_activator.c index d40163eee..59522e30d 100644 --- a/bundles/remote_services/examples/remote_example_service/src/remote_example_activator.c +++ b/bundles/remote_services/examples/remote_example_service/src/remote_example_activator.c @@ -46,7 +46,7 @@ celix_status_t remoteExampleBndStart(struct activator *act, celix_bundle_context celix_properties_t *properties = celix_properties_create(); celix_properties_set(properties, OSGI_RSA_SERVICE_EXPORTED_INTERFACES, REMOTE_EXAMPLE_NAME); - act->svcId = celix_bundleContext_registerServiceAsync(ctx, &act->service, REMOTE_EXAMPLE_NAME, properties); + act->svcId = celix_bundleContext_registerService(ctx, &act->service, REMOTE_EXAMPLE_NAME, properties); } return CELIX_SUCCESS; } diff --git a/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.c b/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.c index a18b4d2d2..f462d3427 100644 --- a/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.c +++ b/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.c @@ -161,7 +161,7 @@ int remoteExample_createAdditionalRemoteService(remote_example_impl_t* impl) { } else { celix_properties_t *properties = celix_properties_create(); celix_properties_set(properties, OSGI_RSA_SERVICE_EXPORTED_INTERFACES, REMOTE_EXAMPLE_NAME); - long newSvcId = celix_bundleContext_registerServiceAsync(impl->ctx, &impl->additionalSvc, REMOTE_EXAMPLE_NAME, properties); + long newSvcId = celix_bundleContext_registerService(impl->ctx, &impl->additionalSvc, REMOTE_EXAMPLE_NAME, properties); pthread_mutex_lock(&impl->mutex); prevSvcId = impl->additionalSvcId; if (prevSvcId == -1L) { diff --git a/bundles/remote_services/remote_service_admin_dfi/gtest/src/tst_activator.c b/bundles/remote_services/remote_service_admin_dfi/gtest/src/tst_activator.c index 66a977e51..a571f1d04 100644 --- a/bundles/remote_services/remote_service_admin_dfi/gtest/src/tst_activator.c +++ b/bundles/remote_services/remote_service_admin_dfi/gtest/src/tst_activator.c @@ -360,7 +360,7 @@ static celix_status_t bndStart(struct activator *act, celix_bundle_context_t* ct } //register test service - act->svcId = celix_bundleContext_registerServiceAsync(ctx, &act->testSvc, TST_SERVICE_NAME, NULL); + act->svcId = celix_bundleContext_registerService(ctx, &act->testSvc, TST_SERVICE_NAME, NULL); return CELIX_SUCCESS; } diff --git a/bundles/remote_services/remote_service_admin_dfi/src/remote_service_admin_activator.c b/bundles/remote_services/remote_service_admin_dfi/src/remote_service_admin_activator.c index a81ea8153..0b470da72 100644 --- a/bundles/remote_services/remote_service_admin_dfi/src/remote_service_admin_activator.c +++ b/bundles/remote_services/remote_service_admin_dfi/src/remote_service_admin_activator.c @@ -56,7 +56,7 @@ static celix_status_t celix_rsa_start(celix_remote_service_admin_activator_t* ac activator->adminService.importRegistration_getException = importRegistration_getException; activator->adminService.importRegistration_getImportReference = importRegistration_getImportReference; - activator->svcIdRsa = celix_bundleContext_registerServiceAsync(ctx, &activator->adminService, OSGI_RSA_REMOTE_SERVICE_ADMIN, NULL); + activator->svcIdRsa = celix_bundleContext_registerService(ctx, &activator->adminService, OSGI_RSA_REMOTE_SERVICE_ADMIN, NULL); } return status; diff --git a/bundles/shell/shell_wui/src/shell_wui_bundle_activator.c b/bundles/shell/shell_wui/src/shell_wui_bundle_activator.c index b9c46c865..d2bfac3bc 100644 --- a/bundles/shell/shell_wui/src/shell_wui_bundle_activator.c +++ b/bundles/shell/shell_wui/src/shell_wui_bundle_activator.c @@ -77,7 +77,7 @@ static celix_status_t shellWui_activator_start(shell_wui_activator_data_t *data, celix_properties_set(props, WEBSOCKET_ADMIN_URI, "/shell/socket"); data->sockSvc.handle = data; data->sockSvc.data = websocket_data_handler; - data->sockSvcId = celix_bundleContext_registerServiceAsync(ctx, &data->sockSvc, WEBSOCKET_ADMIN_SERVICE_NAME, props); + data->sockSvcId = celix_bundleContext_registerService(ctx, &data->sockSvc, WEBSOCKET_ADMIN_SERVICE_NAME, props); return CELIX_SUCCESS; } diff --git a/examples/celix-examples/http_example/src/http_example_bundle_activator.c b/examples/celix-examples/http_example/src/http_example_bundle_activator.c index 5142958be..923eda6b0 100644 --- a/examples/celix-examples/http_example/src/http_example_bundle_activator.c +++ b/examples/celix-examples/http_example/src/http_example_bundle_activator.c @@ -47,7 +47,7 @@ static celix_status_t httpExample_activator_start(http_example_activator_data_t celix_properties_set(props, WEBSOCKET_ADMIN_URI, "/hello/socket"); data->sockSvc.handle = data; data->sockSvc.ready = websocket_ready_handler; - data->sockSvcId = celix_bundleContext_registerServiceAsync(ctx, &data->sockSvc, WEBSOCKET_ADMIN_SERVICE_NAME, props); + data->sockSvcId = celix_bundleContext_registerService(ctx, &data->sockSvc, WEBSOCKET_ADMIN_SERVICE_NAME, props); return CELIX_SUCCESS; } diff --git a/examples/celix-examples/services_example_c/src/simple_provider_example.c b/examples/celix-examples/services_example_c/src/simple_provider_example.c index d23ac9b4b..9f1b95c21 100644 --- a/examples/celix-examples/services_example_c/src/simple_provider_example.c +++ b/examples/celix-examples/services_example_c/src/simple_provider_example.c @@ -40,7 +40,7 @@ static celix_status_t activator_start(activator_data_t *data, celix_bundle_conte data->seed = 42; data->svcId = -1L; - data->svcId = celix_bundleContext_registerServiceAsync(ctx, &data->svc, EXAMPLE_CALC_NAME, NULL); + data->svcId = celix_bundleContext_registerService(ctx, &data->svc, EXAMPLE_CALC_NAME, NULL); printf("Registered calc service with service id %li\n", data->svcId); return CELIX_SUCCESS; diff --git a/examples/celix-examples/track_tracker_example/src/activator.c b/examples/celix-examples/track_tracker_example/src/activator.c index 1334a7c2f..c5a05e578 100644 --- a/examples/celix-examples/track_tracker_example/src/activator.c +++ b/examples/celix-examples/track_tracker_example/src/activator.c @@ -86,7 +86,7 @@ celix_status_t activator_start(activator_data_t* act, celix_bundle_context_t *ct act->svc.handle = act; act->svc.calc = calc; //note only triggers on calcTrk1, because of filter restrictions - act->svcId = celix_bundleContext_registerServiceAsync(ctx, &act->svc, CALC_SERVICE_NAME, NULL); + act->svcId = celix_bundleContext_registerService(ctx, &act->svc, CALC_SERVICE_NAME, NULL); return CELIX_SUCCESS; } From 6c061080038b7c6bc83385c11bfd3520436f4cce Mon Sep 17 00:00:00 2001 From: PengZheng Date: Fri, 16 Jun 2023 11:09:56 +0800 Subject: [PATCH 20/21] Make unload an internal operation to avoid confusing our users. --- .../src/CelixBundleContextBundlesTestSuite.cc | 9 ++++--- libs/framework/include/celix_bundle_context.h | 17 ------------ libs/framework/src/bundle_context_private.h | 27 +++++++++++++++++-- 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc b/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc index c3b3df939..37cf9b2a7 100644 --- a/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc +++ b/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc @@ -19,14 +19,15 @@ #include -#include +#include +#include #include +#include #include #include -#include -#include -#include +#include +#include "bundle_context_private.h" #include "celix_api.h" #include "celix_file_utils.h" diff --git a/libs/framework/include/celix_bundle_context.h b/libs/framework/include/celix_bundle_context.h index 40430d284..2926bac43 100644 --- a/libs/framework/include/celix_bundle_context.h +++ b/libs/framework/include/celix_bundle_context.h @@ -838,7 +838,6 @@ CELIX_FRAMEWORK_EXPORT size_t celix_bundleContext_useServicesWithOptions( celix_bundle_context_t *ctx, const celix_service_use_options_t *opts); - /** * @brief List the installed and started bundle ids. * The bundle ids does not include the framework bundle (bundle id CELIX_FRAMEWORK_BUNDLE_ID). @@ -905,22 +904,6 @@ CELIX_FRAMEWORK_EXPORT long celix_bundleContext_installBundle(celix_bundle_conte */ CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_uninstallBundle(celix_bundle_context_t *ctx, long bndId); -/** - * @brief Unload the bundle with the provided bundle id. If needed the bundle will be stopped first. - * Will silently ignore bundle ids < 0. - * Note that unloaded bundle is kept in bundle cache and can be reloaded with the celix_bundleContext_installBundle function. - * - * If this function is called on the Celix event thread, the actual stopping of the bundle will be done async and - * on a separate thread. - * If this function is called from a different thread than the Celix event thread, then the function will return after - * the bundle is stopped. - * - * @param ctx The bundle context - * @param bndId The bundle id to unload. - * @return true if the bundle is correctly unloaded. False if not. - */ -CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_unloadBundle(celix_bundle_context_t *ctx, long bndId); - /** * @brief Stop the bundle with the provided bundle id. * Will silently ignore bundle ids < 0. diff --git a/libs/framework/src/bundle_context_private.h b/libs/framework/src/bundle_context_private.h index 4a46a9547..fa2c2c9c3 100644 --- a/libs/framework/src/bundle_context_private.h +++ b/libs/framework/src/bundle_context_private.h @@ -21,11 +21,16 @@ #define BUNDLE_CONTEXT_PRIVATE_H_ #include "bundle_context.h" -#include "celix_log.h" #include "bundle_listener.h" #include "celix_bundle_context.h" +#include "celix_log.h" #include "listener_hook_service.h" #include "service_tracker.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif typedef struct celix_bundle_context_bundle_tracker_entry { celix_bundle_context_t *ctx; @@ -84,8 +89,26 @@ struct celix_bundle_context { hash_map_t *stoppingTrackerEventIds; //key = trackerId, value = eventId for stopping the tracker. Note id are only present if the stop tracking is queued. }; +/** + * @brief Unload the bundle with the provided bundle id. If needed the bundle will be stopped first. + * Will silently ignore bundle ids < 0. + * Note that unloaded bundle is kept in bundle cache and can be reloaded with the celix_bundleContext_installBundle function. + * + * If this function is called on the Celix event thread, the actual stopping of the bundle will be done async and + * on a separate thread. + * If this function is called from a different thread than the Celix event thread, then the function will return after + * the bundle is stopped. + * + * @param ctx The bundle context + * @param bndId The bundle id to unload. + * @return true if the bundle is correctly unloaded. False if not. + */ +bool celix_bundleContext_unloadBundle(celix_bundle_context_t* ctx, long bndId); -void celix_bundleContext_cleanup(celix_bundle_context_t *ctx); +void celix_bundleContext_cleanup(celix_bundle_context_t* ctx); +#ifdef __cplusplus +} +#endif #endif /* BUNDLE_CONTEXT_PRIVATE_H_ */ From 58a3c3b02b50701f67cfd5f475f870966a4ff476 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Fri, 16 Jun 2023 20:10:17 +0800 Subject: [PATCH 21/21] Minor documentation improvement. --- libs/framework/include/celix_framework.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/framework/include/celix_framework.h b/libs/framework/include/celix_framework.h index 16da33c43..8275c0fac 100644 --- a/libs/framework/include/celix_framework.h +++ b/libs/framework/include/celix_framework.h @@ -94,6 +94,7 @@ CELIX_FRAMEWORK_EXPORT size_t celix_framework_useBundles(celix_framework_t* fw, /** * @brief Use the currently active bundles. * The provided callback will be called for all the currently active bundles. + * The bundle state is guaranteed to be active during the callback. * * @warning Calling synchronous bundle-state changing functions (e.g. celix_bundleContext_stopBundle) from the callback * will lead to deadlocks. @@ -102,7 +103,6 @@ CELIX_FRAMEWORK_EXPORT size_t celix_framework_useBundles(celix_framework_t* fw, * @param includeFrameworkBundle If true the callback will also be triggered for the framework bundle. * @param callbackHandle The data pointer, which will be used in the callbacks * @param use The callback which will be called for the currently active bundles. - * The bundle state is guaranteed to be active during the callback. * @return The number of times the use callback is called. */ CELIX_FRAMEWORK_EXPORT size_t celix_framework_useActiveBundles(celix_framework_t* fw,