Apache Celix  2.4.0
Apache Celix is a framework for C, C++14 and C++17 to develop dynamic modular software applications using component and in-process service-oriented programming.
Trackers.h
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #pragma once
21 
22 #include <memory>
23 #include <mutex>
24 #include <atomic>
25 #include <cassert>
26 #include <set>
27 #include <unordered_map>
28 #include <functional>
29 #include <thread>
30 
31 #include "celix_utils.h"
32 #include "celix_bundle_context.h"
33 #include "celix_framework.h"
35 #include "celix/Properties.h"
36 #include "celix/Utils.h"
37 #include "celix/Bundle.h"
38 #include "celix/Constants.h"
39 #include "celix/Filter.h"
40 
41 namespace celix {
42 
43 
47  enum class TrackerState : std::uint8_t {
48  OPENING,
49  OPEN,
50  CLOSING,
51  CLOSED
52  };
53 
73  public:
74  explicit AbstractTracker(std::shared_ptr<celix_bundle_context_t> _cCtx) :
75  cCtx{std::move(_cCtx)} {}
76 
77  virtual ~AbstractTracker() noexcept = default;
78 
82  bool isOpen() const {
83  std::lock_guard<std::mutex> lck{mutex};
84  return state == TrackerState::OPEN;
85  }
86 
91  std::lock_guard<std::mutex> lck{mutex};
92  return state;
93  }
94 
101  void close() {
102  long localTrkId = -1;
103  {
104  std::lock_guard<std::mutex> lck{mutex};
106  //not yet closed
108  localTrkId = trkId;
109  trkId = -1;
110  }
111  }
112  if (localTrkId >= 0) {
113  celix_bundleContext_stopTracker(cCtx.get(), localTrkId);
114  {
115  std::lock_guard<std::mutex> lck{mutex};
117  }
118  }
119  }
120 
129  virtual void open() = 0;
130 
136  void wait() const {
137  bool needWaitOpening = false;
138  bool needWaitClosing = false;
139  long localId;
140  {
141  std::lock_guard<std::mutex> lck{mutex};
142  localId = trkId;
143  if (state == TrackerState::OPENING) {
144  needWaitOpening = true;
145  } else if (state == TrackerState::CLOSING) {
146  needWaitClosing = true;
147  }
148  }
149  if (needWaitOpening) {
151  }
152  if (needWaitClosing) {
154  }
155  }
156  protected:
160  void waitIfAble() const {
161  auto* fw = celix_bundleContext_getFramework(cCtx.get());
163  wait();
164  }
165  }
166 
167  template<typename T>
168  static std::function<void(T*)> delCallback() {
169  return [](T *tracker) {
170  if (tracker->getState() == TrackerState::CLOSED) {
171  delete tracker;
172  } else {
173  /*
174  * if open/opening -> close() -> new event on the Celix event thread
175  * if closing -> nop close() -> there is already a event on the Celix event thread to close
176  */
177  tracker->close();
178 
179  /*
180  * Creating event on the Event loop, this will be after the close is done
181  */
182  auto *fw = celix_bundleContext_getFramework(tracker->cCtx.get());
183  auto *bnd = celix_bundleContext_getBundle(tracker->cCtx.get());
184  long bndId = celix_bundle_getId(bnd);
186  fw,
187  -1,
188  bndId,
189  "celix::AbstractTracker delete callback",
190  tracker,
191  [](void *data) {
192  auto *t = static_cast<AbstractTracker *>(data);
193  delete t;
194  },
195  nullptr,
196  nullptr);
197  }
198  };
199  }
200 
201  const std::shared_ptr<celix_bundle_context_t> cCtx;
202 
203  mutable std::mutex mutex{}; //protects below
204  long trkId{-1L};
206  };
207 
218  public:
219 #if __cplusplus >= 201703L //C++17 or higher
220  GenericServiceTracker(std::shared_ptr<celix_bundle_context_t> _cCtx, std::string_view _svcName,
221  std::string_view _svcVersionRange, celix::Filter _filter) : AbstractTracker{std::move(_cCtx)}, svcName{_svcName},
222  svcVersionRange{_svcVersionRange}, filter{std::move(_filter)} {
223  setupServiceTrackerOptions();
224  }
225 #else
226  GenericServiceTracker(std::shared_ptr<celix_bundle_context_t> _cCtx, std::string _svcName,
227  std::string _svcVersionRange, celix::Filter _filter) : AbstractTracker{std::move(_cCtx)}, svcName{std::move(_svcName)},
228  svcVersionRange{std::move(_svcVersionRange)}, filter{std::move(_filter)} {
229  setupServiceTrackerOptions();
230  }
231 #endif
232 
233  ~GenericServiceTracker() override = default;
234 
238  void open() override {
239  std::lock_guard<std::mutex> lck{mutex};
242 
243  //NOTE assuming the opts already configured the callbacks
245  if (trkId < 0) {
246  throw celix::TrackerException{"Cannot open service tracker"};
247  }
248  }
249  }
250 
254  const std::string& getServiceName() const { return svcName; }
255 
259  const std::string& getServiceRange() const { return svcVersionRange; }
260 
267  const celix::Filter& getFilter() const { return filter; }
268 
272  std::size_t getServiceCount() const {
273  return svcCount;
274  }
275  protected:
276  const std::string svcName;
277  const std::string svcVersionRange;
278  const celix::Filter filter;
279  celix_service_tracking_options opts{}; //note only set in the ctor
280  std::atomic<size_t> svcCount{0};
281 
282  private:
283  void setupServiceTrackerOptions() {
284  opts.trackerCreatedCallbackData = this;
285  opts.trackerCreatedCallback = [](void *data) {
286  auto* trk = static_cast<GenericServiceTracker*>(data);
287  {
288  std::lock_guard<std::mutex> callbackLock{trk->mutex};
289  trk->state = TrackerState::OPEN;
290  }
291  };
292  }
293  };
294 
307  template<typename I>
309  public:
322 #if __cplusplus >= 201703L //C++17 or higher
323  static std::shared_ptr<ServiceTracker<I>> create(
324  std::shared_ptr<celix_bundle_context_t> cCtx,
325  std::string_view svcName,
326  std::string_view svcVersionRange,
327  celix::Filter filter,
328  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,
329  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,
330  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) {
331  auto tracker = std::shared_ptr<ServiceTracker<I>>{
332  new ServiceTracker<I>{
333  std::move(cCtx),
334  svcName,
336  std::move(filter),
337  std::move(setCallbacks),
338  std::move(addCallbacks),
339  std::move(remCallbacks)},
340  AbstractTracker::delCallback<ServiceTracker<I>>()};
341  tracker->open();
342  return tracker;
343  }
344 #else
345  static std::shared_ptr<ServiceTracker<I>> create(
346  std::shared_ptr<celix_bundle_context_t> cCtx,
347  std::string svcName,
348  std::string svcVersionRange,
349  celix::Filter filter,
350  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,
351  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,
352  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) {
353  auto tracker = std::shared_ptr<ServiceTracker<I>>{
354  new ServiceTracker<I>{
355  std::move(cCtx),
356  std::move(svcName),
357  std::move(svcVersionRange),
358  std::move(filter),
359  std::move(setCallbacks),
360  std::move(addCallbacks),
361  std::move(remCallbacks)},
362  AbstractTracker::delCallback<ServiceTracker<I>>()};
363  tracker->open();
364  return tracker;
365  }
366 #endif
367 
376  std::shared_ptr<I> getHighestRankingService() {
377  waitIfAble();
378  std::shared_ptr<I> result{};
379  std::lock_guard<std::mutex> lck{mutex};
380  auto it = entries.begin();
381  if (it != entries.end()) {
382  result = (*it)->svc;
383  }
384  return result;
385  }
386 
395  std::vector<std::shared_ptr<I>> getServices() {
396  waitIfAble();
397  std::vector<std::shared_ptr<I>> result{};
398  std::lock_guard<std::mutex> lck{mutex};
399  result.reserve(entries.size());
400  for (auto& e : entries) {
401  result.push_back(e->svc);
402  }
403  return result;
404  }
405  protected:
406  struct SvcEntry {
407  SvcEntry(long _svcId, long _svcRanking, std::shared_ptr<I> _svc,
408  std::shared_ptr<const celix::Properties> _properties,
409  std::shared_ptr<const celix::Bundle> _owner) : svcId(_svcId), svcRanking(_svcRanking),
410  svc(std::move(_svc)),
411  properties(std::move(_properties)),
412  owner(std::move(_owner)) {}
413  long svcId;
415  std::shared_ptr<I> svc;
416  std::shared_ptr<const celix::Properties> properties;
417  std::shared_ptr<const celix::Bundle> owner;
418  };
419 
420 #if __cplusplus >= 201703L //C++17 or higher
421  ServiceTracker(std::shared_ptr<celix_bundle_context_t> _cCtx, std::string_view _svcName,
422  std::string_view _svcVersionRange, celix::Filter _filter,
423  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,
424  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,
425  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) :
426  GenericServiceTracker{std::move(_cCtx), _svcName, _svcVersionRange, std::move(_filter)},
427  setCallbacks{std::move(_setCallbacks)},
428  addCallbacks{std::move(_addCallbacks)},
429  remCallbacks{std::move(_remCallbacks)} {
430  setupServiceTrackerOptions();
431  }
432 #else
433  ServiceTracker(std::shared_ptr<celix_bundle_context_t> _cCtx, std::string _svcName,
434  std::string _svcVersionRange, celix::Filter _filter,
435  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,
436  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,
437  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) :
438  GenericServiceTracker{std::move(_cCtx), std::move(_svcName), std::move(_svcVersionRange), std::move(_filter)},
439  setCallbacks{std::move(_setCallbacks)},
440  addCallbacks{std::move(_addCallbacks)},
441  remCallbacks{std::move(_remCallbacks)} {
442  setupServiceTrackerOptions();
443  }
444 #endif
445 
446  static std::shared_ptr<SvcEntry> createEntry(void* voidSvc, const celix_properties_t* cProps, const celix_bundle_t* cBnd) {
447  long svcId = celix_properties_getAsLong(cProps, OSGI_FRAMEWORK_SERVICE_ID, -1L);
448  long svcRanking = celix_properties_getAsLong(cProps, OSGI_FRAMEWORK_SERVICE_RANKING, 0);
449  auto svc = std::shared_ptr<I>{static_cast<I*>(voidSvc), [](I*){/*nop*/}};
450  auto props = celix::Properties::wrap(cProps);
451  auto owner = std::make_shared<celix::Bundle>(const_cast<celix_bundle_t*>(cBnd));
452  return std::make_shared<SvcEntry>(svcId, svcRanking, svc, props, owner);
453  }
454 
455  void waitForExpiredSvcEntry(std::shared_ptr<SvcEntry>& entry) {
456  if (entry) {
457  std::weak_ptr<void> svcObserve = entry->svc;
458  std::weak_ptr<const celix::Properties> propsObserve = entry->properties;
459  std::weak_ptr<const celix::Bundle> ownerObserve = entry->owner;
460  entry->svc = nullptr;
461  entry->properties = nullptr;
462  entry->owner = nullptr;
463  waitForExpired(svcObserve, entry->svcId, "service");
464  waitForExpired(propsObserve, entry->svcId, "service properties");
465  waitForExpired(ownerObserve, entry->svcId, "service bundle (owner)");
466  }
467  }
468 
469  template<typename U>
470  void waitForExpired(std::weak_ptr<U> observe, long svcId, const char* objName) {
471  auto start = std::chrono::system_clock::now();
472  while (!observe.expired()) {
473  auto now = std::chrono::system_clock::now();
474  auto durationInMilli = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);
475  if (durationInMilli > warningTimoutForNonExpiredSvcObject) {
476  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());
477  start = now;
478  }
479  std::this_thread::sleep_for(std::chrono::milliseconds{50});
480  }
481  }
482 
484  if (!updateCallbacks.empty()) {
485  std::vector<std::shared_ptr<I>> updateVector{};
486  {
487  std::lock_guard<std::mutex> lck{mutex};
488  updateVector.reserve(entries.size());
489  for (const auto &entry : entries) {
490  updateVector.push_back(entry->svc);
491  }
492  }
493  for (const auto& cb : updateCallbacks) {
494  cb(updateVector);
495  }
496  }
497  if (!updateWithPropertiesCallbacks.empty()) {
498  std::vector<std::pair<std::shared_ptr<I>, std::shared_ptr<const celix::Properties>>> updateVector{};
499  updateVector.reserve(entries.size());
500  {
501  std::lock_guard<std::mutex> lck{mutex};
502  for (const auto &entry : entries) {
503  updateVector.emplace_back(entry->svc, entry->properties);
504  }
505  }
506  for (const auto& cb : updateWithPropertiesCallbacks) {
507  cb(updateVector);
508  }
509  }
510  if (!updateWithOwnerCallbacks.empty()) {
511  std::vector<std::tuple<std::shared_ptr<I>, std::shared_ptr<const celix::Properties>, std::shared_ptr<const celix::Bundle>>> updateVector{};
512  updateVector.reserve(entries.size());
513  {
514  std::lock_guard<std::mutex> lck{mutex};
515  for (const auto &entry : entries) {
516  updateVector.emplace_back(entry->svc, entry->properties, entry->owner);
517  }
518  }
519  for (const auto& cb : updateWithOwnerCallbacks) {
520  cb(updateVector);
521  }
522  }
523  }
524 
525  const std::chrono::milliseconds warningTimoutForNonExpiredSvcObject{1000};
526 
527  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;
528  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;
529  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;
530 
531  //NOTE update callbacks cannot yet be configured
532  const std::vector<std::function<void(const std::vector<std::shared_ptr<I>>)>> updateCallbacks{};
533  const std::vector<std::function<void(const std::vector<std::pair<std::shared_ptr<I>, std::shared_ptr<const celix::Properties>>>)>> updateWithPropertiesCallbacks{};
534  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{};
535 
537  bool operator() (const std::shared_ptr<SvcEntry>& a, const std::shared_ptr<SvcEntry>& b) const {
538  int cmp = celix_utils_compareServiceIdsAndRanking(a->svcId, a->svcRanking, b->svcId, b->svcRanking);
539  return cmp < 0;
540  }
541  };
542 
543  mutable std::mutex mutex{}; //protect below
544  std::set<std::shared_ptr<SvcEntry>, SvcEntryCompare> entries{};
545  std::unordered_map<long, std::shared_ptr<SvcEntry>> cachedEntries{};
546  std::shared_ptr<SvcEntry> highestRankingServiceEntry{};
547 
548  private:
549  void setupServiceTrackerOptions() {
550  opts.filter.serviceName = svcName.empty() ? nullptr : svcName.c_str();
551  opts.filter.versionRange = svcVersionRange.empty() ? nullptr : svcVersionRange.c_str();
552  opts.filter.filter = filter.empty() ? nullptr : filter.getFilterCString();
553  opts.callbackHandle = this;
554  opts.addWithOwner = [](void *handle, void *voidSvc, const celix_properties_t* cProps, const celix_bundle_t* cBnd) {
555  auto tracker = static_cast<ServiceTracker<I>*>(handle);
556  auto entry = createEntry(voidSvc, cProps, cBnd);
557  {
558  std::lock_guard<std::mutex> lck{tracker->mutex};
559  tracker->entries.insert(entry);
560  tracker->cachedEntries[entry->svcId] = entry;
561  }
562  tracker->svcCount.fetch_add(1, std::memory_order_relaxed);
563  for (const auto& cb : tracker->addCallbacks) {
564  cb(entry->svc, entry->properties, entry->owner);
565  }
566  tracker->invokeUpdateCallbacks();
567  };
568  opts.removeWithOwner = [](void *handle, void*, const celix_properties_t* cProps, const celix_bundle_t*) {
569  auto tracker = static_cast<ServiceTracker<I>*>(handle);
570  long svcId = celix_properties_getAsLong(cProps, OSGI_FRAMEWORK_SERVICE_ID, -1L);
571  std::shared_ptr<SvcEntry> entry{};
572  {
573  std::lock_guard<std::mutex> lck{tracker->mutex};
574  auto it = tracker->cachedEntries.find(svcId);
575  assert(it != tracker->cachedEntries.end()); //should not happen, added during add callback
576  entry = it->second;
577  tracker->cachedEntries.erase(it);
578  tracker->entries.erase(entry);
579  }
580  for (const auto& cb : tracker->remCallbacks) {
581  cb(entry->svc, entry->properties, entry->owner);
582  }
583  tracker->invokeUpdateCallbacks();
584  tracker->svcCount.fetch_sub(1, std::memory_order_relaxed);
585  tracker->waitForExpiredSvcEntry(entry);
586  };
587  opts.setWithOwner = [](void *handle, void *voidSvc, const celix_properties_t *cProps, const celix_bundle_t *cBnd) {
588  auto tracker = static_cast<ServiceTracker<I>*>(handle);
589  std::unique_lock<std::mutex> lck{tracker->mutex};
590  auto prevEntry = tracker->highestRankingServiceEntry;
591  if (voidSvc) {
592  tracker->highestRankingServiceEntry = createEntry(voidSvc, cProps, cBnd);
593  } else {
594  tracker->highestRankingServiceEntry = nullptr;
595  }
596  for (const auto& cb : tracker->setCallbacks) {
597  if (tracker->highestRankingServiceEntry) {
598  auto& e = tracker->highestRankingServiceEntry;
599  cb(e->svc, e->properties, e->owner);
600  } else /*"unset"*/ {
601  cb(nullptr, nullptr, nullptr);
602  }
603  }
604  lck.unlock();
605  tracker->waitForExpiredSvcEntry(prevEntry);
606  };
607  }
608  };
609 
615  public:
627  static std::shared_ptr<BundleTracker> create(
628  std::shared_ptr<celix_bundle_context_t> cCtx,
629  bool includeFrameworkBundle,
630  std::vector<std::function<void(const celix::Bundle&)>> onInstallCallbacks,
631  std::vector<std::function<void(const celix::Bundle&)>> onStartCallbacks,
632  std::vector<std::function<void(const celix::Bundle&)>> onStopCallbacks) {
633 
634  auto tracker = std::shared_ptr<BundleTracker>{
635  new BundleTracker{
636  std::move(cCtx),
637  includeFrameworkBundle,
638  std::move(onInstallCallbacks),
639  std::move(onStartCallbacks),
640  std::move(onStopCallbacks)},
641  AbstractTracker::delCallback<BundleTracker>()};
642  tracker->open();
643  return tracker;
644  }
645 
649  void open() override {
650  std::lock_guard<std::mutex> lck{mutex};
653  //NOTE the opts already configured the callbacks
655  if (trkId < 0) {
656  throw celix::TrackerException{"Cannot open bundle tracker"};
657  }
658  }
659  }
660  private:
662  std::shared_ptr<celix_bundle_context_t> _cCtx,
663  bool _includeFrameworkBundle,
664  std::vector<std::function<void(const celix::Bundle&)>> _onInstallCallbacks,
665  std::vector<std::function<void(const celix::Bundle&)>> _onStartCallbacks,
666  std::vector<std::function<void(const celix::Bundle&)>> _onStopCallbacks) :
667  AbstractTracker{std::move(_cCtx)},
668  includeFrameworkBundle{_includeFrameworkBundle},
669  onInstallCallbacks{std::move(_onInstallCallbacks)},
670  onStartCallbacks{std::move(_onStartCallbacks)},
671  onStopCallbacks{std::move(_onStopCallbacks)} {
672 
673 
674  opts.includeFrameworkBundle = includeFrameworkBundle;
675  opts.callbackHandle = this;
676  opts.onInstalled = [](void *handle, const celix_bundle_t *cBnd) {
677  auto tracker = static_cast<BundleTracker *>(handle);
678  celix::Bundle bnd{const_cast<celix_bundle_t *>(cBnd)};
679  for (const auto& cb : tracker->onInstallCallbacks) {
680  cb(bnd);
681  }
682  };
683  opts.onStarted = [](void *handle, const celix_bundle_t *cBnd) {
684  auto tracker = static_cast<BundleTracker *>(handle);
685  celix::Bundle bnd{const_cast<celix_bundle_t *>(cBnd)};
686  for (const auto& cb : tracker->onStartCallbacks) {
687  cb(bnd);
688  }
689  };
690  opts.onStopped = [](void *handle, const celix_bundle_t *cBnd) {
691  auto tracker = static_cast<BundleTracker *>(handle);
692  celix::Bundle bnd{const_cast<celix_bundle_t *>(cBnd)};
693  for (const auto& cb : tracker->onStopCallbacks) {
694  cb(bnd);
695  }
696  };
697  opts.trackerCreatedCallbackData = this;
698  opts.trackerCreatedCallback = [](void *data) {
699  auto* trk = static_cast<BundleTracker*>(data);
700  std::lock_guard<std::mutex> callbackLock{trk->mutex};
701  trk->state = TrackerState::OPEN;
702  };
703  }
704 
705  const bool includeFrameworkBundle;
706  const std::vector<std::function<void(const celix::Bundle&)>> onInstallCallbacks;
707  const std::vector<std::function<void(const celix::Bundle&)>> onStartCallbacks;
708  const std::vector<std::function<void(const celix::Bundle&)>> onStopCallbacks;
709  celix_bundle_tracking_options_t opts{}; //note only set in the ctor
710  };
711 
712 
722  const std::string serviceName;
723 
727  const celix::Filter filter;
728 
733  };
734 
740  class MetaTracker : public AbstractTracker {
741  public:
742 
753 #if __cplusplus >= 201703L //C++17 or higher
754  static std::shared_ptr<MetaTracker> create(
755  std::shared_ptr<celix_bundle_context_t> cCtx,
756  std::string_view serviceName,
757  std::vector<std::function<void(const ServiceTrackerInfo&)>> onTrackerCreated,
758  std::vector<std::function<void(const ServiceTrackerInfo&)>> onTrackerDestroyed) {
759  auto tracker = std::shared_ptr<MetaTracker>{
760  new MetaTracker{
761  std::move(cCtx),
762  std::string{serviceName},
763  std::move(onTrackerCreated),
764  std::move(onTrackerDestroyed)},
765  AbstractTracker::delCallback<MetaTracker>()};
766  tracker->open();
767  return tracker;
768  }
769 #else
770  static std::shared_ptr<MetaTracker> create(
771  std::shared_ptr<celix_bundle_context_t> cCtx,
772  std::string serviceName,
773  std::vector<std::function<void(const ServiceTrackerInfo&)>> onTrackerCreated,
774  std::vector<std::function<void(const ServiceTrackerInfo&)>> onTrackerDestroyed) {
775  auto tracker = std::shared_ptr<MetaTracker>{
776  new MetaTracker{
777  std::move(cCtx),
778  std::move(serviceName),
779  std::move(onTrackerCreated),
780  std::move(onTrackerDestroyed)},
781  AbstractTracker::delCallback<MetaTracker>()};
782  tracker->open();
783  return tracker;
784  }
785 #endif
786 
790  void open() override {
791  std::lock_guard<std::mutex> lck{mutex};
794 
795  //NOTE the opts already configured the callbacks
797  cCtx.get(),
798  serviceName.empty() ? nullptr : serviceName.c_str(),
799  static_cast<void*>(this),
800  [](void *handle, const celix_service_tracker_info_t *cInfo) {
801  auto *trk = static_cast<MetaTracker *>(handle);
802  std::string svcName = cInfo->serviceName == nullptr ? "" : cInfo->serviceName;
803  ServiceTrackerInfo info{svcName, celix::Filter::wrap(cInfo->filter), cInfo->bundleId};
804  for (const auto& cb : trk->onTrackerCreated) {
805  cb(info);
806  }
807  },
808  [](void *handle, const celix_service_tracker_info_t *cInfo) {
809  auto *trk = static_cast<MetaTracker *>(handle);
810  std::string svcName = cInfo->serviceName == nullptr ? "" : cInfo->serviceName;
811  ServiceTrackerInfo info{svcName, celix::Filter::wrap(cInfo->filter), cInfo->bundleId};
812  for (const auto& cb : trk->onTrackerDestroyed) {
813  cb(info);
814  }
815  },
816  static_cast<void*>(this),
817  [](void *data) {
818  auto *trk = static_cast<MetaTracker *>(data);
819  std::lock_guard<std::mutex> callbackLock{trk->mutex};
820  trk->state = TrackerState::OPEN;
821  });
822  if (trkId < 0) {
823  throw celix::TrackerException{"Cannot open meta tracker"};
824  }
825  }
826  }
827 
828  private:
829  MetaTracker(
830  std::shared_ptr<celix_bundle_context_t> _cCtx,
831  std::string _serviceName,
832  std::vector<std::function<void(const ServiceTrackerInfo&)>> _onTrackerCreated,
833  std::vector<std::function<void(const ServiceTrackerInfo&)>> _onTrackerDestroyed) :
834  AbstractTracker{std::move(_cCtx)},
835  serviceName{std::move(_serviceName)},
836  onTrackerCreated{std::move(_onTrackerCreated)},
837  onTrackerDestroyed{std::move(_onTrackerDestroyed)} {}
838 
839  const std::string serviceName;
840  const std::vector<std::function<void(const ServiceTrackerInfo&)>> onTrackerCreated;
841  const std::vector<std::function<void(const ServiceTrackerInfo&)>> onTrackerDestroyed;
842  };
843 
844 }
celix::ServiceTracker::warningTimoutForNonExpiredSvcObject
const std::chrono::milliseconds warningTimoutForNonExpiredSvcObject
Definition: Trackers.h:525
Bundle.h
celix::ServiceTracker::entries
std::set< std::shared_ptr< SvcEntry >, SvcEntryCompare > entries
Definition: Trackers.h:544
celix::TrackerState::CLOSING
@ CLOSING
celix::ServiceTrackerInfo::serviceName
const std::string serviceName
The service name the service tracker is tracking.
Definition: Trackers.h:722
celix_bundleContext_waitForAsyncTracker
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_waitForAsyncTracker(celix_bundle_context_t *ctx, long trackerId)
Wait for (async) creation of tracker.
celix::GenericServiceTracker::~GenericServiceTracker
~GenericServiceTracker() override=default
celix_service_tracking_options::addWithOwner
void(* addWithOwner)(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *svcOwner) CELIX_OPTS_INIT
The optional addWithOwner callback is handled as the add callback, but with the addition that the ser...
Definition: celix_bundle_context.h:557
celix::GenericServiceTracker::open
void open() override
Definition: Trackers.h:238
celix::ServiceTracker::updateWithPropertiesCallbacks
const std::vector< std::function< void(const std::vector< std::pair< std::shared_ptr< I >, std::shared_ptr< const celix::Properties >>>)> > updateWithPropertiesCallbacks
Definition: Trackers.h:533
celix::ServiceTracker::SvcEntry
Definition: Trackers.h:406
celix::ServiceTrackerInfo
A trivial struct containing information about a service tracker.
Definition: Trackers.h:716
celix::GenericServiceTracker::filter
const celix::Filter filter
Definition: Trackers.h:278
celix::ServiceTracker::remCallbacks
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
Definition: Trackers.h:529
celix::GenericServiceTracker::opts
celix_service_tracking_options opts
Definition: Trackers.h:279
celix
Definition: Bundle.h:27
celix_bundleContext_trackServiceTrackersAsync
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_trackServiceTrackersAsync(celix_bundle_context_t *ctx, const char *serviceName, void *callbackHandle, void(*trackerAdd)(void *handle, const celix_service_tracker_info_t *info), void(*trackerRemove)(void *handle, const celix_service_tracker_info_t *info), void *doneCallbackData, void(*doneCallback)(void *doneCallbackData))
Track the service tracker targeting the provided service name.
celix::ServiceTracker::SvcEntryCompare::operator()
bool operator()(const std::shared_ptr< SvcEntry > &a, const std::shared_ptr< SvcEntry > &b) const
Definition: Trackers.h:537
celix::ServiceTracker::setCallbacks
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
Definition: Trackers.h:527
celix::AbstractTracker::delCallback
static std::function< void(T *)> delCallback()
Definition: Trackers.h:168
celix::ServiceTracker::createEntry
static std::shared_ptr< SvcEntry > createEntry(void *voidSvc, const celix_properties_t *cProps, const celix_bundle_t *cBnd)
Definition: Trackers.h:446
celix::MetaTracker::create
static std::shared_ptr< MetaTracker > create(std::shared_ptr< celix_bundle_context_t > cCtx, std::string_view serviceName, std::vector< std::function< void(const ServiceTrackerInfo &)>> onTrackerCreated, std::vector< std::function< void(const ServiceTrackerInfo &)>> onTrackerDestroyed)
Creates a new meta tracker and opens the tracker.
Definition: Trackers.h:754
celix::GenericServiceTracker::GenericServiceTracker
GenericServiceTracker(std::shared_ptr< celix_bundle_context_t > _cCtx, std::string_view _svcName, std::string_view _svcVersionRange, celix::Filter _filter)
Definition: Trackers.h:220
celix_bundle_tracker_options::trackerCreatedCallback
void(* trackerCreatedCallback)(void *trackerCreatedCallbackData) CELIX_OPTS_INIT
The callback called when the tracker has ben created (and is active) when using the track bundles asc...
Definition: celix_bundle_context.h:1105
celix_bundle_tracker_options
The Service Bundle Tracking options can be used to fine tune the requested bundle tracker options.
Definition: celix_bundle_context.h:1049
celix::TrackerState::OPEN
@ OPEN
celix::TrackerException
Celix Tracker Exception.
Definition: FrameworkExceptions.h:36
Constants.h
celix_bundleContext_getBundle
CELIX_FRAMEWORK_EXPORT celix_bundle_t * celix_bundleContext_getBundle(const celix_bundle_context_t *ctx)
Returns the bundle for this bundle context.
celix::ServiceTracker::waitForExpired
void waitForExpired(std::weak_ptr< U > observe, long svcId, const char *objName)
Definition: Trackers.h:470
celix::BundleTracker::open
void open() override
Definition: Trackers.h:649
celix::GenericServiceTracker::getServiceRange
const std::string & getServiceRange() const
The service version range tracked by this service tracker.
Definition: Trackers.h:259
celix::ServiceTracker::waitForExpiredSvcEntry
void waitForExpiredSvcEntry(std::shared_ptr< SvcEntry > &entry)
Definition: Trackers.h:455
celix::AbstractTracker::state
TrackerState state
Definition: Trackers.h:205
celix::GenericServiceTracker::getFilter
const celix::Filter & getFilter() const
The additional filter for services tracked by this service tracker.
Definition: Trackers.h:267
celix::AbstractTracker::open
virtual void open()=0
Open the tracker (if the state is not OPEN or OPENING).
celix::ServiceTracker::getHighestRankingService
std::shared_ptr< I > getHighestRankingService()
Get the current highest ranking service tracked by this tracker.
Definition: Trackers.h:376
celix_framework_fireGenericEvent
CELIX_FRAMEWORK_EXPORT long celix_framework_fireGenericEvent(celix_framework_t *fw, long eventId, long bndId, const char *eventName, void *processData, void(*processCallback)(void *data), void *doneData, void(*doneCallback)(void *doneData))
Fire a generic event. The event will be added to the event loop and handled on the event loop thread.
celix::ServiceTrackerInfo::trackerOwnerBundleId
const long trackerOwnerBundleId
The bundle id of the owner of the service tracker.
Definition: Trackers.h:732
celix::ServiceTracker::SvcEntry::owner
std::shared_ptr< const celix::Bundle > owner
Definition: Trackers.h:417
celix::TrackerState::CLOSED
@ CLOSED
celix::GenericServiceTracker
he GenericServiceTracker class is a specialization of the AbstractTracker for managing a service trac...
Definition: Trackers.h:217
celix::TrackerState::OPENING
@ OPENING
celix::ServiceTracker::ServiceTracker
ServiceTracker(std::shared_ptr< celix_bundle_context_t > _cCtx, std::string_view _svcName, std::string_view _svcVersionRange, celix::Filter _filter, 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, 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, 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)
Definition: Trackers.h:421
celix::GenericServiceTracker::getServiceCount
std::size_t getServiceCount() const
The nr of services currently tracked by this tracker.
Definition: Trackers.h:272
celix::ServiceTracker::SvcEntry::properties
std::shared_ptr< const celix::Properties > properties
Definition: Trackers.h:416
celix::ServiceTracker
The ServiceTracker class tracks services.
Definition: Trackers.h:308
celix::GenericServiceTracker::svcCount
std::atomic< size_t > svcCount
Definition: Trackers.h:280
celix_bundleContext_stopTracker
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_stopTracker(celix_bundle_context_t *ctx, long trackerId)
Stop the tracker with the provided track id.
celix_service_tracking_options::trackerCreatedCallback
void(* trackerCreatedCallback)(void *trackerCreatedCallbackData) CELIX_OPTS_INIT
The callback called when the tracker has ben created (and is active) when using a async call.
Definition: celix_bundle_context.h:595
celix::BundleTracker
The BundleTracker class tracks bundles.
Definition: Trackers.h:614
celix_framework.h
The Celix Framework API.
celix_service_tracking_options::removeWithOwner
void(* removeWithOwner)(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *svcOwner) CELIX_OPTS_INIT
The optional removeWithOwner callback is handled as the remove callback, but with the addition that t...
Definition: celix_bundle_context.h:580
celix::ServiceTracker::cachedEntries
std::unordered_map< long, std::shared_ptr< SvcEntry > > cachedEntries
Definition: Trackers.h:545
celix_framework_isCurrentThreadTheEventLoop
CELIX_FRAMEWORK_EXPORT bool celix_framework_isCurrentThreadTheEventLoop(celix_framework_t *fw)
Returns whether the current thread is the Celix framework event loop thread.
celix::MetaTracker
The MetaTracker track service trackers.
Definition: Trackers.h:740
celix::AbstractTracker::waitIfAble
void waitIfAble() const
Wait (if not on the Celix event thread) for the tracker to be OPEN or CLOSED.
Definition: Trackers.h:160
celix::ServiceTracker::SvcEntryCompare
Definition: Trackers.h:536
FrameworkExceptions.h
celix_service_tracking_options
Service Tracker Options used to fine tune which services to track and the callback to be used for the...
Definition: celix_bundle_context.h:508
celix::Bundle
An installed bundle in the Celix framework.
Definition: Bundle.h:48
celix_bundleContext_waitForAsyncStopTracker
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_waitForAsyncStopTracker(celix_bundle_context_t *ctx, long trackerId)
Wait for (async) stopping of tracking.
celix::ServiceTracker::mutex
std::mutex mutex
Definition: Trackers.h:543
celix::AbstractTracker::mutex
std::mutex mutex
Definition: Trackers.h:203
celix::AbstractTracker::getState
TrackerState getState() const
Get the current state of the tracker.
Definition: Trackers.h:90
celix::ServiceTracker::create
static std::shared_ptr< ServiceTracker< I > > create(std::shared_ptr< celix_bundle_context_t > cCtx, std::string_view svcName, std::string_view svcVersionRange, celix::Filter filter, 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, 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, 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)
Creates a new service tracker and opens the tracker.
Definition: Trackers.h:323
celix::ServiceTracker::updateWithOwnerCallbacks
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
Definition: Trackers.h:534
celix::BundleTracker::create
static std::shared_ptr< BundleTracker > create(std::shared_ptr< celix_bundle_context_t > cCtx, bool includeFrameworkBundle, std::vector< std::function< void(const celix::Bundle &)>> onInstallCallbacks, std::vector< std::function< void(const celix::Bundle &)>> onStartCallbacks, std::vector< std::function< void(const celix::Bundle &)>> onStopCallbacks)
Creates a new bundle tracker and opens the tracker.
Definition: Trackers.h:627
celix::AbstractTracker::wait
void wait() const
Wait until a service tracker is completely OPEN or CLOSED.
Definition: Trackers.h:136
celix_bundle_tracker_options::onStarted
void(* onStarted)(void *handle, const celix_bundle_t *bundle) CELIX_OPTS_INIT
Tracker callback when a bundle is started.
Definition: celix_bundle_context.h:1069
celix::GenericServiceTracker::svcName
const std::string svcName
Definition: Trackers.h:276
celix::TrackerState
TrackerState
The tracker state.
Definition: Trackers.h:47
celix_bundleContext_log
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_log(const celix_bundle_context_t *ctx, celix_log_level_e level, const char *format,...) __attribute__((format(printf
Logs a message to Celix framework logger with the provided log level.
celix_bundle_tracker_options::onInstalled
void(* onInstalled)(void *handle, const celix_bundle_t *bundle) CELIX_OPTS_INIT
Tracker callback when a bundle is installed.
Definition: celix_bundle_context.h:1061
celix::ServiceTracker::SvcEntry::svc
std::shared_ptr< I > svc
Definition: Trackers.h:415
celix::ServiceTracker::SvcEntry::svcId
long svcId
Definition: Trackers.h:413
celix::ServiceTracker::invokeUpdateCallbacks
void invokeUpdateCallbacks()
Definition: Trackers.h:483
celix_bundle_getId
CELIX_FRAMEWORK_EXPORT long celix_bundle_getId(const celix_bundle_t *bnd)
Return the bundle id.
celix::ServiceTracker::SvcEntry::svcRanking
long svcRanking
Definition: Trackers.h:414
celix::AbstractTracker::AbstractTracker
AbstractTracker(std::shared_ptr< celix_bundle_context_t > _cCtx)
Definition: Trackers.h:74
celix::AbstractTracker::isOpen
bool isOpen() const
Check if the tracker is open (state == OPEN)
Definition: Trackers.h:82
celix_bundleContext_trackServicesWithOptionsAsync
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_trackServicesWithOptionsAsync(celix_bundle_context_t *ctx, const celix_service_tracking_options_t *opts)
Tracks services using the provided tracker options.
celix::AbstractTracker::trkId
long trkId
Definition: Trackers.h:204
celix::AbstractTracker::cCtx
const std::shared_ptr< celix_bundle_context_t > cCtx
Definition: Trackers.h:201
celix::GenericServiceTracker::getServiceName
const std::string & getServiceName() const
The service name tracked by this service tracker.
Definition: Trackers.h:254
celix_service_tracker_info
Service Tracker Info provided to the service tracker tracker callbacks.
Definition: celix_bundle_context.h:1188
celix_service_tracking_options::setWithOwner
void(* setWithOwner)(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *svcOwner) CELIX_OPTS_INIT
The optional setWithOwner callback is handled as the set callback, but with the addition that the ser...
Definition: celix_bundle_context.h:537
celix::AbstractTracker::~AbstractTracker
virtual ~AbstractTracker() noexcept=default
celix_bundle_tracker_options::onStopped
void(* onStopped)(void *handle, const celix_bundle_t *bundle) CELIX_OPTS_INIT
Tracker callback when a bundle is stopped.
Definition: celix_bundle_context.h:1077
celix_bundleContext_trackBundlesWithOptionsAsync
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_trackBundlesWithOptionsAsync(celix_bundle_context_t *ctx, const celix_bundle_tracking_options_t *opts)
Tracks bundles using the provided bundle tracker options.
celix::ServiceTracker::addCallbacks
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
Definition: Trackers.h:528
celix::AbstractTracker::close
void close()
Close the tracker (of the state is not CLOSED or CLOSING).
Definition: Trackers.h:101
celix::GenericServiceTracker::svcVersionRange
const std::string svcVersionRange
Definition: Trackers.h:277
celix::AbstractTracker
The AbstractTracker class is the base of all C++ Celix trackers.
Definition: Trackers.h:72
celix::MetaTracker::open
void open() override
Definition: Trackers.h:790
celix_bundleContext_getFramework
CELIX_FRAMEWORK_EXPORT celix_framework_t * celix_bundleContext_getFramework(const celix_bundle_context_t *ctx)
celix::ServiceTracker::getServices
std::vector< std::shared_ptr< I > > getServices()
Get a vector of all the currently found services for this tracker.
Definition: Trackers.h:395
celix::ServiceTrackerInfo::filter
const celix::Filter filter
The service filter the service tracker is using for tracking.
Definition: Trackers.h:727
celix::ServiceTracker::highestRankingServiceEntry
std::shared_ptr< SvcEntry > highestRankingServiceEntry
Definition: Trackers.h:546
celix_bundle_context.h
celix::ServiceTracker::updateCallbacks
const std::vector< std::function< void(const std::vector< std::shared_ptr< I >>)> > updateCallbacks
Definition: Trackers.h:532
celix::ServiceTracker::SvcEntry::SvcEntry
SvcEntry(long _svcId, long _svcRanking, std::shared_ptr< I > _svc, std::shared_ptr< const celix::Properties > _properties, std::shared_ptr< const celix::Bundle > _owner)
Definition: Trackers.h:407