2323#include " Framework/Signpost.h"
2424#include < TError.h>
2525#include < TMemFile.h>
26+ #include < ctime>
2627
2728O2_DECLARE_DYNAMIC_LOG (ccdb);
2829
2930namespace o2 ::framework
3031{
3132
32- bool isPrefix (std::string_view prefix, std::string_view full)
33- {
34- return prefix == full.substr (0 , prefix.size ());
35- }
36-
37- CCDBHelpers::ParserResult CCDBHelpers::parseRemappings (char const * str)
38- {
39- std::unordered_map<std::string, std::string> remappings;
40- std::string currentUrl = " " ;
41-
42- enum ParsingStates {
43- IN_BEGIN,
44- IN_BEGIN_URL,
45- IN_BEGIN_TARGET,
46- IN_END_TARGET,
47- IN_END_URL
48- };
49- ParsingStates state = IN_BEGIN;
50-
51- while (true ) {
52- switch (state) {
53- case IN_BEGIN: {
54- if (*str == 0 ) {
55- return {remappings, " " };
56- }
57- state = IN_BEGIN_URL;
58- }
59- case IN_BEGIN_URL: {
60- if ((strncmp (" http://" , str, 7 ) != 0 ) && (strncmp (" https://" , str, 8 ) != 0 && (strncmp (" file://" , str, 7 ) != 0 ))) {
61- return {remappings, " URL should start with either http:// or https:// or file://" };
62- }
63- state = IN_END_URL;
64- } break ;
65- case IN_END_URL: {
66- char const * c = strchr (str, ' =' );
67- if (c == nullptr ) {
68- return {remappings, " Expecting at least one target path, missing `='?" };
69- }
70- if ((c - str) == 0 ) {
71- return {remappings, " Empty url" };
72- }
73- currentUrl = std::string_view (str, c - str);
74- state = IN_BEGIN_TARGET;
75- str = c + 1 ;
76- } break ;
77- case IN_BEGIN_TARGET: {
78- if (*str == 0 ) {
79- return {remappings, " Empty target" };
80- }
81- state = IN_END_TARGET;
82- } break ;
83- case IN_END_TARGET: {
84- char const * c = strpbrk (str, " ,;" );
85- if (c == nullptr ) {
86- if (remappings.count (str)) {
87- return {remappings, fmt::format (" Path {} requested more than once." , str)};
88- }
89- remappings[std::string (str)] = currentUrl;
90- return {remappings, " " };
91- }
92- if ((c - str) == 0 ) {
93- return {remappings, " Empty target" };
94- }
95- auto key = std::string (str, c - str);
96- if (remappings.count (str)) {
97- return {remappings, fmt::format (" Path {} requested more than once." , key)};
98- }
99- remappings[key] = currentUrl;
100- if (*c == ' ;' ) {
101- state = IN_BEGIN_URL;
102- } else {
103- state = IN_BEGIN_TARGET;
104- }
105- str = c + 1 ;
106- } break ;
107- }
108- }
109- }
110-
111- void initialiseHelper (CCDBFetcherHelper& helper, ConfigParamRegistry const & options, std::vector<o2::framework::OutputRoute> const & outputRoutes)
112- {
33+ // Fill valid routes. Here we consider only the routes which have
34+ // Lifetime::Condition. Notice the way we do it for analysis will be
35+ // different.
36+ namespace {
37+ void fillValidRoutes (CCDBFetcherHelper& helper, std::vector<o2::framework::OutputRoute> const & outputRoutes) {
11338 std::unordered_map<std::string, bool > accountedSpecs;
114- auto defHost = options.get <std::string>(" condition-backend" );
115- auto checkRate = options.get <int >(" condition-tf-per-query" );
116- auto checkMult = options.get <int >(" condition-tf-per-query-multiplier" );
117- helper.timeToleranceMS = options.get <int64_t >(" condition-time-tolerance" );
118- helper.queryPeriodGlo = checkRate > 0 ? checkRate : std::numeric_limits<int >::max ();
119- helper.queryPeriodFactor = checkMult > 0 ? checkMult : 1 ;
120- LOGP (info, " CCDB Backend at: {}, validity check for every {} TF{}" , defHost, helper.queryPeriodGlo , helper.queryPeriodFactor == 1 ? std::string{} : fmt::format (" , (query for high-rate objects downscaled by {})" , helper.queryPeriodFactor ));
121- LOGP (info, " Hook to enable signposts for CCDB messages at {}" , (void *)&private_o2_log_ccdb->stacktrace );
122- auto remapString = options.get <std::string>(" condition-remap" );
123- CCDBHelpers::ParserResult result = CCDBHelpers::parseRemappings (remapString.c_str ());
124- if (!result.error .empty ()) {
125- throw runtime_error_f (" Error while parsing remapping string %s" , result.error .c_str ());
126- }
127- helper.remappings = result.remappings ;
128- helper.apis [" " ].init (defHost); // default backend
129- LOGP (info, " Initialised default CCDB host {}" , defHost);
130- //
131- for (auto & entry : helper.remappings ) { // init api instances for every host seen in the remapping
132- if (helper.apis .find (entry.second ) == helper.apis .end ()) {
133- helper.apis [entry.second ].init (entry.second );
134- LOGP (info, " Initialised custom CCDB host {}" , entry.second );
135- }
136- LOGP (info, " {} is remapped to {}" , entry.first , entry.second );
137- }
138- helper.createdNotBefore = std::to_string (options.get <int64_t >(" condition-not-before" ));
139- helper.createdNotAfter = std::to_string (options.get <int64_t >(" condition-not-after" ));
140-
14139 for (auto & route : outputRoutes) {
14240 if (route.matcher .lifetime != Lifetime::Condition) {
14341 continue ;
@@ -156,6 +54,7 @@ void initialiseHelper(CCDBFetcherHelper& helper, ConfigParamRegistry const& opti
15654 }
15755 }
15856}
57+ }
15958
16059auto getOrbitResetTime (o2::pmr::vector<char > const & v) -> Long64_t
16160{
@@ -180,7 +79,8 @@ AlgorithmSpec CCDBHelpers::fetchFromCCDB()
18079{
18180 return adaptStateful ([](CallbackService& callbacks, ConfigParamRegistry const & options, DeviceSpec const & spec) {
18281 std::shared_ptr<CCDBFetcherHelper> helper = std::make_shared<CCDBFetcherHelper>();
183- initialiseHelper (*helper, options, spec.outputs );
82+ CCDBFetcherHelper::initialiseHelper (*helper, options);
83+ fillValidRoutes (*helper, spec.outputs );
18484 // / Add a callback on stop which dumps the statistics for the caching per
18585 // / path
18686 callbacks.set <CallbackService::Id::Stop>([helper]() {
@@ -279,6 +179,33 @@ AlgorithmSpec CCDBHelpers::fetchFromCCDB()
279179 // Fetch the rest of the objects.
280180 O2_SIGNPOST_EVENT_EMIT (ccdb, sid, " fetchFromCCDB" , " Fetching objects. Run %{public}s. OrbitResetTime %lld. Creation %lld. Timestamp %lld. firstTForbit %" PRIu32,
281181 dtc.runNumber .data (), orbitResetTime, timingInfo.creation , timestamp, timingInfo.firstTForbit );
182+ std::vector<CCDBFetcherHelper::FetchOp> ops;
183+ int runNumber = 0 ;
184+ std::string ccdbMetadataPrefix = " ccdb-metadata-" ;
185+ for (auto &route : helper->routes ) {
186+ CCDBFetcherHelper::FetchOp op{.spec = route.matcher , .timestamp = timestamp, .runNumber = std::stoi (dtc.runNumber )};
187+ for (auto & meta : route.matcher .metadata ) {
188+ if (meta.name == " ccdb-path" ) {
189+ op.url = meta.defaultValue .get <std::string>();
190+ } else if (meta.name == " ccdb-run-dependent" && meta.defaultValue .get <int >() > 0 ) {
191+ if (meta.defaultValue .get <int >() == 1 ) {
192+ op.runNumber = runNumber;
193+ } else if (meta.defaultValue .get <int >() == 2 ) {
194+ op.timestamp = runNumber;
195+ } else {
196+ LOGP (fatal, " Undefined ccdb-run-dependent option {} for spec {}" , meta.defaultValue .get <int >(), DataSpecUtils::describe (route.matcher ));
197+ }
198+ } else if (meta.name .starts_with (ccdbMetadataPrefix)) {
199+ std::string key = meta.name .substr (ccdbMetadataPrefix.size ());
200+ auto value = meta.defaultValue .get <std::string>();
201+ O2_SIGNPOST_EVENT_EMIT (ccdb, sid, " populateCacheWith" , " Adding metadata %{public}s: %{public}s to the request" , key.data (), value.data ());
202+ op.metadata .push_back ({key, value});
203+ } else if (meta.name == " ccdb-query-rate" ) {
204+ op.queryRate = meta.defaultValue .get <int >() * helper->queryPeriodFactor ;
205+ }
206+ }
207+ ops.push_back (op);
208+ }
282209
283210 CCDBFetcherHelper::populateCacheWith (helper, ops, timingInfo, dtc, allocator);
284211 O2_SIGNPOST_END (ccdb, _o2_signpost_id_t {(int64_t )timingInfo.timeslice }, " fetchFromCCDB" , " Fetching CCDB objects" );
0 commit comments