|
8 | 8 | // In applying this license CERN does not waive the privileges and immunities |
9 | 9 | // granted to it by virtue of its status as an Intergovernmental Organization |
10 | 10 | // or submit itself to any jurisdiction. |
11 | | -#ifndef FRAMEWORK_INPUTRECORD_H |
12 | | -#define FRAMEWORK_INPUTRECORD_H |
| 11 | +#ifndef O2_FRAMEWORK_INPUTRECORD_H_ |
| 12 | +#define O2_FRAMEWORK_INPUTRECORD_H_ |
13 | 13 |
|
14 | 14 | #include "Framework/DataRef.h" |
15 | 15 | #include "Framework/DataRefUtils.h" |
|
18 | 18 | #include "Framework/TableConsumer.h" |
19 | 19 | #include "Framework/Traits.h" |
20 | 20 | #include "Framework/RuntimeError.h" |
| 21 | +#include "Framework/Logger.h" |
| 22 | +#include "Framework/ObjectCache.h" |
| 23 | + |
21 | 24 | #include "Headers/DataHeader.h" |
22 | 25 |
|
23 | 26 | #include "CommonUtils/BoostSerializer.h" |
|
34 | 37 |
|
35 | 38 | #include <fairmq/FwdDecls.h> |
36 | 39 |
|
37 | | -namespace o2 |
38 | | -{ |
39 | | -namespace framework |
| 40 | +namespace o2::framework |
40 | 41 | { |
41 | 42 |
|
42 | 43 | struct InputSpec; |
@@ -99,7 +100,8 @@ class InputRecord |
99 | 100 | using DataHeader = o2::header::DataHeader; |
100 | 101 |
|
101 | 102 | InputRecord(std::vector<InputRoute> const& inputs, |
102 | | - InputSpan& span); |
| 103 | + InputSpan& span, |
| 104 | + ObjectCache& cache); |
103 | 105 |
|
104 | 106 | /// A deleter type to be used with unique_ptr, which can be marked that |
105 | 107 | /// it does not own the underlying resource and thus should not delete it. |
@@ -384,7 +386,39 @@ class InputRecord |
384 | 386 | std::unique_ptr<ValueT const, Deleter<ValueT const>> result(DataRefUtils::as<ROOTSerialized<ValueT>>(ref).release()); |
385 | 387 | return result; |
386 | 388 | } else if (method == o2::header::gSerializationMethodCCDB) { |
387 | | - std::unique_ptr<ValueT const, Deleter<ValueT const>> result(DataRefUtils::as<CCDBSerialized<ValueT>>(ref).release()); |
| 389 | + // This is to support deserialising objects from CCDB. Contrary to what happens for |
| 390 | + // other objects, those objects are most likely long lived, so we |
| 391 | + // keep around an instance of the associated object and deserialise it only when |
| 392 | + // it's updated. |
| 393 | + // FIXME: add ability to apply callbacks to deserialised objects. |
| 394 | + auto id = ObjectCache::Id::fromRef(ref); |
| 395 | + ConcreteDataMatcher matcher{header->dataOrigin, header->dataDescription, header->subSpecification}; |
| 396 | + // If the matcher does not have an entry in the cache, deserialise it |
| 397 | + // and cache the deserialised object at the given id. |
| 398 | + auto path = fmt::format("{}", DataSpecUtils::describe(matcher)); |
| 399 | + LOGP(info, "{}", path); |
| 400 | + auto cacheEntry = mCache.matcherToId.find(path); |
| 401 | + if (cacheEntry == mCache.matcherToId.end()) { |
| 402 | + mCache.matcherToId.insert(std::make_pair(path, id)); |
| 403 | + std::unique_ptr<ValueT const, Deleter<ValueT const>> result(DataRefUtils::as<CCDBSerialized<ValueT>>(ref).release(), false); |
| 404 | + mCache.idToObject[id] = (void*)result.get(); |
| 405 | + LOGP(info, "Caching in {} ptr to {} ({})", id.value, path, (void*)result.get()); |
| 406 | + return result; |
| 407 | + } |
| 408 | + auto& oldId = cacheEntry->second; |
| 409 | + // The id in the cache is the same, let's simply return it. |
| 410 | + if (oldId.value == id.value) { |
| 411 | + std::unique_ptr<ValueT const, Deleter<ValueT const>> result((ValueT const*)mCache.idToObject[id], false); |
| 412 | + LOGP(info, "Returning cached entry {} for {} ({})", id.value, path, (void*)result.get()); |
| 413 | + return result; |
| 414 | + } |
| 415 | + // The id in the cache is different. Let's destroy the old cached entry |
| 416 | + // and create a new one. |
| 417 | + delete reinterpret_cast<ValueT*>(mCache.idToObject[oldId]); |
| 418 | + std::unique_ptr<ValueT const, Deleter<ValueT const>> result(DataRefUtils::as<CCDBSerialized<ValueT>>(ref).release(), false); |
| 419 | + mCache.idToObject[id] = (void*)result.get(); |
| 420 | + LOGP(info, "Replacing cached entry {} with {} for {} ({})", oldId.value, id.value, path, (void*)result.get()); |
| 421 | + oldId.value = id.value; |
388 | 422 | return result; |
389 | 423 | } else { |
390 | 424 | throw runtime_error("Attempt to extract object from message with unsupported serialization type"); |
@@ -627,11 +661,11 @@ class InputRecord |
627 | 661 | } |
628 | 662 |
|
629 | 663 | private: |
| 664 | + ObjectCache& mCache; |
630 | 665 | std::vector<InputRoute> const& mInputsSchema; |
631 | 666 | InputSpan& mSpan; |
632 | 667 | }; |
633 | 668 |
|
634 | | -} // namespace framework |
635 | | -} // namespace o2 |
| 669 | +} // namespace o2::framework |
636 | 670 |
|
637 | | -#endif // FRAMEWORK_INPUTREGISTRY_H |
| 671 | +#endif // O2_FRAMEWORK_INPUTREGISTRY_H_ |
0 commit comments