27 #include <unordered_map>
31 #include "celix_utils.h"
32 #include "celix/Properties.h"
33 #include "celix/Utils.h"
36 #include "celix/Filter.h"
75 cCtx{std::move(_cCtx)} {}
83 std::lock_guard<std::mutex> lck{
mutex};
91 std::lock_guard<std::mutex> lck{
mutex};
102 long localTrkId = -1;
104 std::lock_guard<std::mutex> lck{
mutex};
112 if (localTrkId >= 0) {
115 std::lock_guard<std::mutex> lck{
mutex};
129 virtual void open() = 0;
137 bool needWaitOpening =
false;
138 bool needWaitClosing =
false;
141 std::lock_guard<std::mutex> lck{
mutex};
144 needWaitOpening =
true;
146 needWaitClosing =
true;
149 if (needWaitOpening) {
152 if (needWaitClosing) {
169 return [](T *tracker) {
189 "celix::AbstractTracker delete callback",
201 const std::shared_ptr<celix_bundle_context_t>
cCtx;
220 std::string_view _svcVersionRange, celix::Filter _filter) :
AbstractTracker{std::move(_cCtx)},
svcName{_svcName},
222 opts.trackerCreatedCallbackData =
this;
226 std::lock_guard<std::mutex> callbackLock{trk->mutex};
238 std::lock_guard<std::mutex> lck{
mutex};
309 static std::shared_ptr<ServiceTracker<I>>
create(
310 std::shared_ptr<celix_bundle_context_t>
cCtx,
314 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>>
setCallbacks,
315 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>>
addCallbacks,
316 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>>
remCallbacks) {
318 auto tracker = std::shared_ptr<ServiceTracker<I>>{
327 AbstractTracker::delCallback<ServiceTracker<I>>()};
342 std::shared_ptr<I> result{};
343 std::lock_guard<std::mutex> lck{
mutex};
361 std::vector<std::shared_ptr<I>> result{};
362 std::lock_guard<std::mutex> lck{
mutex};
363 result.reserve(
entries.size());
365 result.push_back(e->svc);
371 SvcEntry(
long _svcId,
long _svcRanking, std::shared_ptr<I> _svc,
372 std::shared_ptr<const celix::Properties> _properties,
373 std::shared_ptr<const celix::Bundle> _owner) :
svcId(_svcId),
svcRanking(_svcRanking),
374 svc(std::move(_svc)),
376 owner(std::move(_owner)) {}
381 std::shared_ptr<const celix::Bundle>
owner;
384 ServiceTracker(std::shared_ptr<celix_bundle_context_t> _cCtx, std::string_view _svcName,
385 std::string_view _svcVersionRange, celix::Filter _filter,
386 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>> _setCallbacks,
387 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>> _addCallbacks,
388 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>> _remCallbacks) :
396 opts.callbackHandle =
this;
397 opts.
addWithOwner = [](
void *handle,
void *voidSvc,
const celix_properties_t* cProps,
const celix_bundle_t* cBnd) {
398 auto tracker =
static_cast<ServiceTracker<I>*
>(handle);
401 std::lock_guard<std::mutex> lck{tracker->mutex};
402 tracker->entries.insert(entry);
403 tracker->cachedEntries[entry->svcId] = entry;
405 tracker->svcCount.fetch_add(1, std::memory_order_relaxed);
406 for (
const auto& cb : tracker->addCallbacks) {
407 cb(entry->svc, entry->properties, entry->owner);
409 tracker->invokeUpdateCallbacks();
411 opts.
removeWithOwner = [](
void *handle,
void*,
const celix_properties_t* cProps,
const celix_bundle_t*) {
412 auto tracker =
static_cast<ServiceTracker<I>*
>(handle);
413 long svcId = celix_properties_getAsLong(cProps, OSGI_FRAMEWORK_SERVICE_ID, -1L);
414 std::shared_ptr<SvcEntry> entry{};
416 std::lock_guard<std::mutex> lck{tracker->mutex};
417 auto it = tracker->cachedEntries.find(svcId);
418 assert(it != tracker->cachedEntries.end());
420 tracker->cachedEntries.erase(it);
421 tracker->entries.erase(entry);
423 for (
const auto& cb : tracker->remCallbacks) {
424 cb(entry->svc, entry->properties, entry->owner);
426 tracker->invokeUpdateCallbacks();
427 tracker->svcCount.fetch_sub(1, std::memory_order_relaxed);
428 tracker->waitForExpiredSvcEntry(entry);
430 opts.
setWithOwner = [](
void *handle,
void *voidSvc,
const celix_properties_t *cProps,
const celix_bundle_t *cBnd) {
431 auto tracker =
static_cast<ServiceTracker<I>*
>(handle);
432 std::lock_guard<std::mutex> lck{tracker->mutex};
433 auto prevEntry = tracker->highestRankingServiceEntry;
435 tracker->highestRankingServiceEntry =
createEntry(voidSvc, cProps, cBnd);
437 tracker->highestRankingServiceEntry =
nullptr;
439 for (
const auto& cb : tracker->setCallbacks) {
440 if (tracker->highestRankingServiceEntry) {
441 auto& e = tracker->highestRankingServiceEntry;
442 cb(e->svc, e->properties, e->owner);
444 cb(
nullptr,
nullptr,
nullptr);
447 tracker->waitForExpiredSvcEntry(prevEntry);
451 static std::shared_ptr<SvcEntry>
createEntry(
void* voidSvc,
const celix_properties_t* cProps,
const celix_bundle_t* cBnd) {
452 long svcId = celix_properties_getAsLong(cProps, OSGI_FRAMEWORK_SERVICE_ID, -1L);
453 long svcRanking = celix_properties_getAsLong(cProps, OSGI_FRAMEWORK_SERVICE_RANKING, 0);
454 auto svc = std::shared_ptr<I>{
static_cast<I*
>(voidSvc), [](I*){}};
455 auto props = celix::Properties::wrap(cProps);
456 auto owner = std::make_shared<celix::Bundle>(
const_cast<celix_bundle_t*
>(cBnd));
457 return std::make_shared<SvcEntry>(svcId, svcRanking, svc, props, owner);
462 std::weak_ptr<void> svcObserve = entry->svc;
463 std::weak_ptr<const celix::Properties> propsObserve = entry->properties;
464 std::weak_ptr<const celix::Bundle> ownerObserve = entry->owner;
465 entry->svc =
nullptr;
466 entry->properties =
nullptr;
467 entry->owner =
nullptr;
470 waitForExpired(ownerObserve, entry->svcId,
"service bundle (owner)");
476 auto start = std::chrono::system_clock::now();
477 while (!observe.expired()) {
478 auto now = std::chrono::system_clock::now();
479 auto durationInMilli = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);
481 celix_bundleContext_log(
cCtx.get(), CELIX_LOG_LEVEL_WARNING,
"Cannot remove %s associated with service.id %li, because it is still in use. Current shared_ptr use count is %i\n", objName, svcId, (
int)observe.use_count());
484 std::this_thread::sleep_for(std::chrono::milliseconds{50});
490 std::vector<std::shared_ptr<I>> updateVector{};
492 std::lock_guard<std::mutex> lck{
mutex};
493 updateVector.reserve(
entries.size());
494 for (
const auto &entry :
entries) {
495 updateVector.push_back(entry->svc);
503 std::vector<std::pair<std::shared_ptr<I>, std::shared_ptr<const celix::Properties>>> updateVector{};
504 updateVector.reserve(
entries.size());
506 std::lock_guard<std::mutex> lck{
mutex};
507 for (
const auto &entry :
entries) {
508 updateVector.emplace_back(entry->svc, entry->properties);
516 std::vector<std::tuple<std::shared_ptr<I>, std::shared_ptr<const celix::Properties>, std::shared_ptr<const celix::Bundle>>> updateVector{};
517 updateVector.reserve(
entries.size());
519 std::lock_guard<std::mutex> lck{
mutex};
520 for (
const auto &entry :
entries) {
521 updateVector.emplace_back(entry->svc, entry->properties, entry->owner);
532 const std::vector<std::function<void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>>
setCallbacks;
533 const std::vector<std::function<void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>>
addCallbacks;
534 const std::vector<std::function<void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>>
remCallbacks;
537 const std::vector<std::function<void(
const std::vector<std::shared_ptr<I>>)>>
updateCallbacks{};
538 const std::vector<std::function<void(
const std::vector<std::pair<std::shared_ptr<I>, std::shared_ptr<const celix::Properties>>>)>>
updateWithPropertiesCallbacks{};
539 const std::vector<std::function<void(
const std::vector<std::tuple<std::shared_ptr<I>, std::shared_ptr<const celix::Properties>, std::shared_ptr<const celix::Bundle>>>)>>
updateWithOwnerCallbacks{};
542 bool operator() (
const std::shared_ptr<SvcEntry>& a,
const std::shared_ptr<SvcEntry>& b)
const {
543 int cmp = celix_utils_compareServiceIdsAndRanking(a->svcId, a->svcRanking, b->svcId, b->svcRanking);
571 static std::shared_ptr<BundleTracker>
create(
572 std::shared_ptr<celix_bundle_context_t>
cCtx,
573 bool includeFrameworkBundle,
574 std::vector<std::function<
void(
const celix::Bundle&)>> onInstallCallbacks,
575 std::vector<std::function<
void(
const celix::Bundle&)>> onStartCallbacks,
576 std::vector<std::function<
void(
const celix::Bundle&)>> onStopCallbacks) {
578 auto tracker = std::shared_ptr<BundleTracker>{
581 includeFrameworkBundle,
582 std::move(onInstallCallbacks),
583 std::move(onStartCallbacks),
584 std::move(onStopCallbacks)},
585 AbstractTracker::delCallback<BundleTracker>()};
594 std::lock_guard<std::mutex> lck{
mutex};
606 std::shared_ptr<celix_bundle_context_t> _cCtx,
607 bool _includeFrameworkBundle,
608 std::vector<std::function<
void(
const celix::Bundle&)>> _onInstallCallbacks,
609 std::vector<std::function<
void(
const celix::Bundle&)>> _onStartCallbacks,
610 std::vector<std::function<
void(
const celix::Bundle&)>> _onStopCallbacks) :
612 includeFrameworkBundle{_includeFrameworkBundle},
613 onInstallCallbacks{std::move(_onInstallCallbacks)},
614 onStartCallbacks{std::move(_onStartCallbacks)},
615 onStopCallbacks{std::move(_onStopCallbacks)} {
618 opts.includeFrameworkBundle = includeFrameworkBundle;
619 opts.callbackHandle =
this;
620 opts.
onInstalled = [](
void *handle,
const celix_bundle_t *cBnd) {
621 auto tracker =
static_cast<BundleTracker *
>(handle);
623 for (
const auto& cb : tracker->onInstallCallbacks) {
627 opts.
onStarted = [](
void *handle,
const celix_bundle_t *cBnd) {
628 auto tracker =
static_cast<BundleTracker *
>(handle);
630 for (
const auto& cb : tracker->onStartCallbacks) {
634 opts.
onStopped = [](
void *handle,
const celix_bundle_t *cBnd) {
635 auto tracker =
static_cast<BundleTracker *
>(handle);
637 for (
const auto& cb : tracker->onStopCallbacks) {
641 opts.trackerCreatedCallbackData =
this;
643 auto* trk =
static_cast<BundleTracker*
>(data);
644 std::lock_guard<std::mutex> callbackLock{trk->mutex};
649 const bool includeFrameworkBundle;
650 const std::vector<std::function<void(
const celix::Bundle&)>> onInstallCallbacks;
651 const std::vector<std::function<void(
const celix::Bundle&)>> onStartCallbacks;
652 const std::vector<std::function<void(
const celix::Bundle&)>> onStopCallbacks;
697 static std::shared_ptr<MetaTracker>
create(
698 std::shared_ptr<celix_bundle_context_t>
cCtx,
699 std::string_view serviceName,
703 auto tracker = std::shared_ptr<MetaTracker>{
707 std::move(onTrackerCreated),
708 std::move(onTrackerDestroyed)},
709 AbstractTracker::delCallback<MetaTracker>()};
718 std::lock_guard<std::mutex> lck{
mutex};
725 serviceName.empty() ?
nullptr : serviceName.c_str(),
726 static_cast<void*
>(
this),
728 auto *trk = static_cast<MetaTracker *>(handle);
729 std::string svcName = cInfo->serviceName == nullptr ?
"" : cInfo->serviceName;
730 ServiceTrackerInfo info{svcName, celix::Filter::wrap(cInfo->filter), cInfo->bundleId};
731 for (
const auto& cb : trk->onTrackerCreated) {
737 std::string svcName = cInfo->serviceName ==
nullptr ?
"" : cInfo->serviceName;
738 ServiceTrackerInfo info{svcName, celix::Filter::wrap(cInfo->filter), cInfo->bundleId};
739 for (
const auto& cb : trk->onTrackerDestroyed) {
743 static_cast<void*
>(
this),
746 std::lock_guard<std::mutex> callbackLock{trk->
mutex};
757 std::shared_ptr<celix_bundle_context_t> _cCtx,
758 std::string_view _serviceName,
759 std::vector<std::function<
void(
const ServiceTrackerInfo&)>> _onTrackerCreated,
760 std::vector<std::function<
void(
const ServiceTrackerInfo&)>> _onTrackerDestroyed) :
761 AbstractTracker{std::move(_cCtx)},
762 serviceName{_serviceName},
763 onTrackerCreated{std::move(_onTrackerCreated)},
764 onTrackerDestroyed{std::move(_onTrackerDestroyed)} {}
766 const std::string serviceName;
767 const std::vector<std::function<void(
const ServiceTrackerInfo&)>> onTrackerCreated;
768 const std::vector<std::function<void(
const ServiceTrackerInfo&)>> onTrackerDestroyed;