You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2020/02/05 18:26:11 UTC

[celix] branch feature/uninstall_bundle_issue updated: gh-145: Moves some handling of bundle state, stopping, starting & uinstall to framework

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

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


The following commit(s) were added to refs/heads/feature/uninstall_bundle_issue by this push:
     new 1304dfb  gh-145: Moves some handling of bundle state,stopping,starting & uinstall to framework
1304dfb is described below

commit 1304dfbf91b47ebb6ce48e282e13274ba916e30e
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Wed Feb 5 19:25:55 2020 +0100

    gh-145: Moves some handling of bundle state,stopping,starting & uinstall to framework
    
    This is done because in framwork.c there is direct access to the bundle locking mechanisms simplifying to code.
---
 libs/framework/include/celix_bundle_context.h |  12 +-
 libs/framework/include/celix_framework.h      |  58 ++++++++++
 libs/framework/private/mock/framework_mock.c  |  43 +++++++
 libs/framework/src/bundle_context.c           | 118 +------------------
 libs/framework/src/framework.c                | 156 +++++++++++++++++++++-----
 5 files changed, 243 insertions(+), 144 deletions(-)

diff --git a/libs/framework/include/celix_bundle_context.h b/libs/framework/include/celix_bundle_context.h
index ab4b827..8699cbf 100644
--- a/libs/framework/include/celix_bundle_context.h
+++ b/libs/framework/include/celix_bundle_context.h
@@ -618,30 +618,30 @@ long celix_bundleContext_installBundle(celix_bundle_context_t *ctx, const char *
  * Will silently ignore bundle ids < 0.
  *
  * @param ctx The bundle context
- * @param bundleId The bundle id to uninstall.
+ * @param bndId The bundle id to uninstall.
  * @return true if the bundle is correctly uninstalled. False if not.
  */
-bool celix_bundleContext_uninstallBundle(celix_bundle_context_t *ctx, long bundleId);
+bool celix_bundleContext_uninstallBundle(celix_bundle_context_t *ctx, long bndId);
 
 /**
  * Stop the bundle with the provided bundle id.
  * Will silently ignore bundle ids < 0.
  *
  * @param ctx The bundle context
- * @param bundleId The bundle id to stop.
+ * @param bndId The bundle id to stop.
  * @return true if the bundle is found & correctly stop. False if not.
  */
-bool celix_bundleContext_stopBundle(celix_bundle_context_t *ctx, long bundleId);
+bool celix_bundleContext_stopBundle(celix_bundle_context_t *ctx, long bndId);
 
 /**
  * Start the bundle with the provided bundle id.
  * Will silently ignore bundle ids < 0.
  *
  * @param ctx The bundle context
- * @param bundleId The bundle id to start.
+ * @param bndId The bundle id to start.
  * @return true if the bundle is found & correctly started. False if not.
  */
-bool celix_bundleContext_startBundle(celix_bundle_context_t *ctx, long bundleId);
+bool celix_bundleContext_startBundle(celix_bundle_context_t *ctx, long bndId);
 
 /**
  * track bundles
diff --git a/libs/framework/include/celix_framework.h b/libs/framework/include/celix_framework.h
index 470de9b..c3ba650 100644
--- a/libs/framework/include/celix_framework.h
+++ b/libs/framework/include/celix_framework.h
@@ -76,6 +76,64 @@ void celix_framework_useBundles(celix_framework_t *fw, bool includeFrameworkBund
  */
 bool celix_framework_useBundle(celix_framework_t *fw, bool onlyActive, long bndId, void *callbackHandle, void(*use)(void *handle, const celix_bundle_t *bnd));
 
+/**
+ * Check whether a bundle is installed.
+ * @param fw        The Celix framework
+ * @param bndId     The bundle id to check
+ * @return          true if the bundle is installed.
+ */
+bool celix_framework_isBundleInstalled(celix_framework_t *fw, long bndId);
+
+/**
+ * Check whether the bundle is active.
+ * @param fw        The Celix framework
+ * @param bndId     The bundle id to check
+ * @return          true if the bundle is installed and active.
+ */
+bool celix_framework_isBundleActive(celix_framework_t *fw, long bndId);
+
+
+/**
+ * Install and optional start a bundle.
+ * Will silently ignore bundle ids < 0.
+ *
+ * @param fw The Celix framework
+ * @param bundleLoc The bundle location to the bundle zip file.
+ * @param autoStart If the bundle should also be started.
+ * @return the bundleId (>= 0) or < 0 if the bundle could not be installed and possibly started.
+ */
+long celix_framework_installBundle(celix_framework_t *fw, const char *bundleLoc, bool autoStart);
+
+/**
+ * Uninstall the bundle with the provided bundle id. If needed the bundle will be stopped first.
+ * Will silently ignore bundle ids < 0.
+ *
+ * @param fw The Celix framework
+ * @param bndId The bundle id to uninstall.
+ * @return true if the bundle is correctly uninstalled. False if not.
+ */
+bool celix_framework_uninstallBundle(celix_framework_t *fw, long bndId);
+
+/**
+ * Stop the bundle with the provided bundle id.
+ * Will silently ignore bundle ids < 0.
+ *
+ * @param fw The Celix framework
+ * @param bndId The bundle id to stop.
+ * @return true if the bundle is found & correctly stop. False if not.
+ */
+bool celix_framework_stopBundle(celix_framework_t *fw, long bndId);
+
+/**
+ * Start the bundle with the provided bundle id.
+ * Will silently ignore bundle ids < 0.
+ *
+ * @param fw The Celix framework
+ * @param bndId The bundle id to start.
+ * @return true if the bundle is found & correctly started. False if not.
+ */
+bool celix_framework_startBundle(celix_framework_t *fw, long bndId);
+
 
 
 #ifdef __cplusplus
diff --git a/libs/framework/private/mock/framework_mock.c b/libs/framework/private/mock/framework_mock.c
index 1f32931..4b48696 100644
--- a/libs/framework/private/mock/framework_mock.c
+++ b/libs/framework/private/mock/framework_mock.c
@@ -347,4 +347,47 @@ service_registration_t* celix_framework_registerServiceFactory(framework_t *fw ,
 			->withPointerParameters("factory", factory)
 			->withPointerParameters("properties", properties);
 	return mock_c()->returnValue().value.pointerValue;
+}
+
+bool celix_framework_isBundleInstalled(celix_framework_t *fw, long bndId) {
+    mock_c()->actualCall("celix_framework_isBundleInstalled")
+            ->withPointerParameters("fw", fw)
+            ->withLongIntParameters("bndId", bndId);
+    return mock_c()->returnValue().value.boolValue;
+}
+
+bool celix_framework_isBundleActive(celix_framework_t *fw, long bndId) {
+    mock_c()->actualCall("celix_framework_isBundleActive")
+            ->withPointerParameters("fw", fw)
+            ->withLongIntParameters("bndId", bndId);
+    return mock_c()->returnValue().value.boolValue;
+}
+
+long celix_framework_installBundle(celix_framework_t *fw, const char *bundleLoc, bool autoStart) {
+    mock_c()->actualCall("celix_framework_installBundle")
+            ->withPointerParameters("fw", fw)
+            ->withStringParameters("bundleLoc", bundleLoc)
+            ->withBoolParameters("autoStart", autoStart);
+    return mock_c()->returnValue().value.longIntValue;
+}
+
+bool celix_framework_uninstallBundle(celix_framework_t *fw, long bndId) {
+    mock_c()->actualCall("celix_framework_uninstallBundle")
+            ->withPointerParameters("fw", fw)
+            ->withLongIntParameters("bndId", bndId);
+    return mock_c()->returnValue().value.boolValue;
+}
+
+bool celix_framework_stopBundle(celix_framework_t *fw, long bndId) {
+    mock_c()->actualCall("celix_framework_stopBundle")
+            ->withPointerParameters("fw", fw)
+            ->withLongIntParameters("bndId", bndId);
+    return mock_c()->returnValue().value.boolValue;
+}
+
+bool celix_framework_startBundle(celix_framework_t *fw, long bndId) {
+    mock_c()->actualCall("celix_framework_startBundle")
+            ->withPointerParameters("fw", fw)
+            ->withLongIntParameters("bndId", bndId);
+    return mock_c()->returnValue().value.boolValue;
 }
\ No newline at end of file
diff --git a/libs/framework/src/bundle_context.c b/libs/framework/src/bundle_context.c
index 11cb39a..4ae0d2a 100644
--- a/libs/framework/src/bundle_context.c
+++ b/libs/framework/src/bundle_context.c
@@ -684,20 +684,7 @@ void celix_bundleContext_stopTracker(bundle_context_t *ctx, long trackerId) {
 }
 
 long celix_bundleContext_installBundle(bundle_context_t *ctx, const char *bundleLoc, bool autoStart) {
-    long bundleId = -1;
-    bundle_t *bnd = NULL;
-    celix_status_t status = CELIX_SUCCESS;
-
-    if (ctx != NULL && fw_installBundle(ctx->framework, &bnd, bundleLoc, NULL) == CELIX_SUCCESS) {
-        status = bundle_getBundleId(bnd, &bundleId);
-        if (status == CELIX_SUCCESS && autoStart) {
-            status = bundle_start(bnd);
-        }
-    }
-
-    framework_logIfError(logger, status, NULL, "Failed to install bundle");
-
-    return bundleId;
+    return celix_framework_installBundle(ctx->framework, bundleLoc, autoStart);
 }
 
 static void bundleContext_listBundlesCallback(void *handle, const bundle_t *c_bnd) {
@@ -715,117 +702,24 @@ celix_array_list_t* celix_bundleContext_listBundles(celix_bundle_context_t *ctx)
 }
 
 bool celix_bundleContext_isBundleInstalled(celix_bundle_context_t *ctx, long bndId) {
-    celix_bundle_t *bnd = framework_getBundleById(ctx->framework, bndId);
-    return bnd != NULL;
-}
-
-static void celix_bundleContext_isBundleActiveCallback(void *handle, const celix_bundle_t *bnd) {
-    bool *active = handle;
-    *active = celix_bundle_getState(bnd) == OSGI_FRAMEWORK_BUNDLE_ACTIVE;
+    return celix_framework_isBundleInstalled(ctx->framework, bndId);
 }
 
 bool celix_bundleContext_isBundleActive(celix_bundle_context_t *ctx, long bndId) {
-    bool active = false;
-    celix_bundleContext_useBundle(ctx, bndId, &active, celix_bundleContext_isBundleActiveCallback);
-    return active;
-}
-
-static void bundleContext_startBundleCallback(void *handle, const bundle_t *c_bnd) {
-    bool *started = handle;
-    *started = false;
-    bundle_t *bnd = (bundle_t*)c_bnd;
-    celix_bundle_state_e state = celix_bundle_getState(bnd);
-    if (state == OSGI_FRAMEWORK_BUNDLE_INSTALLED || state == OSGI_FRAMEWORK_BUNDLE_RESOLVED) {
-        celix_status_t rc = bundle_start(bnd);
-        *started = rc == CELIX_SUCCESS;
-    }
+    return celix_framework_isBundleActive(ctx->framework, bndId);
 }
 
 bool celix_bundleContext_startBundle(celix_bundle_context_t *ctx, long bundleId) {
-    bool started = false;
-
-    celix_framework_useBundle(ctx->framework, false, bundleId, &started, bundleContext_startBundleCallback);
-    return started;
+    return celix_framework_startBundle(ctx->framework, bundleId);
 }
 
 
-static void bundleContext_stopBundleCallback(void *handle, const bundle_t *c_bnd) {
-    bool *stopped = handle;
-    *stopped = false;
-    bundle_t *bnd = (bundle_t*)c_bnd;
-    if (celix_bundle_getState(bnd) == OSGI_FRAMEWORK_BUNDLE_ACTIVE) {
-        celix_status_t rc = bundle_stop(bnd);
-        *stopped = rc == CELIX_SUCCESS;
-    }
-}
-
 bool celix_bundleContext_stopBundle(celix_bundle_context_t *ctx, long bundleId) {
-    bool stopped = false;
-    celix_framework_useBundle(ctx->framework, true, bundleId, &stopped, bundleContext_stopBundleCallback);
-    return stopped;
-}
-
-struct celix_bundleContext_uninstallBundleCalllback_data {
-    bool threadCreated;
-    const celix_bundle_t *bnd;
-    celix_thread_t uninstallthread; //thread for uninstall
-    celix_thread_mutex_t  mutex; //protects below
-    celix_thread_cond_t cond;
-    bool uninstallCalled;
-    bool uninstalled;
-
-};
-
-static void* celix_bundleContext_uninstallBundleUninstallThread(void *handle) {
-    struct celix_bundleContext_uninstallBundleCalllback_data *data = handle;
-    celix_status_t status = bundle_uninstall((celix_bundle_t*)data->bnd);
-    celixThreadMutex_lock(&data->mutex);
-    data->uninstallCalled = true;
-    data->uninstalled = status == CELIX_SUCCESS;
-    celixThreadCondition_broadcast(&data->cond);
-    celixThreadMutex_unlock(&data->mutex);
-    return NULL;
-}
-
-static void celix_bundleContext_uninstallBundleCallback(void *handle, const celix_bundle_t *bnd) {
-    struct celix_bundleContext_uninstallBundleCalllback_data *data = handle;
-    celix_bundle_state_e bndState = celix_bundle_getState(bnd);
-    if (bndState == OSGI_FRAMEWORK_BUNDLE_ACTIVE) {
-        bundle_stop((celix_bundle_t*)bnd);
-    }
-    bndState = celix_bundle_getState(bnd);
-    if (bndState == OSGI_FRAMEWORK_BUNDLE_RESOLVED || bndState == OSGI_FRAMEWORK_BUNDLE_INSTALLED) {
-        data->bnd = bnd;
-        data->threadCreated = true;
-        celixThread_create(&data->uninstallthread, NULL, celix_bundleContext_uninstallBundleUninstallThread, data);
-    }
+    return celix_framework_stopBundle(ctx->framework, bundleId);
 }
 
 bool celix_bundleContext_uninstallBundle(bundle_context_t *ctx, long bundleId) {
-    bool result = false;
-    struct celix_bundleContext_uninstallBundleCalllback_data data;
-    data.threadCreated = false;
-    data.uninstalled = false;
-    data.uninstallCalled = false;
-    celixThreadMutex_create(&data.mutex, NULL);
-    celixThreadCondition_init(&data.cond, NULL);
-
-    bool called = celix_framework_useBundle(ctx->framework, false, bundleId, &data, celix_bundleContext_uninstallBundleCallback);
-    if (called && data.threadCreated) {
-        celixThreadMutex_lock(&data.mutex);
-        while (!data.uninstallCalled) {
-            celixThreadCondition_wait(&data.cond, &data.mutex);
-        }
-        celixThreadMutex_unlock(&data.mutex);
-        celixThread_join(data.uninstallthread, NULL);
-        celixThreadMutex_lock(&data.mutex);
-        result = data.uninstalled;
-        celixThreadMutex_unlock(&data.mutex);
-    }
-
-    celixThreadMutex_destroy(&data.mutex);
-    celixThreadCondition_destroy(&data.cond);
-    return result;
+    return celix_framework_uninstallBundle(ctx->framework, bundleId);
 }
 
 bool celix_bundleContext_useServiceWithId(
diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c
index eb5b715..5f7233a 100644
--- a/libs/framework/src/framework.c
+++ b/libs/framework/src/framework.c
@@ -129,6 +129,22 @@ static inline celix_framework_bundle_entry_t* fw_bundleEntry_getBundleEntryAndIn
     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;
+    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;
+            fw_bundleEntry_increaseUseCount(entry);
+            celix_arrayList_removeAt(fw->installedBundles.entries, i);
+            break;
+        }
+    }
+    celixThreadMutex_unlock(&fw->installedBundles.mutex);
+    return found;
+}
+
 celix_status_t framework_setBundleStateAndNotify(framework_pt framework, bundle_pt bundle, int state);
 celix_status_t framework_markBundleResolved(framework_pt framework, module_pt module);
 
@@ -1170,55 +1186,43 @@ celix_status_t fw_stopBundle(framework_pt framework, long bndId, bool record) {
 	return status;
 }
 
-celix_status_t fw_uninstallBundle(framework_pt framework, bundle_pt bundle) {
-    celix_status_t status;
-
-    long bndId = celix_bundle_getId(bundle);
-    celix_framework_bundle_entry_t *entry = fw_bundleEntry_getBundleEntryAndIncreaseUseCount(framework, bndId);
+static celix_status_t fw_uninstallBundleEntry(celix_framework_t *framework, celix_framework_bundle_entry_t *entry) {
+    celix_status_t status = CELIX_SUCCESS;
 
-    if (entry != NULL) {
-        status = fw_stopBundle(framework, bndId, true);
-        celixThreadMutex_lock(&framework->installedBundles.mutex);
-        int size = celix_arrayList_size(framework->installedBundles.entries);
-        for (int i = 0; i < size; ++i) {
-            celix_framework_bundle_entry_t *visit = celix_arrayList_get(framework->installedBundles.entries, i);
-            if (visit == entry) {
-                celix_arrayList_removeAt(framework->installedBundles.entries, i);
-                break;
-            }
-        }
-        celixThreadMutex_unlock(&framework->installedBundles.mutex);
-    } else {
-        status = CELIX_ILLEGAL_ARGUMENT;
-    }
+    celix_bundle_t *bnd = NULL;
+    long bndId = -1L;
 
     if (entry != NULL) {
         //NOTE wait outside installedBundles.mutex
+        bnd = entry->bnd;
+        bndId = entry->bndId;
         fw_bundleEntry_decreaseUseCount(entry);
         fw_bundleEntry_destroy(entry, true); //wait till use count is 0 -> e.g. not used
+    } else {
+        status = CELIX_ILLEGAL_ARGUMENT;
     }
 
     if (status == CELIX_SUCCESS) {
         bundle_archive_t *archive = NULL;
         bundle_revision_t *revision = NULL;
         array_list_pt handles = NULL;
-        status = CELIX_DO_IF(status, bundle_getArchive(bundle, &archive));
+        status = CELIX_DO_IF(status, bundle_getArchive(bnd, &archive));
         status = CELIX_DO_IF(status, bundleArchive_setPersistentState(archive, OSGI_FRAMEWORK_BUNDLE_UNINSTALLED)); //set state to uninstalled, so that next framework start will not start bundle.
         status = CELIX_DO_IF(status, bundleArchive_getCurrentRevision(archive, &revision));
         status = CELIX_DO_IF(status, bundleRevision_getHandles(revision, &handles));
         if (handles != NULL) {
-            for (int i = arrayList_size(handles) - 1; i >= 0; i--) {
+            for (int i = celix_arrayList_size(handles) - 1; i >= 0; i--) {
                 celix_library_handle_t *handle = arrayList_get(handles, i);
                 celix_libloader_close(handle);
             }
         }
 
-        status = CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_UNRESOLVED, bundle));
+        status = CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_UNRESOLVED, bnd));
 
-        status = CELIX_DO_IF(status, framework_setBundleStateAndNotify(framework, bundle, OSGI_FRAMEWORK_BUNDLE_UNINSTALLED));
+        status = CELIX_DO_IF(status, framework_setBundleStateAndNotify(framework, bnd, OSGI_FRAMEWORK_BUNDLE_UNINSTALLED));
         status = CELIX_DO_IF(status, bundleArchive_setLastModified(archive, time(NULL)));
 
-        status = CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_UNINSTALLED, bundle));
+        status = CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_UNINSTALLED, bnd));
 
         if (status == CELIX_SUCCESS) {
             celix_status_t refreshStatus = fw_refreshBundle(framework, bndId);
@@ -1226,7 +1230,7 @@ celix_status_t fw_uninstallBundle(framework_pt framework, bundle_pt bundle) {
                 printf("Could not refresh bundle");
             } else {
                 bundleArchive_destroy(archive);
-                status = CELIX_DO_IF(status, bundle_destroy(bundle));
+                status = CELIX_DO_IF(status, bundle_destroy(bnd));
             }
         }
     }
@@ -1246,6 +1250,17 @@ celix_status_t fw_uninstallBundle(framework_pt framework, bundle_pt bundle) {
     return status;
 }
 
+celix_status_t fw_uninstallBundle(framework_pt framework, bundle_pt bundle) {
+    long bndId = celix_bundle_getId(bundle);
+    celix_framework_bundle_entry_t *entry = fw_bundleEntry_removeBundleEntryAndIncreaseUseCount(framework, bndId);
+
+    if (entry != NULL) {
+        return fw_uninstallBundleEntry(framework, entry);
+    } else {
+        return CELIX_ILLEGAL_ARGUMENT;
+    }
+}
+
 //celix_status_t fw_refreshBundles(framework_pt framework, long bundleIds[], int size) {
 //    celix_status_t status = CELIX_SUCCESS;
 //
@@ -2614,4 +2629,93 @@ bundle_pt framework_getBundleById(framework_pt framework, long id) {
         fw_bundleEntry_decreaseUseCount(entry); //NOTE returning bundle without increased use count -> FIXME make all getBundle api private (use bundle id instead)
     }
     return bnd;
+}
+
+
+bool celix_framework_isBundleInstalled(celix_framework_t *fw, long bndId) {
+    bool isInstalled = false;
+    celix_framework_bundle_entry_t *entry = fw_bundleEntry_getBundleEntryAndIncreaseUseCount(fw, bndId);
+    if (entry != NULL) {
+        isInstalled = true;
+        fw_bundleEntry_decreaseUseCount(entry);
+    }
+    return isInstalled;
+}
+
+bool celix_framework_isBundleActive(celix_framework_t *fw, long bndId) {
+    bool isActive = false;
+    celix_framework_bundle_entry_t *entry = fw_bundleEntry_getBundleEntryAndIncreaseUseCount(fw, bndId);
+    if (entry != NULL) {
+        isActive = celix_bundle_getState(entry->bnd) == OSGI_FRAMEWORK_BUNDLE_ACTIVE;
+        fw_bundleEntry_decreaseUseCount(entry);
+    }
+    return isActive;
+}
+
+long celix_framework_installBundle(celix_framework_t *fw, const char *bundleLoc, bool autoStart) {
+    long bundleId = -1;
+    bundle_t *bnd = NULL;
+    celix_status_t status = CELIX_SUCCESS;
+
+    if (fw_installBundle(fw, &bnd, bundleLoc, NULL) == CELIX_SUCCESS) {
+        status = bundle_getBundleId(bnd, &bundleId); //TODO FIXME race condition with fw_installBundle, bundle can be uninstalled (no use count increase)
+        if (status == CELIX_SUCCESS && autoStart) {
+            status = bundle_start(bnd);
+        }
+    }
+
+    framework_logIfError(logger, status, NULL, "Failed to install bundle '%s'", bundleLoc);
+
+    return bundleId;
+}
+
+bool celix_framework_uninstallBundle(celix_framework_t *fw, long bndId) {
+    bool uninstalled = false;
+    celix_framework_bundle_entry_t *entry = fw_bundleEntry_getBundleEntryAndIncreaseUseCount(fw, bndId);
+    if (entry != NULL) {
+        celix_bundle_state_e bndState = celix_bundle_getState(entry->bnd);
+        if (bndState == OSGI_FRAMEWORK_BUNDLE_ACTIVE) {
+            fw_stopBundle(fw, bndId, false);
+        }
+        fw_bundleEntry_decreaseUseCount(entry);
+    }
+
+    entry = fw_bundleEntry_removeBundleEntryAndIncreaseUseCount(fw, bndId);
+    if (entry != NULL) {
+        celix_bundle_state_e bndState = celix_bundle_getState(entry->bnd);
+        if (bndState == OSGI_FRAMEWORK_BUNDLE_RESOLVED || bndState == OSGI_FRAMEWORK_BUNDLE_INSTALLED) {
+            celix_status_t status = fw_uninstallBundleEntry(fw, entry); //also decreases use count
+            uninstalled = status == CELIX_SUCCESS;
+        } else {
+            fw_bundleEntry_decreaseUseCount(entry);
+        }
+    }
+    return uninstalled;
+}
+
+bool celix_framework_stopBundle(celix_framework_t *fw, long bndId) {
+    bool stopped = false;
+    celix_framework_bundle_entry_t *entry = fw_bundleEntry_getBundleEntryAndIncreaseUseCount(fw, bndId);
+    if (entry != NULL) {
+        if (celix_bundle_getState(entry->bnd) == OSGI_FRAMEWORK_BUNDLE_ACTIVE) {
+            celix_status_t rc = bundle_stop(entry->bnd);
+            stopped = rc == CELIX_SUCCESS;
+        }
+        fw_bundleEntry_decreaseUseCount(entry);
+    }
+    return stopped;
+}
+
+bool celix_framework_startBundle(celix_framework_t *fw, long bndId) {
+    bool started = false;
+    celix_framework_bundle_entry_t *entry = fw_bundleEntry_getBundleEntryAndIncreaseUseCount(fw, bndId);
+    if (entry != NULL) {
+        celix_bundle_state_e state = celix_bundle_getState(entry->bnd);
+        if (state == OSGI_FRAMEWORK_BUNDLE_INSTALLED || state == OSGI_FRAMEWORK_BUNDLE_RESOLVED) {
+            celix_status_t rc = bundle_start(entry->bnd);
+            started = rc == CELIX_SUCCESS;
+        }
+        fw_bundleEntry_decreaseUseCount(entry);
+    }
+    return started;
 }
\ No newline at end of file