Project
Loading...
Searching...
No Matches
ConfigurableParam.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
12// first version 8/2018, Sandro Wenzel
13
18#define BOOST_BIND_GLOBAL_PLACEHOLDERS
19#include <boost/algorithm/string/predicate.hpp>
20#include <boost/property_tree/ptree.hpp>
21#include <boost/property_tree/ini_parser.hpp>
22#include <boost/property_tree/json_parser.hpp>
23#include <boost/tokenizer.hpp>
24#include <boost/lexical_cast.hpp>
25#include <algorithm>
26#include <array>
27#include <limits>
28#ifdef NDEBUG
29#undef NDEBUG
30#endif
31#include <cassert>
32#include <iostream>
33#include <string>
34#include <fairlogger/Logger.h>
35#include <typeinfo>
36#include "TDataMember.h"
37#include "TDataType.h"
38#include "TFile.h"
39#include "TEnum.h"
40#include "TEnumConstant.h"
41#include <filesystem>
42
43namespace o2
44{
45namespace conf
46{
47std::vector<ConfigurableParam*>* ConfigurableParam::sRegisteredParamClasses = nullptr;
48boost::property_tree::ptree* ConfigurableParam::sPtree = nullptr;
49std::map<std::string, std::pair<std::type_info const&, void*>>* ConfigurableParam::sKeyToStorageMap = nullptr;
50std::map<std::string, ConfigurableParam::EParamProvenance>* ConfigurableParam::sValueProvenanceMap = nullptr;
51std::string ConfigurableParam::sOutputDir = "";
52EnumRegistry* ConfigurableParam::sEnumRegistry = nullptr;
53
54bool ConfigurableParam::sIsFullyInitialized = false;
55bool ConfigurableParam::sRegisterMode = true;
56
57// ------------------------------------------------------------------
58
59std::ostream& operator<<(std::ostream& out, ConfigurableParam const& param)
60{
61 param.output(out);
62 return out;
63}
64
65// Does the given key exist in the boost property tree?
66bool keyInTree(boost::property_tree::ptree* pt, const std::string& key)
67{
68 if (key.size() == 0 || pt == nullptr) {
69 return false;
70 }
71 bool reply = false;
72 try {
73 reply = pt->get_optional<std::string>(key).is_initialized();
74 } catch (std::exception const& e) {
75 LOG(error) << "ConfigurableParam: Exception when checking for key " << key << " : " << e.what();
76 }
77 return reply;
78}
79
80// ------------------------------------------------------------------
81
82void EnumRegistry::add(const std::string& key, const TDataMember* dm)
83{
84 if (!dm->IsEnum() || this->contains(key)) {
85 return;
86 }
87
88 EnumLegalValues legalVals;
89 auto enumtype = TEnum::GetEnum(dm->GetTypeName());
90 assert(enumtype != nullptr);
91 auto constantlist = enumtype->GetConstants();
92 assert(constantlist != nullptr);
93 if (enumtype) {
94 for (int i = 0; i < constantlist->GetEntries(); ++i) {
95 auto e = (TEnumConstant*)(constantlist->At(i));
96 std::pair<std::string, int> val(e->GetName(), (int)e->GetValue());
97 legalVals.vvalues.push_back(val);
98 }
99 }
100
101 // The other method of fetching enum constants from TDataMember->GetOptions
102 // stopped working with ROOT6-18-0:
103
104 // auto opts = dm->GetOptions();
105 // for (int i = 0; i < opts->GetEntries(); ++i) {
106 // auto opt = (TOptionListItem*)opts->At(i);
107 // std::pair<std::string, int> val(opt->fOptName, (int)opt->fValue);
108 // legalVals.vvalues.push_back(val);
109 // LOG(info) << "Adding legal value " << val.first << " " << val.second;
110 // }
111
112 auto entry = std::pair<std::string, EnumLegalValues>(key, legalVals);
113 this->entries.insert(entry);
114}
115
116std::string EnumRegistry::toString() const
117{
118 std::string out = "";
119 for (auto& entry : entries) {
120 out.append(entry.first + " => ");
121 out.append(entry.second.toString());
122 out.append("\n");
123 }
124
125 return out;
126}
127
128std::string EnumLegalValues::toString() const
129{
130 std::string out = "";
131
132 for (auto& value : vvalues) {
133 out.append("[");
134 out.append(value.first);
135 out.append(" | ");
136 out.append(std::to_string(value.second));
137 out.append("] ");
138 }
139
140 return out;
141}
142
143// getIntValue takes a string value which is supposed to be
144// a legal enum value and tries to cast it to an int.
145// If it succeeds, and if the int value is legal, it is returned.
146// If it fails, and if it is a legal string enum value, we look up
147// and return the equivalent int value. In any case, if it is not
148// a legal value we return -1 to indicate this fact.
149int EnumLegalValues::getIntValue(const std::string& value) const
150{
151 try {
152 int val = boost::lexical_cast<int>(value);
153 if (isLegal(val)) {
154 return val;
155 }
156 } catch (const boost::bad_lexical_cast& e) {
157 if (isLegal(value)) {
158 for (auto& pair : vvalues) {
159 if (pair.first == value) {
160 return pair.second;
161 }
162 }
163 }
164 }
165
166 return -1;
167}
168
169// -----------------------------------------------------------------
170
171void ConfigurableParam::writeINI(std::string const& filename, std::string const& keyOnly)
172{
173 if (sOutputDir == "/dev/null") {
174 LOG(debug) << "ignoring writing of ini file " << filename;
175 return;
176 }
178 initPropertyTree(); // update the boost tree before writing
179 if (!keyOnly.empty()) { // write ini for selected key only
180 try {
181 boost::property_tree::ptree kTree;
182 kTree.add_child(keyOnly, sPtree->get_child(keyOnly));
183 boost::property_tree::write_ini(outfilename, kTree);
184 } catch (const boost::property_tree::ptree_bad_path& err) {
185 LOG(fatal) << "non-existing key " << keyOnly << " provided to writeINI";
186 }
187 } else {
188 boost::property_tree::write_ini(outfilename, *sPtree);
189 }
190}
191
192// ------------------------------------------------------------------
193
194bool ConfigurableParam::configFileExists(std::string const& filepath)
195{
196 return std::filesystem::exists(o2::utils::Str::concat_string(ConfigurableParamReaders::getInputDir(), filepath));
197}
198
199// ------------------------------------------------------------------
200
201void ConfigurableParam::setValue(std::string const& key, std::string const& valuestring)
202{
203 if (!sIsFullyInitialized) {
204 initialize();
205 }
206 assert(sPtree);
207 try {
208 if (sPtree->get_optional<std::string>(key).is_initialized()) {
209 sPtree->put(key, valuestring);
210 auto changed = updateThroughStorageMapWithConversion(key, valuestring);
211 if (changed != EParamUpdateStatus::Failed) {
212 sValueProvenanceMap->find(key)->second = kRT; // set to runtime
213 }
214 }
215 } catch (std::exception const& e) {
216 std::cerr << "Error in setValue (string) " << e.what() << "\n";
217 }
218}
219
220// ------------------------------------------------------------------
221
222void ConfigurableParam::writeJSON(std::string const& filename, std::string const& keyOnly)
223{
224 if (sOutputDir == "/dev/null") {
225 LOG(info) << "ignoring writing of json file " << filename;
226 return;
227 }
228 initPropertyTree(); // update the boost tree before writing
230 if (!keyOnly.empty()) { // write ini for selected key only
231 try {
232 boost::property_tree::ptree kTree;
233 kTree.add_child(keyOnly, sPtree->get_child(keyOnly));
234 boost::property_tree::write_json(outfilename, kTree);
235 } catch (const boost::property_tree::ptree_bad_path& err) {
236 LOG(fatal) << "non-existing key " << keyOnly << " provided to writeJSON";
237 }
238 } else {
239 boost::property_tree::write_json(outfilename, *sPtree);
240 }
241}
242
243// ------------------------------------------------------------------
244
246{
247 sPtree->clear();
248 for (auto p : *sRegisteredParamClasses) {
249 p->putKeyValues(sPtree);
250 }
251}
252
253// ------------------------------------------------------------------
254
256{
257 if (!sIsFullyInitialized) {
258 initialize();
259 }
260 std::cout << "####\n";
261 for (auto p : *sRegisteredParamClasses) {
262 p->printKeyValues(true, useLogger);
263 }
264 std::cout << "----\n";
265}
266
267// ------------------------------------------------------------------
268
270{
271 if (!sIsFullyInitialized) {
272 initialize();
273 }
274 auto iter = sValueProvenanceMap->find(key);
275 if (iter == sValueProvenanceMap->end()) {
276 throw std::runtime_error(fmt::format("provenace of unknown {:s} parameter is requested", key));
278 return iter->second;
279}
280
281// ------------------------------------------------------------------
282
283// evidently this could be a local file or an OCDB server
284// ... we need to generalize this ... but ok for demonstration purposes
286{
287 if (!sIsFullyInitialized) {
288 initialize();
289 }
290 TFile file(filename.c_str(), "RECREATE");
291 for (auto p : *sRegisteredParamClasses) {
292 p->serializeTo(&file);
293 }
294 file.Close();
295}
296
297// ------------------------------------------------------------------
298
300{
301 if (!sIsFullyInitialized) {
302 initialize();
303 }
304 TFile file(filename.c_str(), "READ");
305 for (auto p : *sRegisteredParamClasses) {
306 p->initFrom(&file);
307 }
308 file.Close();
309}
310
311// ------------------------------------------------------------------
312
314{
315 if (sRegisteredParamClasses == nullptr) {
316 sRegisteredParamClasses = new std::vector<ConfigurableParam*>;
317 }
318 if (sPtree == nullptr) {
319 sPtree = new boost::property_tree::ptree;
320 }
321 if (sKeyToStorageMap == nullptr) {
322 sKeyToStorageMap = new std::map<std::string, std::pair<std::type_info const&, void*>>;
323 }
324 if (sValueProvenanceMap == nullptr) {
325 sValueProvenanceMap = new std::map<std::string, ConfigurableParam::EParamProvenance>;
326 }
327
328 if (sEnumRegistry == nullptr) {
330 }
331
332 if (sRegisterMode == true) {
333 sRegisteredParamClasses->push_back(this);
334 }
335}
336
337// ------------------------------------------------------------------
338
340{
342 // initialize the provenance map
343 // initially the values come from code
344 for (auto& key : *sKeyToStorageMap) {
345 sValueProvenanceMap->insert(std::pair<std::string, ConfigurableParam::EParamProvenance>(key.first, kCODE));
346 }
347 sIsFullyInitialized = true;
348}
349
350// ------------------------------------------------------------------
351
353{
354 for (auto p : *sRegisteredParamClasses) {
355 std::cout << p->getName() << "\n";
356 }
357}
358
359// ------------------------------------------------------------------
360
361// Update the storage map of params from the given configuration file.
362// It can be in JSON or INI format.
363// If nonempty comma-separated paramsList is provided, only those params will
364// be updated, absence of data for any of requested params will lead to fatal
365// If unchangedOnly is true, then only those parameters whose provenance is kCODE will be updated
366// (to allow prefernce of run-time settings)
367void ConfigurableParam::updateFromFile(std::string const& configFile, std::string const& paramsList, bool unchangedOnly)
368{
369 if (!sIsFullyInitialized) {
370 initialize();
371 }
372
373 auto cfgfile = o2::utils::Str::trim_copy(configFile);
374
375 if (cfgfile.length() == 0) {
376 return;
377 }
378
379 boost::property_tree::ptree pt = ConfigurableParamReaders::readConfigFile(cfgfile);
380
381 std::vector<std::pair<std::string, std::string>> keyValPairs;
382 auto request = o2::utils::Str::tokenize(paramsList, ',', true);
383 std::unordered_map<std::string, int> requestMap;
384 for (const auto& par : request) {
385 if (!par.empty()) {
386 requestMap[par] = 0;
387 }
388 }
389
390 try {
391 for (auto& section : pt) {
392 std::string mainKey = section.first;
393 if (requestMap.size()) {
394 if (requestMap.find(mainKey) == requestMap.end()) {
395 continue; // if something was requested, ignore everything else
396 } else {
397 requestMap[mainKey] = 1;
398 }
399 }
400 for (auto& subKey : section.second) {
401 auto name = subKey.first;
402 auto value = subKey.second.get_value<std::string>();
403 std::string key = mainKey + "." + name;
404 if (!unchangedOnly || getProvenance(key) == kCODE) {
405 std::pair<std::string, std::string> pair = std::make_pair(key, o2::utils::Str::trim_copy(value));
406 keyValPairs.push_back(pair);
407 }
408 }
409 }
410 } catch (std::exception const& error) {
411 LOG(error) << "Error while updating params " << error.what();
412 } catch (...) {
413 LOG(error) << "Unknown while updating params ";
414 }
415
416 // make sure all requested params were retrieved
417 for (const auto& req : requestMap) {
418 if (req.second == 0) {
419 throw std::runtime_error(fmt::format("Param {:s} was not found in {:s}", req.first, configFile));
420 }
421 }
422
423 try {
424 setValues(keyValPairs);
425 } catch (std::exception const& error) {
426 LOG(error) << "Error while setting values " << error.what();
427 }
428}
429
430// ------------------------------------------------------------------
431// ------------------------------------------------------------------
432
433void ConfigurableParam::updateFromString(std::string const& configString)
434{
435 if (!sIsFullyInitialized) {
436 initialize();
437 }
438
439 auto cfgStr = o2::utils::Str::trim_copy(configString);
440 if (cfgStr.length() == 0) {
441 return;
442 }
443
444 // Take a vector of strings with elements of form a=b, and
445 // return a vector of pairs with each pair of form <a, b>
446 auto toKeyValPairs = [](std::vector<std::string>& tokens) {
447 std::vector<std::pair<std::string, std::string>> pairs;
448
449 for (auto& token : tokens) {
450 auto s = token.find('=');
451 if (s == 0 || s == std::string::npos || s == token.size() - 1) {
452 LOG(fatal) << "Illegal command-line key/value string: " << token;
453 continue;
454 }
455 pairs.emplace_back(token.substr(0, s), token.substr(s + 1, token.size()));
456 }
457
458 return pairs;
459 };
460
461 // Simple check that the string starts/ends with an open square bracket
462 // Find the maximum index of a given key with array value.
463 // We store string keys for arrays as a[0]...a[size_of_array]
464 /*
465 auto maxIndex = [](std::string baseName) {
466 bool isFound = true;
467 int index = -1;
468 do {
469 index++;
470 std::string key = baseName + "[" + std::to_string(index) + "]";
471 isFound = keyInTree(sPtree, key);
472 } while (isFound);
473
474 return index;
475 };
476*/
477
478 // ---- end of helper functions --------------------
479
480 // Command-line string is a ;-separated list of key=value params
481 auto params = o2::utils::Str::tokenize(configString, ';', true);
482
483 // Now split each key=value string into its std::pair<key, value> parts
484 auto keyValues = toKeyValPairs(params);
485
486 setValues(keyValues);
487
488 const auto& kv = o2::conf::KeyValParam::Instance();
489 if (getProvenance("keyval.input_dir") != kCODE) {
491 }
492 if (getProvenance("keyval.output_dir") != kCODE) {
493 if (kv.output_dir == "/dev/null") {
494 sOutputDir = kv.output_dir;
495 } else {
497 }
498 }
499}
500
501// setValues takes a vector of pairs where each pair is a key and value
502// to be set in the storage map
503void ConfigurableParam::setValues(std::vector<std::pair<std::string, std::string>> const& keyValues)
504{
505 auto isArray = [](std::string& el) {
506 return el.size() > 0 && (el.at(0) == '[') && (el.at(el.size() - 1) == ']');
507 };
508
509 bool nonFatal = getenv("ALICEO2_CONFIGURABLEPARAM_WRONGKEYISNONFATAL") != nullptr;
510
511 // Take a vector of param key/value pairs
512 // and update the storage map for each of them by calling setValue.
513 // 1. For string/scalar types this is simple.
514 // 2. For array values we need to iterate over each array element
515 // and call setValue on the element, using an appropriately constructed key.
516 // 3. For enum types we check for the existence of the key in the enum registry
517 // and also confirm that the value is in the list of legal values
518 for (auto& keyValue : keyValues) {
519 std::string key = keyValue.first;
520 std::string value = o2::utils::Str::trim_copy(keyValue.second);
521
522 if (!keyInTree(sPtree, key)) {
523 if (nonFatal) {
524 LOG(warn) << "Ignoring non-existent ConfigurableParam key: " << key;
525 continue;
526 }
527 LOG(fatal) << "Inexistant ConfigurableParam key: " << key;
528 }
529
530 if (sEnumRegistry->contains(key)) {
532 } else if (isArray(value)) {
534 } else {
535 assert(sKeyToStorageMap->find(key) != sKeyToStorageMap->end());
536
537 // If the value is given as a boolean true|false, change to 1|0 int equivalent
538 if (value == "true") {
539 value = "1";
540 } else if (value == "false") {
541 value = "0";
542 }
543
544 // TODO: this will trap complex types like maps and structs.
545 // These need to be broken into their own cases, so that we only
546 // get strings and scalars here.
548 }
549 }
550}
551
552void ConfigurableParam::setArrayValue(const std::string& key, const std::string& value)
553{
554 // We remove the lead/trailing square bracket
555 // value.erase(0, 1).pop_back();
556 auto elems = o2::utils::Str::tokenize(value.substr(1, value.length() - 2), ',', true);
557
558 // TODO:
559 // 1. Should not assume each array element is a scalar/string. We may need to recurse.
560 // 2. Should not assume each array element - even if not complex - is correctly written. Validate.
561 // 3. Validation should include finding same types as in provided defaults.
562 for (int i = 0; i < elems.size(); ++i) {
563 std::string indexKey = key + "[" + std::to_string(i) + "]";
564 setValue(indexKey, elems[i]);
565 }
566}
567
568void ConfigurableParam::setEnumValue(const std::string& key, const std::string& value)
569{
570 int val = (*sEnumRegistry)[key]->getIntValue(value);
571 if (val == -1) {
572 LOG(fatal) << "Illegal value "
573 << value << " for enum " << key
574 << ". Legal string|int values:\n"
575 << (*sEnumRegistry)[key]->toString() << std::endl;
576 }
577
579}
580
581void unsupp() { std::cerr << "currently unsupported\n"; }
582
583template <typename T>
584bool isMemblockDifferent(void const* block1, void const* block2)
585{
586 // loop over thing in elements of bytes
587 for (int i = 0; i < sizeof(T) / sizeof(char); ++i) {
588 if (((char*)block1)[i] != ((char*)block2)[i]) {
589 return true;
590 }
591 }
592 return false;
593}
594
595// copies data from one place to other and returns
596// true of data was actually changed
597template <typename T>
598ConfigurableParam::EParamUpdateStatus Copy(void const* addr, void* targetaddr)
599{
600 if (isMemblockDifferent<T>(addr, targetaddr)) {
601 std::memcpy(targetaddr, addr, sizeof(T));
603 }
605}
606
607ConfigurableParam::EParamUpdateStatus ConfigurableParam::updateThroughStorageMap(std::string mainkey, std::string subkey, std::type_info const& tinfo,
608 void* addr)
609{
610 // check if key_exists
611 auto key = mainkey + "." + subkey;
612 auto iter = sKeyToStorageMap->find(key);
613 if (iter == sKeyToStorageMap->end()) {
614 LOG(warn) << "Cannot update parameter " << key << " not found";
616 }
617
618 // the type we need to convert to
619 int type = TDataType::GetType(tinfo);
620
621 // check that type matches
622 if (iter->second.first != tinfo) {
623 LOG(warn) << "Types do not match; cannot update value";
625 }
626
627 auto targetaddress = iter->second.second;
628 switch (type) {
629 case kChar_t: {
630 return Copy<char>(addr, targetaddress);
631 break;
632 }
633 case kUChar_t: {
634 return Copy<unsigned char>(addr, targetaddress);
635 break;
636 }
637 case kShort_t: {
638 return Copy<short>(addr, targetaddress);
639 break;
640 }
641 case kUShort_t: {
642 return Copy<unsigned short>(addr, targetaddress);
643 break;
644 }
645 case kInt_t: {
646 return Copy<int>(addr, targetaddress);
647 break;
648 }
649 case kUInt_t: {
650 return Copy<unsigned int>(addr, targetaddress);
651 break;
652 }
653 case kLong_t: {
654 return Copy<long>(addr, targetaddress);
655 break;
656 }
657 case kULong_t: {
658 return Copy<unsigned long>(addr, targetaddress);
659 break;
660 }
661 case kFloat_t: {
662 return Copy<float>(addr, targetaddress);
663 break;
664 }
665 case kDouble_t: {
666 return Copy<double>(addr, targetaddress);
667 break;
668 }
669 case kDouble32_t: {
670 return Copy<double>(addr, targetaddress);
671 break;
672 }
673 case kchar: {
674 unsupp();
675 break;
676 }
677 case kBool_t: {
678 return Copy<bool>(addr, targetaddress);
679 break;
680 }
681 case kLong64_t: {
682 return Copy<long long>(addr, targetaddress);
683 break;
684 }
685 case kULong64_t: {
686 return Copy<unsigned long long>(addr, targetaddress);
687 break;
688 }
689 case kOther_t: {
690 unsupp();
691 break;
692 }
693 case kNoType_t: {
694 unsupp();
695 break;
696 }
697 case kFloat16_t: {
698 unsupp();
699 break;
700 }
701 case kCounter: {
702 unsupp();
703 break;
704 }
705 case kCharStar: {
706 return Copy<char*>(addr, targetaddress);
707 break;
708 }
709 case kBits: {
710 unsupp();
711 break;
712 }
713 case kVoid_t: {
714 unsupp();
715 break;
716 }
717 case kDataTypeAliasUnsigned_t: {
718 unsupp();
719 break;
720 }
721 /*
722 case kDataTypeAliasSignedChar_t: {
723 unsupp();
724 break;
725 }
726 case kNumDataTypes: {
727 unsupp();
728 break;
729 }*/
730 default: {
731 unsupp();
732 break;
733 }
734 }
736}
737
738template <typename T>
739ConfigurableParam::EParamUpdateStatus ConvertAndCopy(std::string const& valuestring, void* targetaddr)
740{
741 auto addr = boost::lexical_cast<T>(valuestring);
742 if (isMemblockDifferent<T>(targetaddr, (void*)&addr)) {
743 std::memcpy(targetaddr, (void*)&addr, sizeof(T));
745 }
747}
748
749// special version for std::string
750template <>
751ConfigurableParam::EParamUpdateStatus ConvertAndCopy<std::string>(std::string const& valuestring, void* targetaddr)
752{
753 std::string& target = *((std::string*)targetaddr);
754 if (target.compare(valuestring) != 0) {
755 // the targetaddr is a std::string to which we can simply assign
756 // and all the magic will happen internally
757 target = valuestring;
759 }
761}
762// special version for char and unsigned char since we are interested in the numeric
763// meaning of char as an 8-bit integer (boost lexical cast is assigning the string as a character i// nterpretation
764template <>
765ConfigurableParam::EParamUpdateStatus ConvertAndCopy<char>(std::string const& valuestring, void* targetaddr)
766{
767 int intvalue = boost::lexical_cast<int>(valuestring);
768 if (intvalue > std::numeric_limits<char>::max() || intvalue < std::numeric_limits<char>::min()) {
769 LOG(error) << "Cannot assign " << valuestring << " to a char variable";
771 }
772 char addr = intvalue;
773 if (isMemblockDifferent<char>(targetaddr, (void*)&addr)) {
774 std::memcpy(targetaddr, (void*)&addr, sizeof(char));
776 }
778}
779
780template <>
781ConfigurableParam::EParamUpdateStatus ConvertAndCopy<unsigned char>(std::string const& valuestring, void* targetaddr)
782{
783 unsigned int intvalue = boost::lexical_cast<int>(valuestring);
784 if (intvalue > std::numeric_limits<unsigned char>::max() || intvalue < std::numeric_limits<unsigned char>::min()) {
785 LOG(error) << "Cannot assign " << valuestring << " to an unsigned char variable";
787 }
788 unsigned char addr = intvalue;
789 if (isMemblockDifferent<unsigned char>(targetaddr, (void*)&addr)) {
790 std::memcpy(targetaddr, (void*)&addr, sizeof(unsigned char));
792 }
794}
795
797{
798 // check if key_exists
799 auto iter = sKeyToStorageMap->find(key);
800 if (iter == sKeyToStorageMap->end()) {
801 LOG(warn) << "Cannot update parameter " << key << " (parameter not found) ";
803 }
804
805 auto targetaddress = iter->second.second;
806
807 // treat some special cases first:
808 // the type is actually a std::string
809 if (iter->second.first == typeid(std::string)) {
810 return ConvertAndCopy<std::string>(valuestring, targetaddress);
811 }
812
813 // the type (aka ROOT::EDataType which the type identification in the map) we need to convert to
814 int targettype = TDataType::GetType(iter->second.first);
815
816 switch (targettype) {
817 case kChar_t: {
818 return ConvertAndCopy<char>(valuestring, targetaddress);
819 break;
820 }
821 case kUChar_t: {
822 return ConvertAndCopy<unsigned char>(valuestring, targetaddress);
823 break;
824 }
825 case kShort_t: {
826 return ConvertAndCopy<short>(valuestring, targetaddress);
827 break;
828 }
829 case kUShort_t: {
830 return ConvertAndCopy<unsigned short>(valuestring, targetaddress);
831 break;
832 }
833 case kInt_t: {
834 return ConvertAndCopy<int>(valuestring, targetaddress);
835 break;
836 }
837 case kUInt_t: {
838 return ConvertAndCopy<unsigned int>(valuestring, targetaddress);
839 break;
840 }
841 case kLong_t: {
842 return ConvertAndCopy<long>(valuestring, targetaddress);
843 break;
844 }
845 case kULong_t: {
846 return ConvertAndCopy<unsigned long>(valuestring, targetaddress);
847 break;
848 }
849 case kFloat_t: {
850 return ConvertAndCopy<float>(valuestring, targetaddress);
851 break;
852 }
853 case kDouble_t: {
854 return ConvertAndCopy<double>(valuestring, targetaddress);
855 break;
856 }
857 case kDouble32_t: {
858 return ConvertAndCopy<double>(valuestring, targetaddress);
859 break;
860 }
861 case kchar: {
862 unsupp();
863 break;
864 }
865 case kBool_t: {
866 return ConvertAndCopy<bool>(valuestring, targetaddress);
867 break;
868 }
869 case kLong64_t: {
870 return ConvertAndCopy<long long>(valuestring, targetaddress);
871 break;
872 }
873 case kULong64_t: {
874 return ConvertAndCopy<unsigned long long>(valuestring, targetaddress);
875 break;
876 }
877 case kOther_t: {
878 unsupp();
879 break;
880 }
881 case kNoType_t: {
882 unsupp();
883 break;
884 }
885 case kFloat16_t: {
886 unsupp();
887 break;
888 }
889 case kCounter: {
890 unsupp();
891 break;
892 }
893 case kCharStar: {
894 unsupp();
895 // return ConvertAndCopy<char*>(valuestring, targetaddress);
896 break;
897 }
898 case kBits: {
899 unsupp();
900 break;
901 }
902 case kVoid_t: {
903 unsupp();
904 break;
905 }
906 case kDataTypeAliasUnsigned_t: {
907 unsupp();
908 break;
909 }
910 /*
911 case kDataTypeAliasSignedChar_t: {
912 unsupp();
913 break;
914 }
915 case kNumDataTypes: {
916 unsupp();
917 break;
918 }*/
919 default: {
920 unsupp();
921 break;
922 }
923 }
925}
926
927} // namespace conf
928} // namespace o2
int32_t i
std::ostringstream debug
StringRef key
static void setInputDir(const std::string &d)
static boost::property_tree::ptree readConfigFile(std::string const &filepath)
static const std::string & getInputDir()
static EParamUpdateStatus updateThroughStorageMapWithConversion(std::string const &, std::string const &)
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)
static std::map< std::string, std::pair< std::type_info const &, void * > > * sKeyToStorageMap
static void updateFromFile(std::string const &, std::string const &paramsList="", bool unchangedOnly=false)
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 void printAllKeyValuePairs(bool useLogger=false)
static void toCCDB(std::string filename)
static void writeJSON(std::string const &filename, std::string const &keyOnly="")
static EParamUpdateStatus updateThroughStorageMap(std::string, std::string, std::type_info const &, void *)
static EnumRegistry * sEnumRegistry
static void fromCCDB(std::string filename)
static void updateFromString(std::string const &)
void add(const std::string &key, const TDataMember *dm)
std::string toString() const
bool contains(const std::string &key) const
GLuint entry
Definition glcorearb.h:5735
GLuint const GLchar * name
Definition glcorearb.h:781
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLenum target
Definition glcorearb.h:1641
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLenum const GLfloat * params
Definition glcorearb.h:272
GLuint GLfloat * val
Definition glcorearb.h:1582
GLenum GLfloat param
Definition glcorearb.h:271
bool keyInTree(boost::property_tree::ptree *pt, const std::string &key)
ConfigurableParam::EParamUpdateStatus ConvertAndCopy< unsigned char >(std::string const &valuestring, void *targetaddr)
bool isMemblockDifferent(void const *block1, void const *block2)
std::ostream & operator<<(std::ostream &out, ConfigurableParam const &param)
ConfigurableParam::EParamUpdateStatus ConvertAndCopy< std::string >(std::string const &valuestring, void *targetaddr)
ConfigurableParam::EParamUpdateStatus ConvertAndCopy< char >(std::string const &valuestring, void *targetaddr)
ConfigurableParam::EParamUpdateStatus ConvertAndCopy(std::string const &valuestring, void *targetaddr)
constexpr auto isArray()
Definition Variant.h:59
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
std::string filename()
bool isLegal(const std::string &value) const
std::vector< std::pair< std::string, int > > vvalues
int getIntValue(const std::string &value) const
static std::string rectifyDirectory(const std::string_view p)
static std::vector< std::string > tokenize(const std::string &src, char delim, bool trimToken=true, bool skipEmpty=true)
static std::string trim_copy(const std::string &s)
static std::string concat_string(Ts const &... ts)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"