Skip to content

Commit

Permalink
DPL: add helper method to retrieve and cache CCDB metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
ktf committed Oct 10, 2024
1 parent 3494541 commit b3c6c34
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
47 changes: 47 additions & 0 deletions Framework/Core/include/Framework/InputRecord.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
namespace o2::framework
{

// Wrapper class to get CCDB metadata
struct CCDBMetadataExtractor {
};

struct InputSpec;
class InputSpan;
class CallbackService;
Expand Down Expand Up @@ -464,6 +468,49 @@ class InputRecord
}
}

template <typename T = DataRef, typename R>
std::map<std::string, std::string>& get(R binding, int part = 0) const
requires std::same_as<T, CCDBMetadataExtractor>
{
auto ref = getRef(binding, part);
auto header = DataRefUtils::getHeader<header::DataHeader*>(ref);
auto payloadSize = DataRefUtils::getPayloadSize(ref);
auto method = header->payloadSerializationMethod;
if (method != header::gSerializationMethodCCDB) {
throw runtime_error("Attempt to extract metadata from a non-CCDB serialised message");
}
// This is to support deserialising objects from CCDB. Contrary to what happens for
// other objects, those objects are most likely long lived, so we
// keep around an instance of the associated object and deserialise it only when
// it's updated.
auto id = ObjectCache::Id::fromRef(ref);
ConcreteDataMatcher matcher{header->dataOrigin, header->dataDescription, header->subSpecification};
// If the matcher does not have an entry in the cache, deserialise it
// and cache the deserialised object at the given id.
auto path = fmt::format("{}", DataSpecUtils::describe(matcher));
LOGP(debug, "{}", path);
auto& cache = mRegistry.get<ObjectCache>();
auto cacheEntry = cache.matcherToMetadataId.find(path);
if (cacheEntry == cache.matcherToMetadataId.end()) {
cache.matcherToMetadataId.insert(std::make_pair(path, id));
cache.idToMetadata[id] = extractCCDBHeaders(ref);
LOGP(info, "Caching CCDB metadata {}: {}", id.value, path);
return cache.idToMetadata[id];
}
auto& oldId = cacheEntry->second;
// The id in the cache is the same, let's simply return it.
if (oldId.value == id.value) {
LOGP(debug, "Returning cached CCDB metatada {}: {}", id.value, path);
return cache.idToMetadata[id];
}
// The id in the cache is different. Let's destroy the old cached entry
// and create a new one.
LOGP(info, "Replacing cached entry {} with {} for {}", oldId.value, id.value, path);
cache.idToObject[id] = extracCCDBMetadata(ref);
oldId.value = id.value;
return cache.idToObject[id];
}

/// Helper method to be used to check if a given part of the InputRecord is present.
[[nodiscard]] bool isValid(std::string const& s) const
{
Expand Down
7 changes: 7 additions & 0 deletions Framework/Core/include/Framework/ObjectCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "Framework/DataRef.h"
#include <unordered_map>
#include <map>

namespace o2::framework
{
Expand Down Expand Up @@ -46,6 +47,12 @@ struct ObjectCache {
/// A map from a CacheId (which is the void* ptr of the previous map).
/// to an actual (type erased) pointer to the deserialised object.
std::unordered_map<Id, void*, Id::hash_fn> idToObject;

/// A cache to the deserialised metadata
/// We keep it separate because we want to avoid that looking up
/// the metadata also pollutes the object cache.
std::unordered_map<std::string, Id> matcherToMetadataId;
std::unordered_map<Id, std::map<std::string, std::string>, Id::hash_fn> idToMetadata;
};

} // namespace o2::framework
Expand Down

0 comments on commit b3c6c34

Please sign in to comment.