Apache Celix  latest
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 <cstdint>
23 #include <memory>
24 #include <mutex>
25 #include <atomic>
26 #include <cassert>
27 #include <set>
28 #include <unordered_map>
29 #include <functional>
30 #include <thread>
31 
32 #include "celix_utils.h"
33 #include "celix_bundle_context.h"
34 #include "celix_framework.h"
36 #include "celix/Properties.h"
37 #include "celix/Utils.h"
38 #include "celix/Bundle.h"
39 #include "celix/Constants.h"
40 #include "celix/Filter.h"
41 
42 namespace celix {
43 
44 
48  enum class TrackerState : std::uint8_t {
49  OPENING,
50  OPEN,
51  CLOSING,
52  CLOSED
53  };
54 
74  public:
75  explicit AbstractTracker(std::shared_ptr<celix_bundle_context_t> _cCtx) :
76  cCtx{std::move(_cCtx)} {}
77 
78  virtual ~AbstractTracker() noexcept = default;
79 
83  bool isOpen() const {
84  std::lock_guard<std::mutex> lck{mutex};
85  return state == TrackerState::OPEN;
86  }
87 
92  std::lock_guard<std::mutex> lck{mutex};
93  return state;
94  }
95 
102  void close() {
103  long localTrkId = -1;
104  {
105  std::lock_guard<std::mutex> lck{mutex};
107  //not yet closed
109  localTrkId = trkId;
110  trkId = -1;
111  }
112  }
113  if (localTrkId >= 0) {
114  celix_bundleContext_stopTracker(cCtx.get(), localTrkId);
115  {
116  std::lock_guard<std::mutex> lck{mutex};
118  }
119  }
120  }
121 
130  virtual void open() = 0;
131 
137  void wait() const {
138  bool needWaitOpening = false;
139  bool needWaitClosing = false;
140  long localId;
141  {
142  std::lock_guard<std::mutex> lck{mutex};
143  localId = trkId;
144  if (state == TrackerState::OPENING) {
145  needWaitOpening = true;
146  } else if (state == TrackerState::CLOSING) {
147  needWaitClosing = true;
148  }
149  }
150  if (needWaitOpening) {
152  }
153  if (needWaitClosing) {
155  }
156  }
157  protected:
161  void waitIfAble() const {
162  auto* fw = celix_bundleContext_getFramework(cCtx.get());
164  wait();
165  }
166  }
167 
168  template<typename T>
169  static std::function<void(T*)> delCallback() {
170  return [](T *tracker) {
171  if (tracker->getState() == TrackerState::CLOSED) {
172  delete tracker;
173  } else {
174  /*
175  * if open/opening -> close() -> new event on the Celix event thread
176  * if closing -> nop close() -> there is already a event on the Celix event thread to close
177  */
178  tracker->close();
179 
180  /*
181  * Creating event on the Event loop, this will be after the close is done
182  */
183  auto *fw = celix_bundleContext_getFramework(tracker->cCtx.get());
184  auto *bnd = celix_bundleContext_getBundle(tracker->cCtx.get());
185  long bndId = celix_bundle_getId(bnd);
187  fw,
188  -1,
189  bndId,
190  "celix::AbstractTracker delete callback",
191  tracker,
192  [](void *data) {
193  auto *t = static_cast<AbstractTracker *>(data);
194  delete t;
195  },
196  nullptr,
197  nullptr);
198  }
199  };
200  }
201 
202  const std::shared_ptr<celix_bundle_context_t> cCtx;
203 
204  mutable std::mutex mutex{}; //protects below
205  long trkId{-1L};
207  };
208 
219  public:
220  GenericServiceTracker(std::shared_ptr<celix_bundle_context_t> _cCtx, std::string _svcName,
221  std::string _svcVersionRange, celix::Filter _filter) : AbstractTracker{std::move(_cCtx)}, svcName{std::move(_svcName)},
222  svcVersionRange{std::move(_svcVersionRange)}, filter{std::move(_filter)} {
223  setupServiceTrackerOptions();
224  }
225 
226  ~GenericServiceTracker() override = default;
227 
231  void open() override {
232  std::lock_guard<std::mutex> lck{mutex};
235 
236  //NOTE assuming the opts already configured the callbacks
238  if (trkId < 0) {
239  throw celix::TrackerException{"Cannot open service tracker"};
240  }
241  }
242  }
243 
247  const std::string& getServiceName() const { return svcName; }
248 
252  const std::string& getServiceRange() const { return svcVersionRange; }
253 
260  const celix::Filter& getFilter() const { return filter; }
261 
265  std::size_t getServiceCount() const {
266  return svcCount;
267  }
268  protected:
269  const std::string svcName;
270  const std::string svcVersionRange;
271  const celix::Filter filter;
272  celix_service_tracking_options opts{}; //note only set in the ctor
273  std::atomic<size_t> svcCount{0};
274 
275  private:
276  void setupServiceTrackerOptions() {
277  opts.trackerCreatedCallbackData = this;
278  opts.trackerCreatedCallback = [](void *data) {
279  auto* trk = static_cast<GenericServiceTracker*>(data);
280  {
281  std::lock_guard<std::mutex> callbackLock{trk->mutex};
282  trk->state = TrackerState::OPEN;
283  }
284  };
285  }
286  };
287 
300  template<typename I>
302  public:
315  static std::shared_ptr<ServiceTracker<I>> create(
316  std::shared_ptr<celix_bundle_context_t> cCtx,
317  std::string svcName,
318  std::string svcVersionRange,
319  celix::Filter filter,
320  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,
321  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,
322  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) {
323  auto tracker = std::shared_ptr<ServiceTracker<I>>{
324  new ServiceTracker<I>{
325  std::move(cCtx),
326  std::move(svcName),
327  std::move(svcVersionRange),
328  std::move(filter),
329  std::move(setCallbacks),
330  std::move(addCallbacks),
331  std::move(remCallbacks)},
332  AbstractTracker::delCallback<ServiceTracker<I>>()};
333  tracker->open();
334  return tracker;
335  }
336 
345  std::shared_ptr<I> getHighestRankingService() {
346  waitIfAble();
347  std::shared_ptr<I> result{};
348  std::lock_guard<std::mutex> lck{mutex};
349  auto it = entries.begin();
350  if (it != entries.end()) {
351  result = (*it)->svc;
352  }
353  return result;
354  }
355 
364  std::vector<std::shared_ptr<I>> getServices() {
365  waitIfAble();
366  std::vector<std::shared_ptr<I>> result{};
367  std::lock_guard<std::mutex> lck{mutex};
368  result.reserve(entries.size());
369  for (auto& e : entries) {
370  result.push_back(e->svc);
371  }
372  return result;
373  }
374 
384  template<typename F>
385  size_t useServices(const F& f) {
386  return this->template useServicesInternal(
387  [&f](I& svc, const celix::Properties&, const celix::Bundle&) { f(svc); });
388  }
389 
399  template<typename F>
400  size_t useServicesWithProperties(const F& f) {
401  return this->template useServicesInternal(
402  [&f](I& svc, const celix::Properties& props, const celix::Bundle&) { f(svc, props); });
403  }
404 
415  template<typename F>
416  size_t useServicesWithOwner(const F& f) {
417  return this->template useServicesInternal(
418  [&f](I& svc, const celix::Properties& props, const celix::Bundle& bnd) { f(svc, props, bnd); });
419  }
420 
430  template<typename F>
431  bool useService(const F& f) {
432  return this->template useServiceInternal(
433  [&f](I& svc, const celix::Properties&, const celix::Bundle&) { f(svc); });
434  }
435 
445  template<typename F>
446  bool useServiceWithProperties(const F& f) {
447  return this->template useServiceInternal(
448  [&f](I& svc, const celix::Properties& props, const celix::Bundle&) { f(svc, props); });
449  }
450 
461  template<typename F>
462  bool useServiceWithOwner(const F& f) {
463  return this->template useServiceInternal(
464  [&f](I& svc, const celix::Properties& props, const celix::Bundle& bnd) { f(svc, props, bnd); });
465  }
466  protected:
467  struct SvcEntry {
468  SvcEntry(long _svcId, long _svcRanking, std::shared_ptr<I> _svc,
469  std::shared_ptr<const celix::Properties> _properties,
470  std::shared_ptr<const celix::Bundle> _owner) : svcId(_svcId), svcRanking(_svcRanking),
471  svc(std::move(_svc)),
472  properties(std::move(_properties)),
473  owner(std::move(_owner)) {}
474  long svcId;
476  std::shared_ptr<I> svc;
477  std::shared_ptr<const celix::Properties> properties;
478  std::shared_ptr<const celix::Bundle> owner;
479  };
480 
481 
482  ServiceTracker(std::shared_ptr<celix_bundle_context_t> _cCtx, std::string _svcName,
483  std::string _svcVersionRange, celix::Filter _filter,
484  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,
485  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,
486  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) :
487  GenericServiceTracker{std::move(_cCtx), std::move(_svcName), std::move(_svcVersionRange), std::move(_filter)},
488  setCallbacks{std::move(_setCallbacks)},
489  addCallbacks{std::move(_addCallbacks)},
490  remCallbacks{std::move(_remCallbacks)} {
491  setupServiceTrackerOptions();
492  }
493 
494  static std::shared_ptr<SvcEntry> createEntry(void* voidSvc, const celix_properties_t* cProps, const celix_bundle_t* cBnd) {
495  long svcId = celix_properties_getAsLong(cProps, CELIX_FRAMEWORK_SERVICE_ID, -1L);
496  long svcRanking = celix_properties_getAsLong(cProps, CELIX_FRAMEWORK_SERVICE_RANKING, 0);
497  auto svc = std::shared_ptr<I>{static_cast<I*>(voidSvc), [](I*){/*nop*/}};
498  auto props = std::make_shared<const celix::Properties>(celix::Properties::wrap(cProps));
499  auto owner = std::make_shared<celix::Bundle>(const_cast<celix_bundle_t*>(cBnd));
500  return std::make_shared<SvcEntry>(svcId, svcRanking, svc, props, owner);
501  }
502 
503  void waitForExpiredSvcEntry(std::shared_ptr<SvcEntry>& entry) {
504  if (entry) {
505  std::weak_ptr<void> svcObserve = entry->svc;
506  std::weak_ptr<const celix::Properties> propsObserve = entry->properties;
507  std::weak_ptr<const celix::Bundle> ownerObserve = entry->owner;
508  entry->svc = nullptr;
509  entry->properties = nullptr;
510  entry->owner = nullptr;
511  waitForExpired(svcObserve, entry->svcId, "service");
512  waitForExpired(propsObserve, entry->svcId, "service properties");
513  waitForExpired(ownerObserve, entry->svcId, "service bundle (owner)");
514  }
515  }
516 
517  template<typename U>
518  void waitForExpired(std::weak_ptr<U> observe, long svcId, const char* objName) {
519  auto start = std::chrono::steady_clock::now();
520  while (!observe.expired()) {
521  auto now = std::chrono::steady_clock::now();
522  auto durationInMilli = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);
523  if (durationInMilli > warningTimoutForNonExpiredSvcObject) {
524  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());
525  start = now;
526  }
527  std::this_thread::sleep_for(std::chrono::milliseconds{50});
528  }
529  }
530 
532  if (!updateCallbacks.empty()) {
533  std::vector<std::shared_ptr<I>> updateVector{};
534  {
535  std::lock_guard<std::mutex> lck{mutex};
536  updateVector.reserve(entries.size());
537  for (const auto &entry : entries) {
538  updateVector.push_back(entry->svc);
539  }
540  }
541  for (const auto& cb : updateCallbacks) {
542  cb(updateVector);
543  }
544  }
545  if (!updateWithPropertiesCallbacks.empty()) {
546  std::vector<std::pair<std::shared_ptr<I>, std::shared_ptr<const celix::Properties>>> updateVector{};
547  updateVector.reserve(entries.size());
548  {
549  std::lock_guard<std::mutex> lck{mutex};
550  for (const auto &entry : entries) {
551  updateVector.emplace_back(entry->svc, entry->properties);
552  }
553  }
554  for (const auto& cb : updateWithPropertiesCallbacks) {
555  cb(updateVector);
556  }
557  }
558  if (!updateWithOwnerCallbacks.empty()) {
559  std::vector<std::tuple<std::shared_ptr<I>, std::shared_ptr<const celix::Properties>, std::shared_ptr<const celix::Bundle>>> updateVector{};
560  updateVector.reserve(entries.size());
561  {
562  std::lock_guard<std::mutex> lck{mutex};
563  for (const auto &entry : entries) {
564  updateVector.emplace_back(entry->svc, entry->properties, entry->owner);
565  }
566  }
567  for (const auto& cb : updateWithOwnerCallbacks) {
568  cb(updateVector);
569  }
570  }
571  }
572 
573  const std::chrono::milliseconds warningTimoutForNonExpiredSvcObject{1000};
574 
575  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;
576  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;
577  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;
578 
579  //NOTE update callbacks cannot yet be configured
580  const std::vector<std::function<void(const std::vector<std::shared_ptr<I>>)>> updateCallbacks{};
581  const std::vector<std::function<void(const std::vector<std::pair<std::shared_ptr<I>, std::shared_ptr<const celix::Properties>>>)>> updateWithPropertiesCallbacks{};
582  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{};
583 
585  bool operator() (const std::shared_ptr<SvcEntry>& a, const std::shared_ptr<SvcEntry>& b) const {
586  int cmp = celix_utils_compareServiceIdsAndRanking(a->svcId, a->svcRanking, b->svcId, b->svcRanking);
587  return cmp < 0;
588  }
589  };
590 
591  mutable std::mutex mutex{}; //protect below
592  std::set<std::shared_ptr<SvcEntry>, SvcEntryCompare> entries{};
593  std::unordered_map<long, std::shared_ptr<SvcEntry>> cachedEntries{};
594  std::shared_ptr<SvcEntry> highestRankingServiceEntry{};
595 
596  private:
597  void setupServiceTrackerOptions() {
598  opts.filter.serviceName = svcName.empty() ? nullptr : svcName.c_str();
599  opts.filter.versionRange = svcVersionRange.empty() ? nullptr : svcVersionRange.c_str();
600  opts.filter.filter = filter.empty() ? nullptr : filter.getFilterCString();
601  opts.callbackHandle = this;
602  opts.addWithOwner = [](void *handle, void *voidSvc, const celix_properties_t* cProps, const celix_bundle_t* cBnd) {
603  auto tracker = static_cast<ServiceTracker<I>*>(handle);
604  auto entry = createEntry(voidSvc, cProps, cBnd);
605  {
606  std::lock_guard<std::mutex> lck{tracker->mutex};
607  tracker->entries.insert(entry);
608  tracker->cachedEntries[entry->svcId] = entry;
609  }
610  tracker->svcCount.fetch_add(1, std::memory_order_relaxed);
611  for (const auto& cb : tracker->addCallbacks) {
612  cb(entry->svc, entry->properties, entry->owner);
613  }
614  tracker->invokeUpdateCallbacks();
615  };
616  opts.removeWithOwner = [](void *handle, void*, const celix_properties_t* cProps, const celix_bundle_t*) {
617  auto tracker = static_cast<ServiceTracker<I>*>(handle);
618  long svcId = celix_properties_getAsLong(cProps, CELIX_FRAMEWORK_SERVICE_ID, -1L);
619  std::shared_ptr<SvcEntry> entry{};
620  {
621  std::lock_guard<std::mutex> lck{tracker->mutex};
622  auto it = tracker->cachedEntries.find(svcId);
623  assert(it != tracker->cachedEntries.end()); //should not happen, added during add callback
624  entry = it->second;
625  tracker->cachedEntries.erase(it);
626  tracker->entries.erase(entry);
627  }
628  for (const auto& cb : tracker->remCallbacks) {
629  cb(entry->svc, entry->properties, entry->owner);
630  }
631  tracker->invokeUpdateCallbacks();
632  tracker->svcCount.fetch_sub(1, std::memory_order_relaxed);
633  tracker->waitForExpiredSvcEntry(entry);
634  };
635  opts.setWithOwner = [](void *handle, void *voidSvc, const celix_properties_t *cProps, const celix_bundle_t *cBnd) {
636  auto tracker = static_cast<ServiceTracker<I>*>(handle);
637  std::unique_lock<std::mutex> lck{tracker->mutex};
638  auto prevEntry = tracker->highestRankingServiceEntry;
639  if (voidSvc) {
640  tracker->highestRankingServiceEntry = createEntry(voidSvc, cProps, cBnd);
641  } else {
642  tracker->highestRankingServiceEntry = nullptr;
643  }
644  for (const auto& cb : tracker->setCallbacks) {
645  if (tracker->highestRankingServiceEntry) {
646  auto& e = tracker->highestRankingServiceEntry;
647  cb(e->svc, e->properties, e->owner);
648  } else /*"unset"*/ {
649  cb(nullptr, nullptr, nullptr);
650  }
651  }
652  lck.unlock();
653  tracker->waitForExpiredSvcEntry(prevEntry);
654  };
655  }
656 
657  template<typename F>
658  size_t useServicesInternal(const F& f) {
659  size_t count = 0;
660  std::lock_guard<std::mutex> lck{mutex};
661  for (auto& e : entries) {
662  I& svc = *e->svc;
663  const celix::Properties& props = *e->properties;
664  const celix::Bundle& owner = *e->owner;
665  f(svc, props, owner);
666  count++;
667  }
668  return count;
669  }
670 
671  template<typename F>
672  bool useServiceInternal(const F& f) {
673  std::lock_guard<std::mutex> lck{mutex};
675  I& svc = *highestRankingServiceEntry->svc;
676  const celix::Properties& props = *highestRankingServiceEntry->properties;
677  const celix::Bundle& owner = *highestRankingServiceEntry->owner;
678  f(svc, props, owner);
679  return true;
680  }
681  return false;
682  }
683  };
684 
690  public:
702  static std::shared_ptr<BundleTracker> create(
703  std::shared_ptr<celix_bundle_context_t> cCtx,
704  bool includeFrameworkBundle,
705  std::vector<std::function<void(const celix::Bundle&)>> onInstallCallbacks,
706  std::vector<std::function<void(const celix::Bundle&)>> onStartCallbacks,
707  std::vector<std::function<void(const celix::Bundle&)>> onStopCallbacks) {
708 
709  auto tracker = std::shared_ptr<BundleTracker>{
710  new BundleTracker{
711  std::move(cCtx),
712  includeFrameworkBundle,
713  std::move(onInstallCallbacks),
714  std::move(onStartCallbacks),
715  std::move(onStopCallbacks)},
716  AbstractTracker::delCallback<BundleTracker>()};
717  tracker->open();
718  return tracker;
719  }
720 
724  void open() override {
725  std::lock_guard<std::mutex> lck{mutex};
728  //NOTE the opts already configured the callbacks
730  if (trkId < 0) {
731  throw celix::TrackerException{"Cannot open bundle tracker"};
732  }
733  }
734  }
735  private:
737  std::shared_ptr<celix_bundle_context_t> _cCtx,
738  bool _includeFrameworkBundle,
739  std::vector<std::function<void(const celix::Bundle&)>> _onInstallCallbacks,
740  std::vector<std::function<void(const celix::Bundle&)>> _onStartCallbacks,
741  std::vector<std::function<void(const celix::Bundle&)>> _onStopCallbacks) :
742  AbstractTracker{std::move(_cCtx)},
743  includeFrameworkBundle{_includeFrameworkBundle},
744  onInstallCallbacks{std::move(_onInstallCallbacks)},
745  onStartCallbacks{std::move(_onStartCallbacks)},
746  onStopCallbacks{std::move(_onStopCallbacks)} {
747 
748 
749  opts.includeFrameworkBundle = includeFrameworkBundle;
750  opts.callbackHandle = this;
751  opts.onInstalled = [](void *handle, const celix_bundle_t *cBnd) {
752  auto tracker = static_cast<BundleTracker *>(handle);
753  celix::Bundle bnd{const_cast<celix_bundle_t *>(cBnd)};
754  for (const auto& cb : tracker->onInstallCallbacks) {
755  cb(bnd);
756  }
757  };
758  opts.onStarted = [](void *handle, const celix_bundle_t *cBnd) {
759  auto tracker = static_cast<BundleTracker *>(handle);
760  celix::Bundle bnd{const_cast<celix_bundle_t *>(cBnd)};
761  for (const auto& cb : tracker->onStartCallbacks) {
762  cb(bnd);
763  }
764  };
765  opts.onStopped = [](void *handle, const celix_bundle_t *cBnd) {
766  auto tracker = static_cast<BundleTracker *>(handle);
767  celix::Bundle bnd{const_cast<celix_bundle_t *>(cBnd)};
768  for (const auto& cb : tracker->onStopCallbacks) {
769  cb(bnd);
770  }
771  };
772  opts.trackerCreatedCallbackData = this;
773  opts.trackerCreatedCallback = [](void *data) {
774  auto* trk = static_cast<BundleTracker*>(data);
775  std::lock_guard<std::mutex> callbackLock{trk->mutex};
776  trk->state = TrackerState::OPEN;
777  };
778  }
779 
780  const bool includeFrameworkBundle;
781  const std::vector<std::function<void(const celix::Bundle&)>> onInstallCallbacks;
782  const std::vector<std::function<void(const celix::Bundle&)>> onStartCallbacks;
783  const std::vector<std::function<void(const celix::Bundle&)>> onStopCallbacks;
784  celix_bundle_tracking_options_t opts{}; //note only set in the ctor
785  };
786 
787 
797  const std::string serviceName;
798 
802  const celix::Filter filter;
803 
808  };
809 
815  class MetaTracker : public AbstractTracker {
816  public:
817 
829  static std::shared_ptr<MetaTracker> create(
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  auto tracker = std::shared_ptr<MetaTracker>{
835  new MetaTracker{
836  std::move(cCtx),
837  std::move(serviceName),
838  std::move(onTrackerCreated),
839  std::move(onTrackerDestroyed)},
840  AbstractTracker::delCallback<MetaTracker>()};
841  tracker->open();
842  return tracker;
843  }
844 
848  void open() override {
849  std::lock_guard<std::mutex> lck{mutex};
852 
853  //NOTE the opts already configured the callbacks
855  cCtx.get(),
856  serviceName.empty() ? nullptr : serviceName.c_str(),
857  static_cast<void*>(this),
858  [](void *handle, const celix_service_tracker_info_t *cInfo) {
859  auto *trk = static_cast<MetaTracker *>(handle);
860  std::string svcName = cInfo->serviceName == nullptr ? "" : cInfo->serviceName;
861  ServiceTrackerInfo info{svcName, celix::Filter::wrap(cInfo->filter), cInfo->bundleId};
862  for (const auto& cb : trk->onTrackerCreated) {
863  cb(info);
864  }
865  },
866  [](void *handle, const celix_service_tracker_info_t *cInfo) {
867  auto *trk = static_cast<MetaTracker *>(handle);
868  std::string svcName = cInfo->serviceName == nullptr ? "" : cInfo->serviceName;
869  ServiceTrackerInfo info{svcName, celix::Filter::wrap(cInfo->filter), cInfo->bundleId};
870  for (const auto& cb : trk->onTrackerDestroyed) {
871  cb(info);
872  }
873  },
874  static_cast<void*>(this),
875  [](void *data) {
876  auto *trk = static_cast<MetaTracker *>(data);
877  std::lock_guard<std::mutex> callbackLock{trk->mutex};
878  trk->state = TrackerState::OPEN;
879  });
880  if (trkId < 0) {
881  throw celix::TrackerException{"Cannot open meta tracker"};
882  }
883  }
884  }
885 
886  private:
887  MetaTracker(
888  std::shared_ptr<celix_bundle_context_t> _cCtx,
889  std::string _serviceName,
890  std::vector<std::function<void(const ServiceTrackerInfo&)>> _onTrackerCreated,
891  std::vector<std::function<void(const ServiceTrackerInfo&)>> _onTrackerDestroyed) :
892  AbstractTracker{std::move(_cCtx)},
893  serviceName{std::move(_serviceName)},
894  onTrackerCreated{std::move(_onTrackerCreated)},
895  onTrackerDestroyed{std::move(_onTrackerDestroyed)} {}
896 
897  const std::string serviceName;
898  const std::vector<std::function<void(const ServiceTrackerInfo&)>> onTrackerCreated;
899  const std::vector<std::function<void(const ServiceTrackerInfo&)>> onTrackerDestroyed;
900  };
901 
902 }
celix::ServiceTracker::create
static std::shared_ptr< ServiceTracker< I > > create(std::shared_ptr< celix_bundle_context_t > cCtx, std::string svcName, std::string 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:315
celix::ServiceTracker::warningTimoutForNonExpiredSvcObject
const std::chrono::milliseconds warningTimoutForNonExpiredSvcObject
Definition: Trackers.h:573
Bundle.h
celix::ServiceTracker::entries
std::set< std::shared_ptr< SvcEntry >, SvcEntryCompare > entries
Definition: Trackers.h:592
celix::TrackerState::CLOSING
@ CLOSING
celix::ServiceTrackerInfo::serviceName
const std::string serviceName
The service name the service tracker is tracking.
Definition: Trackers.h:797
celix_bundleContext_waitForAsyncTracker
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_waitForAsyncTracker(celix_bundle_context_t *ctx, long trackerId)
Wait, if able, for (async) creation of a 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:680
celix::ServiceTracker::useServiceWithProperties
bool useServiceWithProperties(const F &f)
Applies the provided function to the highest ranking service being tracked, along with its properties...
Definition: Trackers.h:446
celix::GenericServiceTracker::open
void open() override
Definition: Trackers.h:231
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:581
celix::ServiceTracker::SvcEntry
Definition: Trackers.h:467
celix::ServiceTrackerInfo
A trivial struct containing information about a service tracker.
Definition: Trackers.h:791
celix::GenericServiceTracker::filter
const celix::Filter filter
Definition: Trackers.h:271
celix::ServiceTracker::useServices
size_t useServices(const F &f)
Applies the provided function to each service being tracked.
Definition: Trackers.h:385
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:577
celix::GenericServiceTracker::opts
celix_service_tracking_options opts
Definition: Trackers.h:272
celix
Definition: Bundle.h:28
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:585
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:575
celix::AbstractTracker::delCallback
static std::function< void(T *)> delCallback()
Definition: Trackers.h:169
celix::ServiceTracker::createEntry
static std::shared_ptr< SvcEntry > createEntry(void *voidSvc, const celix_properties_t *cProps, const celix_bundle_t *cBnd)
Definition: Trackers.h:494
celix::ServiceTracker::ServiceTracker
ServiceTracker(std::shared_ptr< celix_bundle_context_t > _cCtx, std::string _svcName, std::string _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:482
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:1282
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:1226
celix::TrackerState::OPEN
@ OPEN
celix::TrackerException
Celix Tracker Exception.
Definition: FrameworkExceptions.h:36
celix::ServiceTracker::useServicesWithOwner
size_t useServicesWithOwner(const F &f)
Applies the provided function to each service being tracked, along with its properties and owner bund...
Definition: Trackers.h:416
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:518
celix::GenericServiceTracker::GenericServiceTracker
GenericServiceTracker(std::shared_ptr< celix_bundle_context_t > _cCtx, std::string _svcName, std::string _svcVersionRange, celix::Filter _filter)
Definition: Trackers.h:220
celix::BundleTracker::open
void open() override
Definition: Trackers.h:724
celix::GenericServiceTracker::getServiceRange
const std::string & getServiceRange() const
The service version range tracked by this service tracker.
Definition: Trackers.h:252
celix::ServiceTracker::waitForExpiredSvcEntry
void waitForExpiredSvcEntry(std::shared_ptr< SvcEntry > &entry)
Definition: Trackers.h:503
celix::AbstractTracker::state
TrackerState state
Definition: Trackers.h:206
celix::GenericServiceTracker::getFilter
const celix::Filter & getFilter() const
The additional filter for services tracked by this service tracker.
Definition: Trackers.h:260
celix::MetaTracker::create
static std::shared_ptr< MetaTracker > create(std::shared_ptr< celix_bundle_context_t > cCtx, std::string 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:829
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:345
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:807
celix::ServiceTracker::SvcEntry::owner
std::shared_ptr< const celix::Bundle > owner
Definition: Trackers.h:478
celix::TrackerState::CLOSED
@ CLOSED
celix::GenericServiceTracker
he GenericServiceTracker class is a specialization of the AbstractTracker for managing a service trac...
Definition: Trackers.h:218
celix::TrackerState::OPENING
@ OPENING
celix::GenericServiceTracker::getServiceCount
std::size_t getServiceCount() const
The nr of services currently tracked by this tracker.
Definition: Trackers.h:265
celix::ServiceTracker::useServicesWithProperties
size_t useServicesWithProperties(const F &f)
Applies the provided function to each service being tracked, along with its properties.
Definition: Trackers.h:400
celix::ServiceTracker::useService
bool useService(const F &f)
Applies the provided function to the highest ranking service being tracked.
Definition: Trackers.h:431
celix::ServiceTracker::SvcEntry::properties
std::shared_ptr< const celix::Properties > properties
Definition: Trackers.h:477
celix::ServiceTracker
The ServiceTracker class tracks services.
Definition: Trackers.h:301
celix::GenericServiceTracker::svcCount
std::atomic< size_t > svcCount
Definition: Trackers.h:273
celix::ServiceTracker::useServiceWithOwner
bool useServiceWithOwner(const F &f)
Applies the provided function to the highest ranking service being tracked, along with its properties...
Definition: Trackers.h:462
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:719
celix::BundleTracker
The BundleTracker class tracks bundles.
Definition: Trackers.h:689
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:704
celix::ServiceTracker::cachedEntries
std::unordered_map< long, std::shared_ptr< SvcEntry > > cachedEntries
Definition: Trackers.h:593
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:815
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:161
celix::ServiceTracker::SvcEntryCompare
Definition: Trackers.h:584
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:627
celix::Bundle
An installed bundle in the Celix framework.
Definition: Bundle.h:49
celix_bundleContext_waitForAsyncStopTracker
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_waitForAsyncStopTracker(celix_bundle_context_t *ctx, long trackerId)
Wait, if able, for (async) stopping of tracking.
celix::ServiceTracker::mutex
std::mutex mutex
Definition: Trackers.h:591
celix::AbstractTracker::mutex
std::mutex mutex
Definition: Trackers.h:204
celix::AbstractTracker::getState
TrackerState getState() const
Get the current state of the tracker.
Definition: Trackers.h:91
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:582
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:702
celix::AbstractTracker::wait
void wait() const
Wait until a service tracker is completely OPEN or CLOSED.
Definition: Trackers.h:137
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:1246
celix::GenericServiceTracker::svcName
const std::string svcName
Definition: Trackers.h:269
celix::TrackerState
TrackerState
The tracker state.
Definition: Trackers.h:48
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:1238
celix::ServiceTracker::SvcEntry::svc
std::shared_ptr< I > svc
Definition: Trackers.h:476
celix::ServiceTracker::SvcEntry::svcId
long svcId
Definition: Trackers.h:474
celix::ServiceTracker::invokeUpdateCallbacks
void invokeUpdateCallbacks()
Definition: Trackers.h:531
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:475
celix::AbstractTracker::AbstractTracker
AbstractTracker(std::shared_ptr< celix_bundle_context_t > _cCtx)
Definition: Trackers.h:75
celix::AbstractTracker::isOpen
bool isOpen() const
Check if the tracker is open (state == OPEN)
Definition: Trackers.h:83
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:205
celix::AbstractTracker::cCtx
const std::shared_ptr< celix_bundle_context_t > cCtx
Definition: Trackers.h:202
celix::GenericServiceTracker::getServiceName
const std::string & getServiceName() const
The service name tracked by this service tracker.
Definition: Trackers.h:247
celix_service_tracker_info
Service Tracker Info provided to the service tracker tracker callbacks.
Definition: celix_bundle_context.h:1365
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:659
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:1254
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:576
celix::AbstractTracker::close
void close()
Close the tracker (of the state is not CLOSED or CLOSING).
Definition: Trackers.h:102
celix::GenericServiceTracker::svcVersionRange
const std::string svcVersionRange
Definition: Trackers.h:270
celix::dm::Properties
celix::Properties Properties
Definition: Properties.h:25
celix::AbstractTracker
The AbstractTracker class is the base of all C++ Celix trackers.
Definition: Trackers.h:73
celix::MetaTracker::open
void open() override
Definition: Trackers.h:848
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:364
celix::ServiceTrackerInfo::filter
const celix::Filter filter
The service filter the service tracker is using for tracking.
Definition: Trackers.h:802
celix::ServiceTracker::highestRankingServiceEntry
std::shared_ptr< SvcEntry > highestRankingServiceEntry
Definition: Trackers.h:594
celix_bundle_context.h
celix::ServiceTracker::updateCallbacks
const std::vector< std::function< void(const std::vector< std::shared_ptr< I >>)> > updateCallbacks
Definition: Trackers.h:580
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:468