Project
Loading...
Searching...
No Matches
RootSerializableKeyValueStore.h
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
12#ifndef ALICEO2_ROOTSERKEYVALUESTORE_H
13#define ALICEO2_ROOTSERKEYVALUESTORE_H
14
15#include <map>
16#include <string>
17#include <TClass.h>
18#include <Rtypes.h>
19#include <typeinfo>
20#include <typeindex>
21#include <TBufferFile.h>
22#include <type_traits>
23#include <cstring>
24#include <memory>
25
26namespace o2
27{
28namespace utils
29{
30
38{
39 public:
42 SerializedInfo() = default;
44 std::unique_ptr<char> buffer, TClass const* cl, std::string const& s) : N(N), cl(cl), typeinfo_name(s)
45 {
46 bufferptr = buffer.get();
47 buffer.release();
48 }
50 {
51 // we do a deep copy
52 N = other.N;
53 bufferptr = new char[N];
54
55 std::memcpy(bufferptr, other.bufferptr, sizeof(char) * N);
56 cl = other.cl;
57 typeinfo_name = other.typeinfo_name;
58 }
60 {
62 std::swap(*this, temp);
63 return *this;
64 }
66 {
67 // we are the owner of this ... so delete it
68 delete[] bufferptr;
69 }
70
71 void* objptr = nullptr;
72 Int_t N = 0;
73 char* bufferptr = nullptr; //[N] pointer to serialized buffer
74
75 // we use the TClass and/or the type_index_hash for type idendification
76 TClass const* cl = nullptr;
77 std::string typeinfo_name; // typeinfo name that can be used to store type if TClass not available (for PODs!)
79 };
80
81 enum class GetState {
82 kOK = 0,
83 kNOSUCHKEY = 1,
84 kWRONGTYPE = 2,
85 kNOTCLASS = 3
86 };
87
88 private:
89 static constexpr const char* GetStateString[4] = {
90 "ok",
91 "no such key",
92 "wrong type",
93 "no TClass"};
94
95 public:
96 static const char* getStateString(GetState state)
97 {
98 return (int)state < 4 ? GetStateString[(int)state] : nullptr;
99 };
100
102
105 template <typename T>
106 void put(std::string const& key, T const& value)
107 {
108 remove_entry(key);
109 GetState s;
110 return put_impl(key, value, s, int{});
111 }
112
114 template <typename T>
115 const T* get(std::string const& key) const
116 {
117 GetState s;
118 return get_impl<T>(key, s, int{});
119 }
120
122 template <typename T>
123 const T* get(std::string const& key, GetState& state) const
124 {
125 return get_impl<T>(key, state, int{});
126 }
127
130 template <typename T>
131 const T& getRef(std::string const& key, GetState& state) const
132 {
133 auto ptr = get_impl<T>(key, state, int{});
134 if (ptr) {
135 return *ptr;
136 } else {
137 static T t = T();
138 // in case of error we return a default object
139 return t;
140 }
141 }
142
144 bool has(std::string const& key) const
145 {
146 return mStore.find(key) != mStore.end();
147 }
148
150 void clear()
151 {
152 mStore.clear();
153 }
154
156 void print(bool includetypeinfo = false) const;
157
160 {
161 mStore.clear();
162 mStore = other.mStore;
163 }
164
165 private:
166 std::map<std::string, SerializedInfo> mStore;
167
168 // generic implementation for put relying on TClass
169 template <typename T>
170 void put_impl(std::string const& key, T const& value, GetState& state, ...)
171 {
172 // make sure we have a TClass for this
173 // if there is a TClass, we'll use ROOT serialization to encode into the buffer
174 auto ptr = std::make_unique<T>(T{value});
175 auto cl = TClass::GetClass(typeid(value));
176 if (!cl) {
178 return;
179 }
180 std::unique_ptr<char> bufferptr(nullptr);
181 TBufferFile buff(TBuffer::kWrite);
182 buff.WriteObjectAny(ptr.get(), cl);
183 int N = buff.Length();
184 bufferptr.reset(new char[N]);
185 memcpy(bufferptr.get(), buff.Buffer(), sizeof(char) * N);
186
187 auto name = std::type_index(typeid(value)).name();
188 mStore.insert(std::pair<std::string, SerializedInfo>(key, SerializedInfo(N, std::move(bufferptr), cl, name)));
189 }
190
191 // implementation for put for trivial types
192 template <typename T, typename std::enable_if<std::is_trivial<T>::value, T>::type* = nullptr>
193 void put_impl(std::string const& key, T const& value, GetState& state, int)
194 {
195 // we forbid pointers
196 static_assert(!std::is_pointer<T>::value);
197 // serialization of trivial types is easy (not based on ROOT)
198 auto ptr = std::make_unique<T>(T{value});
199 int N = sizeof(T);
200 std::unique_ptr<char> bufferptr(new char[N]);
201 memcpy(bufferptr.get(), (char*)ptr.get(), sizeof(char) * N);
202
203 auto name = std::type_index(typeid(value)).name();
204 mStore.insert(std::pair<std::string, SerializedInfo>(key, SerializedInfo(N, std::move(bufferptr), nullptr, name)));
205 }
206
207 // generic implementation for get relying on TClass
208 template <typename T>
209 const T* get_impl(std::string const& key, GetState& state, ...) const
210 {
212 auto iter = mStore.find(key);
213 if (iter != mStore.end()) {
214 auto& info = const_cast<SerializedInfo&>(iter->second);
215 auto cl = TClass::GetClass(typeid(T));
216 if (!cl) {
218 return nullptr;
219 }
220 if (info.cl && strcmp(cl->GetName(), info.cl->GetName()) == 0) {
221 // if there is a (cached) object pointer ... we return it
222 if (info.objptr) {
223 return (T*)info.objptr;
224 }
225 // do this only once and cache instance into info.objptr
226 TBufferFile buff(TBuffer::kRead, info.N, info.bufferptr, false, nullptr);
227 buff.Reset();
228 auto instance = (T*)buff.ReadObjectAny(cl);
229 info.objptr = instance;
230 return (T*)info.objptr;
231 } else {
233 return nullptr;
234 }
235 }
237 return nullptr;
238 }
239
240 // implementation for standard POD types
241 template <typename T, typename std::enable_if<std::is_trivial<T>::value, T>::type* = nullptr>
242 const T* get_impl(std::string const& key, GetState& state, int) const
243 {
245 auto iter = mStore.find(key);
246 if (iter != mStore.end()) {
247 auto& info = const_cast<SerializedInfo&>(iter->second);
248 if (strcmp(std::type_index(typeid(T)).name(), info.typeinfo_name.c_str()) == 0) {
249 // if there is a (cached) object pointer ... we return it
250 if (info.objptr) {
251 return (T*)info.objptr;
252 }
253 info.objptr = (T*)info.bufferptr;
254 return (T*)info.objptr;
255 } else {
257 return nullptr;
258 }
259 }
261 return nullptr;
262 }
263
264 // removes a previous entry
265 void remove_entry(std::string const& key)
266 {
267 auto iter = mStore.find(key);
268 if (iter != mStore.end()) {
269 mStore.erase(iter);
270 }
271 }
272
273 ClassDefNV(RootSerializableKeyValueStore, 2);
274};
275
276} // namespace utils
277} // namespace o2
278
279#endif
void print() const
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error s
SurfaceTrackState state
TBranch * ptr
StringRef key
const T & getRef(std::string const &key, GetState &state) const
const T * get(std::string const &key, GetState &state) const
returns object pointer for this key or nullptr if error or does not exist; state is set with meaningf...
void put(std::string const &key, T const &value)
const T * get(std::string const &key) const
returns object pointer for this key or nullptr if error or does not exist.
static const char * getStateString(GetState state)
void copyFrom(RootSerializableKeyValueStore const &other)
resets store to the store of another object
bool has(std::string const &key) const
checks if a key exists
GLuint const GLchar * name
Definition glcorearb.h:781
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Common utility functions.
Structure encapsulating the stored information: raw buffers and attached type information (combinatio...
SerializedInfo(int N, std::unique_ptr< char > buffer, TClass const *cl, std::string const &s)
VectorOfTObjectPtrs other