You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pe...@apache.org on 2023/06/02 15:04:05 UTC
[celix] 04/08: Add support for bundle unload.
This is an automated email from the ASF dual-hosted git repository.
pengzheng pushed a commit to branch feature/556-osgi-uninstall
in repository https://gitbox.apache.org/repos/asf/celix.git
commit 6008b3d734a204711b98c4b588bcd51dfa0b2384
Author: PengZheng <ho...@gmail.com>
AuthorDate: Thu Jun 1 21:40:26 2023 +0800
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 +
bundles/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 +++++++++++++++++++++-
.../framework/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(-)
diff --git a/bundles/shell/shell/CMakeLists.txt b/bundles/shell/shell/CMakeLists.txt
index a07c76b6..34914da8 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 36d1f9c2..4117f0ad 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 dd3934ad..8edbf092 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 <file> [<file> ...]"
+ .usage = "uninstall <id> [<id> ...]"
};
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 <id> [<id> ...]"
+ };
+ 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 6c0a8d06..a2be1070 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 00000000..b27a37e1
--- /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 e6213766..f7672087 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<char **>(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<char **>(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<char **>(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 1a3562c1..89c20f61 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 8b1ef2bc..fc73b180 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 e5beb0d2..2bfbd114 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 7f08f15e..64eaa241 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 8a802b7c..b3f70232 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 823d3d19..8671abac 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 669778d8..6ffa9bb3 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 f2944cac..c506e94b 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.