in libs/framework/src/bundle_context.c [917:1015]
static void celix_bundleContext_stopTrackerInternal(celix_bundle_context_t* ctx, long trackerId, bool async, void *doneData, void (*doneCallback)(void* doneData)) {
if (ctx == NULL || trackerId <= 0) {
return;
}
bool found = false;
bool cancelled = false;
celix_bundle_context_bundle_tracker_entry_t *bundleTracker = NULL;
celix_bundle_context_service_tracker_entry_t *serviceTracker = NULL;
celix_bundle_context_service_tracker_tracker_entry_t *svcTrackerTracker = NULL;
celixThreadRwlock_writeLock(&ctx->lock);
if (celix_longHashMap_hasKey(ctx->bundleTrackers, trackerId)) {
found = true;
bundleTracker = celix_longHashMap_get(ctx->bundleTrackers, trackerId);
(void)celix_longHashMap_remove(ctx->bundleTrackers, trackerId);
if (!bundleTracker->created && !async) {
//note tracker not yet created, so cancel instead of removing
bundleTracker->cancelled = true;
cancelled = true;
}
} else if (celix_longHashMap_hasKey(ctx->serviceTrackers, trackerId)) {
found = true;
serviceTracker = celix_longHashMap_get(ctx->serviceTrackers, trackerId);
(void)celix_longHashMap_remove(ctx->serviceTrackers, trackerId);
if (serviceTracker->tracker == NULL && !async) {
//note tracker not yet created, so cancel instead of removing
serviceTracker->cancelled = true;
cancelled = true;
}
} else if (celix_longHashMap_hasKey(ctx->metaTrackers, trackerId)) {
found = true;
svcTrackerTracker = celix_longHashMap_get(ctx->metaTrackers, trackerId);
(void)celix_longHashMap_remove(ctx->metaTrackers, trackerId);
//note because a meta tracker is a service listener hook under waiter, no additional cancel is needed (svc reg will be cancelled)
}
if (found && cancelled) {
//nop
celixThreadRwlock_unlock(&ctx->lock);
} else if (found && !async && celix_framework_isCurrentThreadTheEventLoop(ctx->framework)) {
//already on the event loop, stop tracker "traditionally" to keep old behavior
celixThreadRwlock_unlock(&ctx->lock); //note calling remove/stops/unregister out side of locks
if (bundleTracker != NULL) {
fw_removeBundleListener(ctx->framework, ctx->bundle, &bundleTracker->listener);
free(bundleTracker);
} else if (serviceTracker != NULL) {
celix_bundleContext_waitForUnusedServiceTracker(ctx, serviceTracker);
celix_serviceTracker_destroy(serviceTracker->tracker);
if (serviceTracker->isFreeFilterNeeded) {
free((char*)serviceTracker->opts.filter.serviceName);
free((char*)serviceTracker->opts.filter.versionRange);
free((char*)serviceTracker->opts.filter.filter);
}
free(serviceTracker);
} else if (svcTrackerTracker != NULL) {
celix_framework_unregister(ctx->framework, ctx->bundle, svcTrackerTracker->serviceId);
free(svcTrackerTracker->serviceName);
free(svcTrackerTracker);
}
if (doneCallback != NULL) {
doneCallback(doneData);
}
} else if (found && async) {
//NOTE: for async stopping of tracking we need to ensure we cant wait for the tracker destroy id event.
long eventId = celix_framework_nextEventId(ctx->framework);
celix_longHashMap_put(ctx->stoppingTrackerEventIds, trackerId, (void*)eventId);
if (bundleTracker != NULL) {
celix_framework_fireGenericEvent(ctx->framework, eventId, celix_bundle_getId(ctx->bundle), "stop tracker", bundleTracker, celix_bundleContext_removeBundleTracker, doneData, doneCallback);
} else if (serviceTracker != NULL) {
celix_framework_fireGenericEvent(ctx->framework, eventId, celix_bundle_getId(ctx->bundle), "stop tracker", serviceTracker, celix_bundleContext_removeServiceTracker, doneData, doneCallback);
} else if (svcTrackerTracker != NULL) {
celix_framework_fireGenericEvent(ctx->framework, eventId, celix_bundle_getId(ctx->bundle), "stop meta tracker", svcTrackerTracker, celix_bundleContext_removeServiceTrackerTracker, doneData, doneCallback);
} else {
fw_log(ctx->framework->logger, CELIX_LOG_LEVEL_ERROR, "Unexpected else branch");
}
celixThreadRwlock_unlock(&ctx->lock);
} else if (found) { /*sync, so waiting for events*/
long eventId = -1L;
if (bundleTracker != NULL) {
eventId = celix_framework_fireGenericEvent(ctx->framework, -1L, celix_bundle_getId(ctx->bundle), "stop tracker", bundleTracker, celix_bundleContext_removeBundleTracker, doneData, doneCallback);
} else if (serviceTracker != NULL) {
eventId = celix_framework_fireGenericEvent(ctx->framework, -1L, celix_bundle_getId(ctx->bundle), "stop tracker", serviceTracker, celix_bundleContext_removeServiceTracker, doneData, doneCallback);
} else if (svcTrackerTracker != NULL) {
eventId = celix_framework_fireGenericEvent(ctx->framework, -1L, celix_bundle_getId(ctx->bundle), "stop meta tracker", svcTrackerTracker, celix_bundleContext_removeServiceTrackerTracker, doneData, doneCallback);
} else {
fw_log(ctx->framework->logger, CELIX_LOG_LEVEL_ERROR, "Unexpected else branch");
}
celixThreadRwlock_unlock(&ctx->lock);
celix_framework_waitForGenericEvent(ctx->framework, eventId);
} else {
celixThreadRwlock_unlock(&ctx->lock);
fw_log(ctx->framework->logger, CELIX_LOG_LEVEL_ERROR, "No tracker with id %li found'", trackerId);
}
}