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/03 07:13:43 UTC
[celix] branch feature/556-osgi-uninstall-2 created (now 415b8eb3)
This is an automated email from the ASF dual-hosted git repository.
pengzheng pushed a change to branch feature/556-osgi-uninstall-2
in repository https://gitbox.apache.org/repos/asf/celix.git
at 415b8eb3 Implement bundle update as bundle unload plus bundle install.
This branch includes the following new commits:
new 415b8eb3 Implement bundle update as bundle unload plus bundle install.
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
[celix] 01/01: Implement bundle update as bundle unload plus bundle install.
Posted by pe...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
pengzheng pushed a commit to branch feature/556-osgi-uninstall-2
in repository https://gitbox.apache.org/repos/asf/celix.git
commit 415b8eb38ec98650c6f87a42fdd56d2ce2cc5fd6
Author: PengZheng <ho...@gmail.com>
AuthorDate: Sat Jun 3 15:13:31 2023 +0800
Implement bundle update as bundle unload plus bundle install.
---
.../src/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 38aa3b3c..7f0896c5 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 945242db..c37ef142 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 0d222bb7..c3b3df93 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 3d3d71e1..40430d28 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 ad833ce5..16da33c4 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 aa0bbce8..94a5933d 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 14f5ea86..fb093705 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 <stdbool.h>
-#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 e730133c..0c3983eb 100644
--- a/libs/framework/src/framework.c
+++ b/libs/framework/src/framework.c
@@ -17,33 +17,35 @@
* under the License.
*/
-#include <stdlib.h>
+#include <assert.h>
+#include <celix_log_utils.h>
+#include <stdbool.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <stdbool.h>
#include <uuid/uuid.h>
-#include <assert.h>
-#include <celix_log_utils.h>
+#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;
}