Project
Loading...
Searching...
No Matches
ConfigurableParam.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// first version 8/2018, Sandro Wenzel
13
14#ifndef COMMON_SIMCONFIG_INCLUDE_SIMCONFIG_CONFIGURABLEPARAM_H_
15#define COMMON_SIMCONFIG_INCLUDE_SIMCONFIG_CONFIGURABLEPARAM_H_
16
17#include <algorithm>
18#include <cassert>
19#include <cctype>
20#include <concepts>
21#include <cstdint>
22#include <limits>
23#include <map>
24#include <sstream>
25#include <stdexcept>
26#include <string>
27#include <type_traits>
28#include <unordered_map>
29#include <vector>
30#include <boost/property_tree/ptree_fwd.hpp>
31#include <typeinfo>
32#include <iostream>
33#include <array>
34
35class TFile;
36class TRootIOCtor;
37class TDataMember;
38
39namespace o2
40{
41namespace conf
42{
43// Base class for a configurable parameter.
44//
45// A configurable parameter (ConfigurableParameter) is a simple class, defining
46// a few (pod) properties/members which are registered
47// in a global (boost) property tree / structure.
48//
49// The features that we provide here are:
50// *) Automatic translation from C++ data description to INI/JSON/XML
51// format via ROOT introspection and boost property trees and
52// the possibility to readably save the configuration
53// *) Serialization/Deserialization into ROOT binary blobs (for the purpose
54// of writing/retrieving parameters from CCDB and to pass parameters along the processing chain)
55// *) Automatic integration of sub-classes into a common configuration
56// *) Be able to query properties from high level interfaces (just knowing
57// *) Be able to set properties from high-level interfaces (and modifying the underlying
58// C++ object)
59// *) Automatic ability to modify parameters from the command-line
60// *) Keeping track of the provenance of individual parameter values; The user is able
61// to see whether is parameter is defaulted-code-value/coming-from-CCDB/coming-from-comandline
62//
63// Note that concrete parameter sub-classes **must** be implemented
64// by inheriting from ConfigurableParamHelper and not from this class.
65//
66// ---------------------
67// Example: To define a parameter class TPCGasParameters, one does the following:
68//
69// class TPCGasParamer : public ConfigurableParamHelper<TPCGasParameter>
70// {
71// public:
72// double getGasDensity() const { return mGasDensity; }
73// private: // define properties AND default values
74// double mGasDensity = 1.23;
75// int mGasMaterialID = 1;
76//
77// O2ParamDef(TPCGasParameter, TPCGas); // a macro implementing some magic
78// }
79//
80//
81// We can now query the parameters in various ways
82// - All parameter classes are singletons and we can say: TPCGasParameter::Instance().getGasDensity();
83// - We can query by key (using classname + parameter name) from the global registry:
84// - ConfigurableParameter::getValueAs<double>("TPCGas", "mGasDensity");
85//
86// We can modify the parameters via the global registry together with an automatic syncing
87// of the underlying C++ object:
88// - ConfigurableParameter::setValue("TPCGas.mGasDensity", "0.5");
89//
90// - TPCGasParameter::Instance().getGasParameter() will now return 0.5;
91//
92// This feature allows to easily modify parameters at run-time via a textual representation
93// (for example by giving strings on the command line)
94//
95// The collection of all parameter keys and values can be stored to a human/machine readable
96// file
97// - ConfigurableParameter::writeJSON("thisconfiguration.json")
98
100 std::vector<std::pair<std::string, int>> vvalues;
101
102 bool isLegal(const std::string& value) const
103 {
104 for (auto& v : vvalues) {
105 if (v.first == value) {
106 return true;
107 }
108 }
109 return false;
110 }
111
112 bool isLegal(int value) const
113 {
114 for (auto& v : vvalues) {
115 if (v.second == value) {
116 return true;
117 }
118 }
119 return false;
120 }
121
122 std::string toString() const;
123 int getIntValue(const std::string& value) const;
124};
125
127{
128 public:
129 void add(const std::string& key, const TDataMember* dm);
130
131 bool contains(const std::string& key) const
132 {
133 return entries.count(key) > 0;
134 }
135
136 std::string toString() const;
137
138 const EnumLegalValues* operator[](const std::string& key) const
139 {
140 auto iter = entries.find(key);
141 return iter != entries.end() ? &iter->second : nullptr;
142 }
143
144 private:
145 std::unordered_map<std::string, EnumLegalValues> entries;
146};
147
148template <typename T>
149concept Container = !std::is_same_v<std::remove_cvref_t<T>, std::string> && requires(T t) {
150 typename T::value_type;
151 typename T::iterator;
152 { t.begin() } -> std::same_as<typename T::iterator>;
153 { t.end() } -> std::same_as<typename T::iterator>;
154};
155
156template <typename T>
157concept MapLike = Container<T> && requires {
158 typename T::key_type;
159 typename T::mapped_type;
160};
161
162template <typename T>
164
165template <typename>
166inline constexpr bool AlwaysFalse = false;
167
169{
170 public:
171 template <typename T>
172 static T parse(const std::string& str)
173 {
174 if constexpr (MapLike<T>) {
175 return parseMap<T>(str);
176 } else if constexpr (Container<T>) {
177 // Covers vector/list/deque as well as set/unordered_set: parseSequence
178 // inserts at end(), which both sequence and associative-set containers
179 // accept. (Any non-map Container is a SequenceContainer, so the previous
180 // separate parseSet branch was unreachable and re-parsed into a temporary
181 // vector first.)
182 return parseSequence<T>(str);
183 } else {
184 return parseScalar<T>(str);
185 }
186 }
187
188 static std::string trim(const std::string& str)
189 {
190 auto start = str.find_first_not_of(" \t\n\r\f\v");
191 if (start == std::string::npos) {
192 return "";
193 }
194 auto end = str.find_last_not_of(" \t\n\r\f\v");
195 return str.substr(start, end - start + 1);
196 }
197
198 private:
199 // Parse sequence and set containers (vector, list, deque, set, unordered_set)
200 template <SequenceContainer SequenceT>
201 static SequenceT parseSequence(const std::string& str)
202 {
203 SequenceT result;
204 using ValueType = typename SequenceT::value_type;
205 std::string cleaned = str;
206 if (!cleaned.empty() && cleaned.front() == '[' && cleaned.back() == ']') { // removed brackets [1,2,3] -> 1,2,3
207 cleaned = cleaned.substr(1, cleaned.length() - 2);
208 }
209 if (cleaned.empty() || cleaned == "{}") { // nothing to do
210 return result;
211 }
212 if constexpr (Container<ValueType>) {
213 static_assert(AlwaysFalse<ValueType>, "Nested containers are not supported as configurable parameters");
214 }
215 auto tokens = split(cleaned, ',');
216 for (const auto& token : tokens) {
217 std::string trimmed = trim(token);
218 result.insert(result.end(), parseScalar<ValueType>(trimmed));
219 }
220 return result;
221 }
222
223 // Parse map, unordered_map, multimap
224 template <MapLike MapT>
225 static MapT parseMap(const std::string& str)
226 {
227 MapT result;
228 using KeyType = typename MapT::key_type;
229 using ValueType = typename MapT::mapped_type;
230 std::string cleaned = str;
231 if (!cleaned.empty() && cleaned.front() == '{' && cleaned.back() == '}') { // stip braces {a:1,b:2} -> a:1,b:2
232 cleaned = cleaned.substr(1, cleaned.length() - 2);
233 }
234 if (cleaned.empty()) { // nothing to do
235 return result;
236 }
237 if constexpr (Container<KeyType> || Container<ValueType>) {
238 static_assert(AlwaysFalse<MapT>, "Nested containers are not supported as configurable parameters");
239 }
240 auto pairs = split(cleaned, ',');
241 for (const auto& pair_str : pairs) {
242 auto kv = split(pair_str, ':');
243 if (kv.size() != 2) {
244 throw std::runtime_error("Invalid map syntax: " + pair_str + ". Expected 'key:value' format, got ");
245 }
246 KeyType key = parseScalar<KeyType>(trim(kv[0]));
247 result[key] = parseScalar<ValueType>(trim(kv[1]));
248 }
249 return result;
250 }
251
252 // Parse scalar types
253 template <typename T>
254 static T parseScalar(const std::string& str)
255 {
256 if constexpr (std::is_same_v<T, std::string>) {
257 return str;
258 } else if constexpr (std::is_same_v<T, bool>) {
259 std::string lower = str;
260 std::transform(lower.begin(), lower.end(), lower.begin(), [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
261 if (lower == "true" || lower == "1") {
262 return true;
263 }
264 if (lower == "false" || lower == "0") {
265 return false;
266 }
267 throw std::runtime_error("Invalid boolean value: " + str);
268 } else if constexpr (std::is_same_v<T, char> || std::is_same_v<T, signed char>) {
269 size_t pos = 0;
270 long long value = std::stoll(str, &pos);
271 if (pos != str.size()) {
272 throw std::runtime_error("Failed to parse '" + str + "' as char type");
273 }
274 if (value < std::numeric_limits<T>::min() || value > std::numeric_limits<T>::max()) {
275 throw std::runtime_error("Value out of range for char type: " + str);
276 }
277 return static_cast<T>(value);
278 } else if constexpr (std::is_same_v<T, unsigned char>) {
279 size_t pos = 0;
280 unsigned long long value = std::stoull(str, &pos);
281 if (pos != str.size()) {
282 throw std::runtime_error("Failed to parse '" + str + "' as unsigned char type");
283 }
284 if (value > std::numeric_limits<T>::max()) {
285 throw std::runtime_error("Value out of range for unsigned char type: " + str);
286 }
287 return static_cast<T>(value);
288 } else if constexpr (std::is_integral_v<T> && std::is_unsigned_v<T>) {
289 if (!str.empty() && str.front() == '-') {
290 throw std::runtime_error("Value out of range for unsigned integer type: " + str);
291 }
292 size_t pos = 0;
293 unsigned long long value = std::stoull(str, &pos);
294 if (pos != str.size() || value > std::numeric_limits<T>::max()) {
295 throw std::runtime_error("Failed to parse '" + str + "' as unsigned integer type");
296 }
297 return static_cast<T>(value);
298 } else if constexpr (std::is_integral_v<T>) {
299 size_t pos = 0;
300 long long value = std::stoll(str, &pos);
301 if (pos != str.size() || value < std::numeric_limits<T>::min() || value > std::numeric_limits<T>::max()) {
302 throw std::runtime_error("Failed to parse '" + str + "' as signed integer type");
303 }
304 return static_cast<T>(value);
305 } else if constexpr (std::is_floating_point_v<T>) {
306 size_t pos = 0;
307 long double value = std::stold(str, &pos);
308 if (pos != str.size()) {
309 throw std::runtime_error("Failed to parse '" + str + "' as floating point type");
310 }
311 return static_cast<T>(value);
312 } else {
313 std::istringstream iss(str);
314 T value;
315 iss >> value;
316 iss >> std::ws;
317 if (iss.fail() || !iss.eof()) {
318 throw std::runtime_error("Failed to parse '" + str + "' as " + typeid(T).name());
319 }
320 return value;
321 }
322 }
323
324 // Split respecting nested brackets and braces
325 static std::vector<std::string> split(const std::string& str, char delimiter)
326 {
327 std::vector<std::string> tokens;
328 std::string current;
329 int bracket_depth = 0;
330 int brace_depth = 0;
331 for (char c : str) {
332 if (c == '[') {
333 bracket_depth++;
334 } else if (c == ']') {
335 bracket_depth--;
336 } else if (c == '{') {
337 brace_depth++;
338 } else if (c == '}') {
339 brace_depth--;
340 } else if (c == delimiter && bracket_depth == 0 && brace_depth == 0) {
341 // Keep empty fields: a stray delimiter (e.g. "[1,,3]" or "key:") must
342 // surface as a parse error downstream rather than silently dropping an
343 // element. The empty-container case ("[]"/"{}") is handled by the
344 // callers before split() is ever reached.
345 tokens.push_back(current);
346 current.clear();
347 continue;
348 }
349 current += c;
350 }
351 tokens.push_back(current);
352 return tokens;
353 }
354};
355
357{
358 public:
360 kCODE /* from default code initialization */,
361 kCCDB /* overwritten from CCDB */,
362 kRT /* changed during runtime via API call setValue (for example command line) */
363 /* can add more modes here */
364 };
365
367 Changed, // param was successfully changed
368 Unchanged, // param was not changed: new value is the same as previous
369 Failed // failed to update param
370 };
371
372 static std::string toString(EParamProvenance p)
373 {
374 static std::array<std::string, 3> names = {"CODE", "CCDB", "RT"};
375 return names[(int)p];
376 }
377
378 // get the name of the configurable Parameter
379 virtual std::string getName() const = 0;
380
381 // print the current keys and values to screen (optionally with provenance information)
382 virtual void printKeyValues(bool showprov = true, bool useLogger = false, bool withPadding = false, bool showHash = false) const = 0;
383
384 // get a single size_t hash_value of this parameter (can be used as a checksum to see
385 // if object changed or different)
386 virtual size_t getHash() const = 0;
387
388 // return the provenance of the member key
389 virtual EParamProvenance getMemberProvenance(const std::string& key) const = 0;
390
391 static EParamProvenance getProvenance(const std::string& key);
392
393 static void printAllRegisteredParamNames();
394 static void printAllKeyValuePairs(bool useLogger = false);
395
396 static const std::string& getOutputDir() { return sOutputDir; }
397
398 static void setOutputDir(const std::string& d) { sOutputDir = d; }
399
400 static bool configFileExists(std::string const& filepath);
401
402 // writes a human readable JSON file of all parameters
403 static void writeJSON(std::string const& filename, std::string const& keyOnly = "");
404 // writes a human readable INI file of all parameters
405 static void writeINI(std::string const& filename, std::string const& keyOnly = "");
406
407 // writes a human readable INI or JSON file depending on the extension
408 static void write(std::string const& filename, std::string const& keyOnly = "");
409
410 static std::string asJSON(std::string const& keyOnly = "");
411
412 // can be used instead of using API on concrete child classes
413 template <typename T>
414 static T getValueAs(std::string key)
415 {
416 return [](auto* tree, const std::string& key) -> T {
417 if (!sIsFullyInitialized) {
418 initialize();
419 }
420 return tree->template get<T>(key);
421 }(sPtree, key);
422 }
423
424 template <typename T>
425 static void setValue(std::string const& mainkey, std::string const& subkey, T x)
426 {
427 if (!sIsFullyInitialized) {
428 initialize();
429 }
430 return [&subkey, &x, &mainkey](auto* tree) -> void {
431 assert(tree);
432 try {
433 auto key = mainkey + "." + subkey;
434 if (tree->template get_optional<std::string>(key).is_initialized()) {
435 tree->put(key, x);
436 auto changed = updateThroughStorageMap(mainkey, subkey, typeid(T), (void*)&x);
437 if (changed != EParamUpdateStatus::Failed) {
438 sValueProvenanceMap->find(key)->second = kRT; // set to runtime
439 }
440 }
441 } catch (std::exception const& e) {
442 std::cerr << "Error in setValue (T) " << e.what() << "\n";
443 }
444 }(sPtree);
445 }
446
447 static void setProvenance(std::string const& mainkey, std::string const& subkey, EParamProvenance p)
448 {
449 if (!sIsFullyInitialized) {
450 std::cerr << "setProvenance was called on non-initialized ConfigurableParam\n";
451 return;
452 }
453 try {
454 auto key = mainkey + "." + subkey;
455 auto keyProv = sValueProvenanceMap->find(key);
456 if (keyProv != sValueProvenanceMap->end()) {
457 keyProv->second = p;
458 }
459 } catch (std::exception const& e) {
460 std::cerr << "Error in setProvenance (T) " << e.what() << "\n";
461 }
462 }
463
464 // specialized for std::string
465 // which means that the type will be converted internally
466 static void setValue(std::string const& key, std::string const& valuestring);
467 static void setEnumValue(const std::string&, const std::string&);
468 static void setArrayValue(const std::string&, const std::string&);
469 static void setContainerValue(const std::string&, const std::string&);
470 static bool isRegisteredContainerType(const std::string& typeName);
471 static void registerContainerType(const std::string& key, const std::string& typeName);
472 static std::string getRegisteredContainerType(const std::string& key);
473 static bool assignRegisteredContainer(const std::string& typeName, void* target, const void* source);
474 static bool areRegisteredContainersEqual(const std::string& typeName, const void* lhs, const void* rhs);
475 static std::string registeredContainerAsString(const std::string& typeName, const void* source);
476
477 // update the storagemap from a vector of key/value pairs, calling setValue for each pair
478 static void setValues(std::vector<std::pair<std::string, std::string>> const& keyValues);
479
480 // initializes the parameter database
481 static void initialize();
482
483 // create CCDB snapshot
484 static void toCCDB(std::string filename);
485 // load from (CCDB) snapshot
486 static void fromCCDB(std::string filename);
487
488 // allows to provide a string of key-values from which to update
489 // (certain) key-values
490 // propagates changes down to each registered configuration
491 // might be useful to get stuff from the command line
492 static void updateFromString(std::string const&);
493
494 // provide a path to a configuration file with ConfigurableParam key/values
495 // If nonempty comma-separated paramsList is provided, only those params will
496 // be updated, absence of data for any of requested params will lead to fatal
497 static void updateFromFile(std::string const&, std::string const& paramsList = "", bool unchangedOnly = false);
498
499 // update from a JSON string with the same filtering semantics as updateFromFile
500 static void updateFromJSONString(std::string const&, std::string const& paramsList = "", bool unchangedOnly = false);
501
502 // interface for use from the CCDB API; allows to sync objects read from CCDB with the information
503 // stored in the registry; modifies given object as well as registry
504 virtual void syncCCDBandRegistry(void* obj) = 0;
505
506 protected:
507 // constructor is doing nothing else but
508 // registering the concrete parameters
510
511 friend std::ostream& operator<<(std::ostream& out, const ConfigurableParam& me);
512
513 static void initPropertyTree();
514 static EParamUpdateStatus updateThroughStorageMap(std::string, std::string, std::type_info const&, void*);
515 static EParamUpdateStatus updateThroughStorageMapWithConversion(std::string const&, std::string const&);
516
517 virtual ~ConfigurableParam() = default;
518
519 // fill property tree with the key-values from the sub-classes
520 virtual void putKeyValues(boost::property_tree::ptree*) = 0;
521 virtual void output(std::ostream& out) const = 0;
522
523 virtual void serializeTo(TFile*) const = 0;
524 virtual void initFrom(TFile*) = 0;
525
526 // static map keeping, for each configuration key, its memory location and type
527 // (internal use to easily sync updates, this is ok since parameter classes are singletons)
528 static std::map<std::string, std::pair<std::type_info const&, void*>>* sKeyToStorageMap;
529
530 // keep track of provenance of parameters and values
531 static std::map<std::string, ConfigurableParam::EParamProvenance>* sValueProvenanceMap;
532
533 // A registry of enum names and their allowed values
534 // (stored as a vector of pairs <enumValueLabel, enumValueInt>)
536
537 static std::string sOutputDir;
538
539 void setRegisterMode(bool b) { sRegisterMode = b; }
540 bool isInitialized() const { return sIsFullyInitialized; }
541
542 // friend class o2::ccdb::CcdbApi;
543 private:
544 // static registry for implementations of this type
545 static std::vector<ConfigurableParam*>* sRegisteredParamClasses;
546 // static property tree (stocking all key - value pairs from instances of type ConfigurableParam)
547 static boost::property_tree::ptree* sPtree;
548 static bool sIsFullyInitialized;
549 static bool sRegisterMode;
550};
551
552} // end namespace conf
553} // end namespace o2
554
555// a helper macro for boilerplate code in parameter classes
556#define O2ParamDef(classname, key) \
557 public: \
558 classname(TRootIOCtor*) {} \
559 classname(classname const&) = delete; \
560 \
561 private: \
562 static constexpr char const* const sKey = key; \
563 static classname sInstance; \
564 classname() = default; \
565 template <typename T> \
566 friend class o2::conf::ConfigurableParamHelper; \
567 template <typename T, typename P> \
568 friend class o2::conf::ConfigurableParamPromoter;
569
570// a helper macro to implement necessary symbols in source
571#define O2ParamImpl(classname) classname classname::sInstance;
572
573#endif /* COMMON_SIMCONFIG_INCLUDE_SIMCONFIG_CONFIGURABLEPARAM_H_ */
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 First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char e
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 First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char Directory with events to Events directory is and not inside events d
double lower[3]
uint16_t pos
Definition RawData.h:3
uint32_t c
Definition RawData.h:2
StringRef key
friend std::ostream & operator<<(std::ostream &out, const ConfigurableParam &me)
virtual ~ConfigurableParam()=default
virtual void printKeyValues(bool showprov=true, bool useLogger=false, bool withPadding=false, bool showHash=false) const =0
static EParamUpdateStatus updateThroughStorageMapWithConversion(std::string const &, std::string const &)
static std::string registeredContainerAsString(const std::string &typeName, const void *source)
virtual void serializeTo(TFile *) const =0
virtual std::string getName() const =0
static void setEnumValue(const std::string &, const std::string &)
static void writeINI(std::string const &filename, std::string const &keyOnly="")
static void setValues(std::vector< std::pair< std::string, std::string > > const &keyValues)
static bool configFileExists(std::string const &filepath)
virtual void putKeyValues(boost::property_tree::ptree *)=0
static std::map< std::string, std::pair< std::type_info const &, void * > > * sKeyToStorageMap
static bool areRegisteredContainersEqual(const std::string &typeName, const void *lhs, const void *rhs)
static void setProvenance(std::string const &mainkey, std::string const &subkey, EParamProvenance p)
static void registerContainerType(const std::string &key, const std::string &typeName)
static std::string asJSON(std::string const &keyOnly="")
static void updateFromFile(std::string const &, std::string const &paramsList="", bool unchangedOnly=false)
static void write(std::string const &filename, std::string const &keyOnly="")
static bool isRegisteredContainerType(const std::string &typeName)
static T getValueAs(std::string key)
static bool assignRegisteredContainer(const std::string &typeName, void *target, const void *source)
virtual size_t getHash() const =0
virtual void initFrom(TFile *)=0
virtual EParamProvenance getMemberProvenance(const std::string &key) const =0
static void setArrayValue(const std::string &, const std::string &)
static void setValue(std::string const &mainkey, std::string const &subkey, T x)
static std::map< std::string, ConfigurableParam::EParamProvenance > * sValueProvenanceMap
static EParamProvenance getProvenance(const std::string &key)
static const std::string & getOutputDir()
static void printAllKeyValuePairs(bool useLogger=false)
static void toCCDB(std::string filename)
static void writeJSON(std::string const &filename, std::string const &keyOnly="")
static void setOutputDir(const std::string &d)
static std::string toString(EParamProvenance p)
static EParamUpdateStatus updateThroughStorageMap(std::string, std::string, std::type_info const &, void *)
static void setContainerValue(const std::string &, const std::string &)
static void updateFromJSONString(std::string const &, std::string const &paramsList="", bool unchangedOnly=false)
static EnumRegistry * sEnumRegistry
virtual void output(std::ostream &out) const =0
static std::string getRegisteredContainerType(const std::string &key)
virtual void syncCCDBandRegistry(void *obj)=0
static void fromCCDB(std::string filename)
static void updateFromString(std::string const &)
static T parse(const std::string &str)
static std::string trim(const std::string &str)
void add(const std::string &key, const TDataMember *dm)
std::string toString() const
bool contains(const std::string &key) const
const EnumLegalValues * operator[](const std::string &key) const
GLint GLenum GLint x
Definition glcorearb.h:403
GLuint64EXT * result
Definition glcorearb.h:5662
GLuint GLuint end
Definition glcorearb.h:469
const GLdouble * v
Definition glcorearb.h:832
GLuint const GLchar * name
Definition glcorearb.h:781
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLsizei GLsizei GLchar * source
Definition glcorearb.h:798
GLsizei const GLfloat * value
Definition glcorearb.h:819
constexpr bool AlwaysFalse
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string filename()
bool isLegal(int value) const
bool isLegal(const std::string &value) const
std::vector< std::pair< std::string, int > > vvalues
int getIntValue(const std::string &value) const
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))
const std::string str