Skip to content

Commit eaabbab

Browse files
committed
DPL: add helper method to retrieve and cache CCDB metadata
1 parent 0442605 commit eaabbab

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

Framework/Core/include/Framework/InputRecord.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@
4040
namespace o2::framework
4141
{
4242

43+
// Wrapper class to get CCDB metadata
44+
struct CCDBMetadataExtractor {
45+
};
46+
4347
struct InputSpec;
4448
class InputSpan;
4549
class CallbackService;
@@ -464,6 +468,49 @@ class InputRecord
464468
}
465469
}
466470

471+
template <typename T = DataRef, typename R>
472+
std::map<std::string, std::string>& get(R binding, int part = 0) const
473+
requires std::same_as<T, CCDBMetadataExtractor>
474+
{
475+
auto ref = getRef(binding, part);
476+
auto header = DataRefUtils::getHeader<header::DataHeader*>(ref);
477+
auto payloadSize = DataRefUtils::getPayloadSize(ref);
478+
auto method = header->payloadSerializationMethod;
479+
if (method != header::gSerializationMethodCCDB) {
480+
throw runtime_error("Attempt to extract metadata from a non-CCDB serialised message");
481+
}
482+
// This is to support deserialising objects from CCDB. Contrary to what happens for
483+
// other objects, those objects are most likely long lived, so we
484+
// keep around an instance of the associated object and deserialise it only when
485+
// it's updated.
486+
auto id = ObjectCache::Id::fromRef(ref);
487+
ConcreteDataMatcher matcher{header->dataOrigin, header->dataDescription, header->subSpecification};
488+
// If the matcher does not have an entry in the cache, deserialise it
489+
// and cache the deserialised object at the given id.
490+
auto path = fmt::format("{}", DataSpecUtils::describe(matcher));
491+
LOGP(debug, "{}", path);
492+
auto& cache = mRegistry.get<ObjectCache>();
493+
auto cacheEntry = cache.matcherToMetadataId.find(path);
494+
if (cacheEntry == cache.matcherToMetadataId.end()) {
495+
cache.matcherToMetadataId.insert(std::make_pair(path, id));
496+
cache.idToMetadata[id] = extractCCDBHeaders(ref);
497+
LOGP(info, "Caching CCDB metadata {}: {}", id.value, path);
498+
return cache.idToMetadata[id];
499+
}
500+
auto& oldId = cacheEntry->second;
501+
// The id in the cache is the same, let's simply return it.
502+
if (oldId.value == id.value) {
503+
LOGP(debug, "Returning cached CCDB metatada {}: {}", id.value, path);
504+
return cache.idToMetadata[id];
505+
}
506+
// The id in the cache is different. Let's destroy the old cached entry
507+
// and create a new one.
508+
LOGP(info, "Replacing cached entry {} with {} for {}", oldId.value, id.value, path);
509+
cache.idToObject[id] = extracCCDBMetadata(ref);
510+
oldId.value = id.value;
511+
return cache.idToObject[id];
512+
}
513+
467514
/// Helper method to be used to check if a given part of the InputRecord is present.
468515
[[nodiscard]] bool isValid(std::string const& s) const
469516
{

Framework/Core/include/Framework/ObjectCache.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "Framework/DataRef.h"
1515
#include <unordered_map>
16+
#include <map>
1617

1718
namespace o2::framework
1819
{
@@ -46,6 +47,12 @@ struct ObjectCache {
4647
/// A map from a CacheId (which is the void* ptr of the previous map).
4748
/// to an actual (type erased) pointer to the deserialised object.
4849
std::unordered_map<Id, void*, Id::hash_fn> idToObject;
50+
51+
/// A cache to the deserialised metadata
52+
/// We keep it separate because we want to avoid that looking up
53+
/// the metadata also pollutes the object cache.
54+
std::unordered_map<std::string, Id> matcherToMetadataId;
55+
std::unordered_map<Id, std::map<std::string, std::string>, Id::hash_fn> idToMetadata;
4956
};
5057

5158
} // namespace o2::framework

0 commit comments

Comments
 (0)