ATLAS Offline Software
Loading...
Searching...
No Matches
IOVDbParser.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// IOVDbParser.cxx
6// implementation for simple XML parser for IOVDbSvc
7
8#include "GaudiKernel/MsgStream.h"
9#include "IOVDbParser.h"
11
12IOVDbParser::IOVDbParser(const std::string & input, MsgStream& log) :
13 m_valid(true)
14{
15 // parse the input string as XML, decode into Key/Value pairs
16 m_keys.clear();
17 // slot for the data outside of XML
18 m_keys[""]="";
19 // work through the string to build list of tags
20 std::string::size_type iofs=0;
21 std::string::size_type len=input.size();
22 while (iofs!=std::string::npos && iofs<len) {
23 // look for the start of the next XML tag
24 std::string::size_type iofs1=input.find('<',iofs);
25 if (iofs1>iofs && iofs1!=std::string::npos) {
26 // take any unmarked-up text into the 'outside' data slot
27 m_keys[""]+=IOVDbNamespace::spaceStrip(input.substr(iofs,iofs1-iofs));
28 }
29 if (iofs1!=std::string::npos) {
30 // have an opening XML tag - process it
31 // first find the end of the tag, either '>' or ' ', whichever first
32 std::string::size_type iofs2=input.find('>',iofs1);
33 std::string::size_type iofs3=input.find("/>",iofs1);
34 bool noClosingTag = (iofs2 == std::string::npos);
35 if (noClosingTag){
36 log << MSG::FATAL <<
37 "Badly formed XML string, no closing tag in " << input << endmsg;
38 m_valid=false;
39 iofs=std::string::npos;
40 return;
41 }
42 if (iofs2!=std::string::npos && iofs2<iofs3) {
43 // found a closing >, so tag is standard <tag>value</tag> form
44 std::string tag=IOVDbNamespace::spaceStrip(input.substr(iofs1+1,iofs2-iofs1-1));
45 // now need to find the closing </tag>
46 std::string::size_type iofs4=input.find("</"+tag,iofs2+1);
47 if (iofs4!=std::string::npos) {
48 // found closing tag, store tag and text
49 m_keys[tag]=IOVDbNamespace::spaceStrip(input.substr(iofs2+1,iofs4-iofs2-1));
50 // advance to the next part of the string, after '>' on closing tag
51 iofs=input.find('>',iofs4);
52 if (iofs == std::string::npos) {
53 log << MSG::FATAL <<
54 "Badly formed XML string, no closing tag in " << input << endmsg;
55 m_valid=false;
56 iofs=std::string::npos;
57 return;
58 } else {
59 iofs+=1;
60 }
61 } else {
62 log << MSG::FATAL <<
63 "Badly formed XML string, no closing tag in " << input << endmsg;
64 m_valid=false;
65 iofs=std::string::npos;
66 return;
67 }
68 } else if (iofs3!=std::string::npos) {
69 // found a />, so tag is of form <tag values info/>
70 // find the end of the tag part to see if a value is present
71 std::string::size_type iofs4=input.find(' ',iofs1+1);
72 std::string value,tag;
73 if (iofs4!=std::string::npos && iofs4<iofs3) {
74 value=IOVDbNamespace::spaceStrip(input.substr(iofs4,iofs3-iofs4));
75 tag=IOVDbNamespace::spaceStrip(input.substr(iofs1+1,iofs4-iofs1-1));
76 } else {
77 tag=input.substr(iofs1+1,iofs3-iofs1-1);
78 value="";
79 }
81 // advance to next part of string after closing />
82 iofs=iofs3+2;
83 } else {
84 // found a < but no closing >
85 log << MSG::FATAL << "Badly formed XML string, no closing > in input " <<
86 input << endmsg;
87 iofs=std::string::npos;
88 m_valid=false;
89 return;
90 }
91 } else {
92 // no more < in input, take the rest into 'outside' data slot
93 m_keys[""]+=IOVDbNamespace::spaceStrip(input.substr(iofs));
94 iofs=len;
95 }
96 }
97 this->clean(); //rectify obsolete key names
98 if (log.level()<=MSG::VERBOSE) {
99 log << MSG::VERBOSE << "parseXML processed input string: " << input << endmsg;
100 for (KeyValMap::const_iterator itr=m_keys.begin();itr!=m_keys.end();++itr) {
101 log << MSG::VERBOSE << "Key: " << itr->first << " value:" <<
102 itr->second << endmsg;
103 }
104 }
105}
106
107bool
108IOVDbParser::getKey(const std::string& key, const std::string& defvalue,
109 std::string& value) const {
110 // check if key is present in keyval, if so set value to it
111 // if not set value to supplied default
112 // return true or false depending on whether a matching key was found
113 if (!m_valid) {
114 value=defvalue;
115 return false;
116 }
117 auto [theValue,found] = at(key,defvalue);
118 value=std::move(theValue);
119 return found;
120}
121
122std::pair<std::string, bool>
123IOVDbParser::at(const std::string & searchKey, const std::string &defaultValue) const{
124 KeyValMap::const_iterator it = m_keys.find(searchKey);
125 if (it != m_keys.end()) {
126 //may contain return or newline character
127 return std::pair<std::string, bool>(IOVDbNamespace::spaceStrip(it->second), true);
128 }
129 return std::pair<std::string, bool> (defaultValue, false);
130}
131
132std::string
134 return at("").first;
135}
136
137std::string
139 return at("key",folderName()).first;
140}
141
142bool
144 return at("key").second;
145}
146
147std::string
149 return at("tag").first;
150}
151
152std::string
154 return at("eventStoreName","StoreGateSvc").first;
155}
156
157bool
159 return (at("timeStamp").first=="time");
160}
161
162std::string
164 return at("cache").first;
165}
166
167int
169 auto valuePair=at("cachehint");
170 return valuePair.second ? std::stoi(valuePair.first) : 0;
171}
172
173bool
175 return at("named").second;
176}
177
178bool
180 return at("metaOnly").second;
181}
182
183bool
185 return at("extensible").second;
186}
187
188
189CLID
190IOVDbParser::classId(MsgStream& msg) const{
191 CLID result{};
192 auto [addrHeader,foundHeader]=at("addrHeader");
193 if (foundHeader) {
195 msg << MSG::DEBUG <<"Decode addrHeader "<< addrHeader << endmsg;
196 IOVDbParser addrH(addrHeader,msg);
197 if (auto addrPair=addrH.at("address_header");addrPair.second) {
198 result = IOVDbNamespace::parseClid(addrPair.first);
199 msg << MSG::DEBUG << "Got CLID " << result << " from " << addrPair.first << endmsg;
200 }
201 }
202 return result;
203}
204
205std::string
207 return at("addrHeader").first;
208}
209
210std::vector<std::string>
212 const auto & symLinkString = at("symlinks").first;
213 return IOVDbNamespace::parseLinkNames(symLinkString);
214}
215
216bool
218 return at("noover").second;
219}
220
221
223 auto it=m_keys.find("dbConnection");
224 if (it!=m_keys.end()) {
225 std::string connection=std::move(it->second);
226 m_keys.erase(it);
227 m_keys["db"]=std::move(connection);
228 }
229 }
230
231
232unsigned
233IOVDbParser::applyOverrides(const IOVDbParser& other, MsgStream & log) {
234 unsigned keyCounter=0;
235 for (const auto& otherKeyValue : other.m_keys) {
236 const std::string& otherKey=otherKeyValue.first;
237 const std::string& otherValue=otherKeyValue.second;
238 if (otherKey.empty()) continue; //Ignore Foldername
239 if (otherKey=="prefix") continue; //Ignore prefix
240 KeyValMap::iterator it=m_keys.find(otherKey);
241 if (it==m_keys.end()) {
242 log << MSG::INFO << "Folder " << m_keys[""] << ", adding new key " << otherKey
243 << " with value " << otherValue << endmsg;
244 m_keys[otherKey]=otherValue;
245 }
246 else {
247 log << MSG::INFO << "Folder " << m_keys[""] << ", Key: " << otherKey
248 << "Overriding existing value " << m_keys[otherKey] << " to new value " << otherValue << endmsg;
249 it->second=otherValue;
250 }
251 ++keyCounter;
252 } //End loop over keys in other
253 return keyCounter;
254}
255
256bool
258 return ((this->m_keys) == other.m_keys);
259}
260
261bool
263 //no check on folder time unit compatibility
264 return overridesIovImpl(msg, false);
265}
266
267bool
268IOVDbParser::overridesIov(MsgStream& msg, const bool folderIs_nsOfEpoch) const {
269 //check folder time unit compatibility
270 return overridesIovImpl(msg ,true, folderIs_nsOfEpoch);
271}
272
273bool
274IOVDbParser::overridesIovImpl(MsgStream& msg, const bool performFolderCheck,const bool folderIs_nsOfEpoch) const{
275 bool overrideIs_nsEpochIov{true};
276 const bool overridingTimestamp=(m_keys.find("forceTimestamp")!=m_keys.end());
277 const bool overridingRun=(m_keys.find("forceRunNumber")!=m_keys.end());
278 const bool overridingLumi=(m_keys.find("forceLumiblockNumber")!=m_keys.end());
279 //check for nonsense scenarios:
280 //1. overriding Lumi but not the Run number
281 if (overridingLumi and not overridingRun){
282 msg << MSG::WARNING<<"Trying to override lumi block without specifying the run"<<endmsg;
283 return false;
284 }
285 //2. Trying to override both
286 if (overridingRun and overridingTimestamp){
287 msg << MSG::WARNING<<"Trying to override using both run-lumi and ns timestamp"<<endmsg;
288 return false;
289 }
290 // now we are consistent, so set the 'is_ns' variable if it's different from default
291 if (overridingRun) overrideIs_nsEpochIov=false;
292 //3. Overriding a folder in ns format with a run-lumi IOV, or folder in run-lumi with ns timestamp
293 if (performFolderCheck and (overrideIs_nsEpochIov != folderIs_nsOfEpoch)){
294 msg << MSG::WARNING<<"Trying to override run-lumi for a ns folder, or ns for a run-lumi folder"<<endmsg;
295 return false;
296 }
297 return (overridingTimestamp or overridingRun);
298}
299
300unsigned long long
302 unsigned long long value{};
303 if (not overridesIov(msg)) return value;
304 auto pTsPair = m_keys.find("forceTimestamp");
305 if (pTsPair!=m_keys.end()){
306 value = IOVDbNamespace::iovFromTimeString(pTsPair->second);
307 }
308 else {
309 auto pRunPair = m_keys.find("forceRunNumber");
310 auto pLumiPair = m_keys.find("forceLumiblockNumber");
311 const auto & runString = (pRunPair!=m_keys.end()) ? pRunPair->second : "";
312 const auto & lumiString = (pLumiPair!=m_keys.end()) ? pLumiPair->second : "";
313 //could check that values were actually given here
315 }
316 return value;
317}
318
319std::string
321 std::stringstream retval;
322 retval <<"Folder:";
323 retval << folderName();
324 retval << ", Attributes: ";
325 auto it=m_keys.begin();
326 auto it_e=m_keys.end();
327 for (;it!=it_e;++it) {
328 if (it->first.empty()) continue;
329 retval << "[" << it->first << ":" << it->second << "] ";
330 }
331 return retval.str();
332
333}
334MsgStream& operator<<(MsgStream& os, const IOVDbParser& fldr) {
335 os << fldr.toString();
336 return os;
337}
#define endmsg
uint32_t CLID
The Class ID type.
MsgStream & operator<<(MsgStream &os, const IOVDbParser &fldr)
bool overridesIovImpl(MsgStream &msg, const bool performFolderCheck, const bool folderIs_nsOfEpoch=true) const
implementation of overridesIov, with or without check on folder compatibility
std::pair< std::string, bool > at(const std::string &searchKey, const std::string &defaultValue="") const
'at' accessor with an optional default; the bool is true if the key was found
std::string toString() const
std::vector< std::string > symLinks() const
std::string key() const
int cachehint() const
std::string cache() const
CLID classId(MsgStream &msg) const
bool onlyReadMetadata() const
bool named() const
bool getKey(const std::string &key, const std::string &devvalue, std::string &value) const
original 'getKey' method, now implemented using 'at'
std::string eventStoreName() const
bool hasKey() const
bool timebaseIs_nsOfEpoch() const
unsigned long long iovOverrideValue(MsgStream &msg) const
bool overridesIov(MsgStream &msg) const
return true if this description overrides the timestamp or runlumi
bool operator==(const IOVDbParser &other) const
bool extensible() const
bool noTagOverride() const
KeyValMap m_keys
Definition IOVDbParser.h:61
std::string addressHeader() const
unsigned applyOverrides(const IOVDbParser &other, MsgStream &log)
std::string folderName() const
give the folder name contained in the parsed description
std::string tag() const
IOVDbParser()=delete
unsigned long long iovFromRunString(const std::string &runString)
Take a string run number and convert it to an ULL representing run<<32.
unsigned long long iovFromLumiBlockString(const std::string &lbString)
String representation of lumiblock just converted to LL (as in original code) and returned as a ULL.
std::string spaceStrip(const std::string &input)
Trim leading and trailing spaces,return a new trimmed string.
bool replaceServiceType71(std::string &addrHeader)
unsigned long long iovFromTimeString(const std::string &iovString)
Take a string integer giving a time in seconds and convert it to a ULL in nanoseconds.
int parseClid(const std::string &addrHeaderStr)
Extract the Class ID (an integer) from a string of form <addrHeader><address_header service_type="256...
std::vector< std::string > parseLinkNames(const std::string &linktext)
Parse string of format "A:X::B:C" to "A" , "X::B", "C".
MsgStream & msg
Definition testRead.cxx:32