Project
Loading...
Searching...
No Matches
ObjectStore.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
17#include "Mergers/ObjectStore.h"
22#include <TObject.h>
23#include <string_view>
24
25namespace o2::mergers
26{
27
28namespace object_store_helpers
29{
30
31constexpr static std::string_view errorPrefix = "Could not extract object to be merged: ";
32
33template <typename... Args>
34static std::string concat(Args&&... arguments)
35{
36 std::ostringstream ss;
37 (ss << ... << arguments);
38 return std::move(ss.str());
39}
40
42{
43 using namespace std::string_view_literals;
44 auto* object = ftm.ReadObjectAny(type);
45
46 if (object == nullptr) {
47 throw std::runtime_error(concat(errorPrefix, "Failed to read object with name '"sv, type->GetName(), "' from message using ROOT serialization."sv));
48 }
49 return object;
50}
51
52MergeInterface* castToMergeInterface(bool inheritsFromTObject, void* object, TClass* storedClass)
53{
54 using namespace std::string_view_literals;
55 MergeInterface* objectAsMergeInterface = inheritsFromTObject ? dynamic_cast<MergeInterface*>(static_cast<TObject*>(object)) : static_cast<MergeInterface*>(object);
56 if (objectAsMergeInterface == nullptr) {
57 throw std::runtime_error(concat(errorPrefix, "Could not cast '"sv, storedClass->GetName(), "' to MergeInterface"sv));
58 }
59
60 return objectAsMergeInterface;
61}
62
63std::optional<ObjectStore> extractVector(o2::framework::FairInputTBuffer& ftm, const TClass* storedClass)
64{
65 if (!storedClass->InheritsFrom(TClass::GetClass(typeid(VectorOfRawTObjects)))) {
66 return std::nullopt;
67 }
68
69 const auto* extractedVector = static_cast<VectorOfRawTObjects*>(readObject(storedClass, ftm));
70 auto result = std::vector<TObjectPtr>{};
71 result.reserve(extractedVector->size());
72 std::transform(extractedVector->begin(), extractedVector->end(), std::back_inserter(result), [](const auto& rawTObject) { return TObjectPtr(rawTObject, algorithm::deleteTCollections); });
73 return result;
74}
75
77{
78 // We do extraction on the low level to efficiently determine if the message
79 // contains an object inheriting MergeInterface or TObject. If we did it the
80 // the following way and catch an exception:
81 // framework::DataRefUtils::as<MergeInterface>(ref)
82 // it could cause a memory leak if `ref` contained a non-owning TCollection.
83 // This way we also avoid doing most of the checks twice.
84
85 using namespace std::string_view_literals;
87 if (framework::DataRefUtils::getHeader<const DataHeader*>(ref)->payloadSerializationMethod != o2::header::gSerializationMethodROOT) {
88 throw std::runtime_error(concat(errorPrefix, "It is not ROOT-serialized"sv));
89 }
90
92 ftm.InitMap();
93 auto* storedClass = ftm.ReadClass();
94 if (storedClass == nullptr) {
95 throw std::runtime_error(concat(errorPrefix, "Unknown stored class"sv));
96 }
97 ftm.SetBufferOffset(0);
98 ftm.ResetMap();
99
100 if (const auto extractedVector = extractVector(ftm, storedClass)) {
101 return extractedVector.value();
102 }
103
104 const bool inheritsFromMergeInterface = storedClass->InheritsFrom(TClass::GetClass(typeid(MergeInterface)));
105 const bool inheritsFromTObject = storedClass->InheritsFrom(TClass::GetClass(typeid(TObject)));
106
107 if (!inheritsFromMergeInterface && !inheritsFromTObject) {
108 throw std::runtime_error(concat(errorPrefix, "Class '"sv, storedClass->GetName(), "'does not inherit from MergeInterface nor TObject"sv));
109 }
110
111 auto* object = readObject(storedClass, ftm);
112
113 if (inheritsFromMergeInterface) {
114 auto* objectAsMergeInterface = castToMergeInterface(inheritsFromTObject, object, storedClass);
115 objectAsMergeInterface->postDeserialization();
116 return MergeInterfacePtr(objectAsMergeInterface);
117 } else {
118 return TObjectPtr(static_cast<TObject*>(object), algorithm::deleteTCollections);
119 }
120}
121
123{
124 // NOTE: MT - it might be worth it to create custom stack allocators for this case
126 result.reserve(vector.size());
127 std::transform(vector.begin(), vector.end(), std::back_inserter(result), [](const auto& ptr) { return ptr.get(); });
128 return result;
129}
130
131template <typename TypeToSnapshot>
133 static bool snapshot(framework::DataAllocator& allocator, const header::DataHeader::SubSpecificationType subSpec, const ObjectStore& object)
134 {
135 if (!std::holds_alternative<TypeToSnapshot>(object)) {
136 return false;
137 }
138
139 allocator.snapshot(framework::OutputRef{MergerBuilder::mergerIntegralOutputBinding(), subSpec}, *std::get<TypeToSnapshot>(object));
140
141 return true;
142 }
143};
144
145template <>
147 static bool snapshot(framework::DataAllocator& allocator, const header::DataHeader::SubSpecificationType subSpec, const ObjectStore& object)
148 {
149 if (!std::holds_alternative<VectorOfTObjectPtrs>(object)) {
150 return false;
151 }
152
153 // NOTE: it might be worth it to create custom stack allocators
154 const auto& mergedVector = std::get<VectorOfTObjectPtrs>(object);
155 const auto vectorToSnapshot = object_store_helpers::toRawObserverPointers(mergedVector);
156
157 allocator.snapshot(framework::OutputRef{MergerBuilder::mergerIntegralOutputBinding(), subSpec}, vectorToSnapshot);
158
159 return true;
160 }
161};
162
164{
165 return Snapshoter<MergeInterfacePtr>::snapshot(allocator, subSpec, mergedObject) ||
166 Snapshoter<TObjectPtr>::snapshot(allocator, subSpec, mergedObject) ||
167 Snapshoter<VectorOfTObjectPtrs>::snapshot(allocator, subSpec, mergedObject);
168}
169
170} // namespace object_store_helpers
171
172} // namespace o2::mergers
Definition of O2 Mergers merging interface, v0.1.
Algorithms for merging objects.
Definition of ObjectStore for Mergers, v0.1.
TBranch * ptr
void snapshot(const Output &spec, T const &object)
An interface which allows to merge custom objects.
static std::string mergerIntegralOutputBinding()
GLuint64EXT * result
Definition glcorearb.h:5662
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLuint object
Definition glcorearb.h:4041
bpo::variables_map arguments
constexpr o2::header::SerializationMethod gSerializationMethodROOT
Definition DataHeader.h:328
void deleteTCollections(TObject *obj)
MergeInterface * castToMergeInterface(bool inheritsFromTObject, void *object, TClass *storedClass)
void * readObject(const TClass *type, o2::framework::FairInputTBuffer &ftm)
std::optional< ObjectStore > extractVector(o2::framework::FairInputTBuffer &ftm, const TClass *storedClass)
ObjectStore extractObjectFrom(const framework::DataRef &ref)
Takes a DataRef, deserializes it (if type is supported) and puts into an ObjectStore.
VectorOfRawTObjects toRawObserverPointers(const VectorOfTObjectPtrs &)
Helper function that converts vector of smart pointers to the vector of raw pointers that is serializ...
bool snapshot(framework::DataAllocator &allocator, const header::DataHeader::SubSpecificationType subSpec, const ObjectStore &mergedObject)
Used in FullHistorMerger's and IntegratingMerger's publish function. Checks mergedObject for every st...
std::vector< TObjectPtr > VectorOfTObjectPtrs
Definition ObjectStore.h:43
std::vector< TObject * > VectorOfRawTObjects
Definition ObjectStore.h:42
std::shared_ptr< TObject > TObjectPtr
Definition ObjectStore.h:41
std::shared_ptr< MergeInterface > MergeInterfacePtr
Definition ObjectStore.h:44
std::variant< std::monostate, TObjectPtr, VectorOfTObjectPtrs, MergeInterfacePtr > ObjectStore
Definition ObjectStore.h:45
constexpr auto concat(Ts const &... t)
Definition ASoA.h:3272
static o2::header::DataHeader::PayloadSizeType getPayloadSize(const DataRef &ref)
the main header struct
Definition DataHeader.h:618
uint32_t SubSpecificationType
Definition DataHeader.h:620
static bool snapshot(framework::DataAllocator &allocator, const header::DataHeader::SubSpecificationType subSpec, const ObjectStore &object)
static bool snapshot(framework::DataAllocator &allocator, const header::DataHeader::SubSpecificationType subSpec, const ObjectStore &object)