ATLAS Offline Software
Loading...
Searching...
No Matches
CoralCrestManager.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4// @file CoralCrestManager.cxx
5// Implementation for CrestFunctions utilities
6// @author Evgeny Alexandrov
7// @date 24 February 2025
8
9#include "CoralCrestManager.h"
10#include <memory>
11#include "CrestApi/CrestApi.h"
12#include "CrestApi/CrestApiFs.h"
13#include "CoralBase/AttributeList.h"
14#include "CoralBase/Attribute.h"
15#include "CoolKernel/StorageType.h"
16#include "CoolKernel/RecordSpecification.h"
17#include "CoolKernel/Record.h"
19#include "CxxUtils/base64.h"
20
22#include "GaudiKernel/MsgStream.h"
23#include "GaudiKernel/SystemOfUnits.h"
24
25namespace{
26 const std::map<std::string, cool::StorageType::TypeId> typeCorrespondance={
27 {"Bool", cool::StorageType::Bool},
28 {"UChar",cool::StorageType::UChar},
29 {"Int16", cool::StorageType::Int16},
30 {"UInt16", cool::StorageType::UInt16},
31 {"Int32", cool::StorageType::Int32},
32 {"UInt32", cool::StorageType::UInt32},
33 {"UInt63",cool::StorageType::UInt63},
34 {"Int64", cool::StorageType::Int64},
35 {"Float", cool::StorageType::Float},
36 {"Double", cool::StorageType::Double},
37 {"String255", cool::StorageType::String255},
38 {"String4k", cool::StorageType::String4k},
39 {"String64k", cool::StorageType::String64k},
40 {"String16M", cool::StorageType::String16M},
41 {"String128M", cool::StorageType::String128M},
42 {"Blob64k", cool::StorageType::Blob64k},
43 {"Blob16M", cool::StorageType::Blob16M},
44 {"Blob128M", cool::StorageType::Blob128M},
45 {"Blob", cool::StorageType::Blob128M}
46 };
47
48 const std::string colonDelimiter{" : "};
49}
50 CoralCrestManager::CoralCrestManager(const std::string & crest_path, const std::string & crestTag):m_crestTag(crestTag){ //AthMessaging("CoralCrestManager")
51 if(crest_path.length()==0)
52 return;
53 if (crest_path.starts_with(CoralCrestManager::prefix1) || crest_path.starts_with(CoralCrestManager::prefix2)){
54 m_crestCl = std::make_unique<Crest::CrestApi>(Crest::CrestApi(crest_path));
55 }
56 else{
57 m_crestCl = std::make_unique<Crest::CrestApiFs>(Crest::CrestApiFs(false,crest_path));
58 }
59
60 }
61
62 std::map<std::string, std::string> CoralCrestManager::getGlobalTagMap(const std::string & crest_path, const std::string& globaltag){
63 std::unique_ptr<Crest::CrestApiBase> crestCl;
64 if (crest_path.starts_with(CoralCrestManager::prefix1) || crest_path.starts_with(CoralCrestManager::prefix2)){
65 crestCl.reset(new Crest::CrestApi(crest_path));
66 }
67 else{
68 crestCl.reset(new Crest::CrestApiFs(true,crest_path));
69 }
70 std::map<std::string, std::string> tagmap;
71 try{
72 Crest::GlobalTagMapSetDto dto = crestCl->findGlobalTagMap(globaltag,"Trace");
73 for (const auto &tagMapDto : dto.getResources()){
74 tagmap[tagMapDto.getLabel()]=tagMapDto.getTagName();
75 }
76 } catch (std::exception & e){
77 MsgStream gLog(Athena::getMessageSvc(), "CoralCrestManager");
78 gLog << MSG::ERROR << __FILE__<<":"<<__LINE__<< ": " << e.what() << " Cannot get a global tag map for " << globaltag<<endmsg;
79 }
80 return tagmap;
81 }
82
83 std::string CoralCrestManager::parseTypeName(const std::string & description){
84 std::string regex=R"delim(<typeName>\s*([^\s]+)\s*</typeName>)delim";
85 std::regex re(regex);
86 std::smatch typeMatch;
87 bool match=std::regex_search(description, typeMatch,re);
88 return (match) ? std::string(typeMatch[1]) : std::string("");
89 }
90
92 Crest::TagInfoDto info = getTagInfoDto();
93 std::string folderDescription = info.getFolderDescription();
94 if (folderDescription.find("<coracool>") != std::string::npos) return IOVDbNamespace::CoraCool;
95 const std::string typeName = parseTypeName(folderDescription);
96 if (typeName=="CondAttrListVec"){
97 m_isVectorPayload = true;
99 }
100 m_isVectorPayload = false;
101 std::vector< std::pair<std::string,std::string> > spec= info.getPayloadSpec().getColumns();
102 std::vector< std::pair<std::string,std::string> > chs = info.getChannels().getChannels();
103 for (auto &p : spec){
104 if(p.first=="PoolRef" && p.second=="String4k"){
105 int id=std::stoll(chs[0].first);
106 if(chs.size()==1 && id==0)
108 else
110 }
111 }
112 if (typeName == "CondAttrListCollection") return IOVDbNamespace::AttrListColl;
114 }
115
117 if(!m_isVectorPayload.has_value())
119 return m_isVectorPayload.value();
120 }
121
123 if(m_TagMeta.has_value()){
124 return;
125 }
126
127 try{
128 m_TagMeta = m_crestCl->findTagMeta(m_crestTag);
129 } catch (std::exception & e){
130 MsgStream gLog(Athena::getMessageSvc(), "CoralCrestManager");
131 gLog << MSG::ERROR << __FILE__<<":"<<__LINE__<< ": " << e.what() << " Cannot get a tag meta info " << m_crestTag<<endmsg;
132 }
133 return;
134 }
135
137 if(!m_TagMeta.has_value())
138 loadTagInfo();
139 return m_TagMeta.value().getTagInfoDto();
140 }
141
143 if(!m_Tag.has_value()){
144 m_Tag = m_crestCl->findTag(m_crestTag);
145 }
146 return m_Tag.value();
147 }
148
150 return getTagInfoDto().getPayloadSpec().toJson().dump();
151 }
152
154 Crest::TagInfoDto info = getTagInfoDto();
155 return info.getFolderDescription();
156 }
157
158 std::pair<std::vector<cool::ChannelId> , std::vector<std::string>> CoralCrestManager::getChannelList(){
159 if(!m_TagMeta.has_value())
160 loadTagInfo();
161 Crest::TagInfoDto info = getTagInfoDto();
162 std::vector<cool::ChannelId> list;
163 std::vector<std::string> names;
164 std::vector< std::pair<std::string,std::string> > res = info.getChannels().getChannels();
165 for (auto &p : res){
166 list.push_back(std::stoll(p.first));
167 names.push_back(p.second);
168 }
169 return std::make_pair(std::move(list), std::move(names));
170 }
171
172 coral::AttributeListSpecification* CoralCrestManager::getAttributeListSpec(){
173 Crest::TagInfoDto info = getTagInfoDto();
174 std::vector< std::pair<std::string,std::string> > spec_vec= info.getPayloadSpec().getColumns();
175 auto * spec = new coral::AttributeListSpecification();
176 for (auto &p : spec_vec){
177 auto it = typeCorrespondance.find(p.second);
178 if (it != typeCorrespondance.end()) {
179 spec->extend(p.first,cool::StorageType::storageType(it->second).cppType());
180 }
181 }
182 return spec;
183 }
184
186 if(m_crest_cont.has_value())
187 return;
188 Crest::TagInfoDto info = getTagInfoDto();
189 Crest::TagDto tag = getTagDto();
191 if(tag.getObjectType()=="crest-json-multi-iov")
193 Crest::CrestContainer cr_cont(mId);
194 std::vector< std::pair<std::string,std::string> > spec= info.getPayloadSpec().getColumns();
195 for (auto &p : spec){
196 cr_cont.addColumn(p.first,p.second.c_str());
197 }
198 if(!m_isVectorPayload.has_value()) determineFolderType();
199 cr_cont.setVectorPayload(m_isVectorPayload.value());
200 m_crest_cont.emplace(cr_cont);
201 return;
202 }
203
204 std::pair<uint64_t,uint64_t>
205 CoralCrestManager::getSinceUntilPair(std::vector<uint64_t>& v, const uint64_t since, const uint64_t until){
206 uint64_t new_since = 0;
207 uint64_t new_until = 0;
208
209 if (until < since){
210 MsgStream gLog(Athena::getMessageSvc(), "CoralCrestManager");
211 gLog << MSG::ERROR << "Wrong since/until."<<endmsg;
212 return std::make_pair(0,0);
213 }
214 const std::size_t N = v.size();
215 std::size_t i = 0;
216 for (; i < N; ++i) {
217 if(v[i] <= since && since < v[i+1]){
218 new_since = v[i];
219 break;
220 }
221 }
222
223 for (; i < N; ++i) {
224 if(v[i] < until && until <= v[i+1]){
225 new_until = v[i+1];
226 break;
227 }
228 }
229
230 return std::make_pair(new_since,new_until);
231 }
232
233 std::pair<uint64_t,uint64_t>
234 CoralCrestManager::getIovInterval(const std::string& tag, const uint64_t since, const uint64_t until){
235 Crest::IovSetDto dto = m_crestCl->selectGroups(tag, 0, 10000, 0, "id.since:ASC");
236 std::vector<uint64_t> v = dto.getListSince();
237 v.push_back(cool::ValidityKeyMax); // added "infinity" as the last item 9223372036854775807
238 return getSinceUntilPair(v, since, until);
239 }
240
241 std::vector<std::pair<cool::ValidityKey,std::string>> CoralCrestManager::getIovsForTag(uint64_t since, uint64_t until){
243 int iovNumber = m_crestCl->getSize(m_crestTag);
244 std::vector<std::pair<cool::ValidityKey,std::string>> res;
245 Crest::IovSetDto dto;
246 if(iovNumber <=1000){
247 dto = m_crestCl->selectIovs(m_crestTag, 0, -1, 0, 10000, 0, "id.since:ASC");
248 }
249 else{
250 std::pair<uint64_t,uint64_t> ppt = getIovInterval(m_crestTag, since, until);
251 uint64_t s_time = ppt.first;
252 uint64_t u_time = ppt.second;
253
254 if (s_time == 0 && u_time == 0){ // data out of range
255 return res;
256 }
257 else {
258 dto = m_crestCl->selectIovs(m_crestTag, s_time, u_time, 0, 10000, 0, "id.since:ASC");
259 }
260 }
261 for (auto &p : dto.getResources()){
262 res.push_back(std::make_pair((cool::ValidityKey)p.getSince(),p.getPayloadHash()));
263 }
264 return res;
265 }
266
267 std::vector<uint64_t> CoralCrestManager::loadPayloadForHash(uint64_t since, const std::string & hash){
269 std::string reply;
270 try{
271 // get payload from Crest server
272 reply = m_crestCl->getPayload(hash);
273 } catch (std::exception & e){
274 MsgStream gLog(Athena::getMessageSvc(), "CoralCrestManager");
275 gLog << MSG::ERROR << __FILE__<<":"<<__LINE__<< ": "<<e.what()<<" while trying to find the payload"<<endmsg;
276 throw std::runtime_error(e.what());
277 }
278 try{
279 // parse payload according to type of payload and put it to CrestConteiner.
280 // Store only one value before 'since'.
281 // Returns a list of timestamp for which data has been loaded
282 return m_crest_cont.value().fromJson(since,reply);
283 } catch (std::exception & e){
284 MsgStream gLog(Athena::getMessageSvc(), "CoralCrestManager");
285 gLog << MSG::ERROR << "LoadPayloadForHash:"<<e.what()<<" while trying to parse the payload. Since="<<since<<", hash="<<hash<<endmsg;
286 throw std::runtime_error(e.what());
287 }
288 }
289
290 //put payload for selected since in json string
291 std::string CoralCrestManager::dumpPayload(cool::ValidityKey since){
292 m_crest_cont.value().selectIov(since);
294 std::stringstream res;
295 res<<"[";
296 std::vector<std::string> chIds = m_crest_cont.value().channelIds();
297 auto* pspec=getAttributeListSpec();
298 std::string sep="";
299 for (auto &ch : chIds){
300 res<<sep;
301 res<<IOVDbNamespace::s_openJson<<"\""<<ch<<"\" : ";
302 switch (ftype){
304 {
305 std::vector<coral::AttributeList> attr=getVectorPayload(pspec,ch);
306 res<<"[";
307 std::string sep2="";
308 for (const auto & vitr:attr){
310 if (sep2.empty()) sep2 =IOVDbNamespace::s_delimiterJson;
311 }
312 res<<"]";
313 break;
314 }
318 {
319 coral::AttributeList attr=getPayload(pspec,ch);
321 break;
322 }
324 {
325 coral::AttributeList attr=getPayload(pspec,ch);
326 std::ostringstream os;
327 attr[0].toOutputStream(os);
328 auto str=os.str();
329 const auto separatorPosition = str.find(colonDelimiter);
330 const std::string payloadOnly=str.substr(separatorPosition+3);
331 res<<"\""<<payloadOnly<<"\"";
332 break;
333 }
335 res<< " CoraCool";
336 break;
337 default:
338 res<<" a_data_value";
339 }
340 if (sep.empty()) sep=",";
342 }
343 res<<"]";
344 pspec->release();
345 return res.str();
346 }
347
348 coral::AttributeList CoralCrestManager::getPayload(coral::AttributeListSpecification * pSpec,const std::string & chId){
349 nlohmann::json j=m_crest_cont.value().getPayloadChannel(chId.c_str());
350 return createAttributeList(pSpec,j,m_crest_cont.value().getMPayloadSpec());
351 }
352
353 std::vector<coral::AttributeList> CoralCrestManager::getVectorPayload(coral::AttributeListSpecification* pSpec,const std::string & chId){
354 std::vector<coral::AttributeList> res;
355 nlohmann::json vecJ=m_crest_cont.value().getPayloadChannel(chId.c_str());
356 for (auto &p : vecJ){
357 coral::AttributeList att=createAttributeList(pSpec,p,m_crest_cont.value().getMPayloadSpec());
358 res.push_back(att);
359 }
360 return res;
361 }
362
363 void CoralCrestManager::selectIov(cool::ValidityKey since){
364 m_crest_cont.value().selectIov(since);
365 }
366
367 std::vector<std::string> CoralCrestManager::channelIds(cool::ValidityKey since){
368 selectIov(since);
369 return m_crest_cont.value().channelIds();
370 }
371
372 coral::AttributeList CoralCrestManager::createAttributeList(coral::AttributeListSpecification * pSpec,nlohmann::json& j,const std::vector<std::pair<std::string, Crest::TypeId>> & tSpec){
373 coral::AttributeList attr(*pSpec,true);
374 unsigned int s=attr.size();
375
376 json::const_iterator it = j.begin();
377 for (unsigned int i(0);i!=s;++i){
378 // cool::Record does not provide non-const access to AttributeList.
379 // But this is safe because we are filling a local instance.
380 auto & att = const_cast<coral::Attribute&>(attr[i]);
381 if (it == j.end()){
382 continue;
383 }
384 const auto thisVal = it.value();
385 ++it;
386
387 try{
388 if (thisVal.is_null()){
389 att.setNull();
390 continue;
391 }
392 cool::StorageType::TypeId typespec=cool::StorageType::Bool;
393 for(auto &p : tSpec){
394 if(p.first.compare(att.specification().name())==0){
395 auto pElement = Crest::s_typeToString.find(p.second);
396 if (pElement == Crest::s_typeToString.end()){
397 throw std::runtime_error("CoralCrestManager::createAttributeList: name not found.");
398 }
399 std::string str_spec = pElement ->second;
400 auto pTypespec = typeCorrespondance.find(str_spec);
401 if (pTypespec == typeCorrespondance.end()){
402 throw std::runtime_error("CoralCrestManager::createAttributeList: typespec not found.");
403 }
404 typespec=pTypespec->second;
405 break;
406 }
407 }
408 std::string strVal = to_string(thisVal);
409 if(strVal.size()>2&& strVal[0]=='"'&& strVal[strVal.size()-1]=='"')
410 strVal=strVal.substr(1,strVal.size()-2);
411
412 if((strVal.compare("NULL")==0||strVal.compare("null")==0)&&
413 (typespec==cool::StorageType::Bool || typespec==cool::StorageType::Int16 || typespec==cool::StorageType::UInt16
414 || typespec==cool::StorageType::Int32 || typespec==cool::StorageType::UInt32
415 || typespec==cool::StorageType::Int64 || typespec==cool::StorageType::UInt63
416 || typespec==cool::StorageType::Float || typespec==cool::StorageType::Double)){
417 att.setNull();
418 continue;
419 }
420 switch (typespec) {
421 case cool::StorageType::Bool:
422 {
423 const bool newVal=(strVal == "true");
424 att.setValue<bool>(newVal);
425 break;
426 }
427 case cool::StorageType::UChar:
428 {
429 const unsigned char newVal=std::stoul(strVal);
430 att.setValue<unsigned char>(newVal);
431 break;
432 }
433 case cool::StorageType::Int16:
434 {
435 const short newVal=std::stol(strVal);
436 att.setValue<short>(newVal);
437 break;
438 }
439 case cool::StorageType::UInt16:
440 {
441 const unsigned short newVal=std::stoul(strVal);
442 att.setValue<unsigned short>(newVal);
443 break;
444 }
445 case cool::StorageType::Int32:
446 {
447 const int newVal=std::stoi(strVal);
448 att.setValue<int>(newVal);
449 break;
450 }
451 case cool::StorageType::UInt32:
452 {
453 const unsigned int newVal=std::stoull(strVal);
454 att.setValue<unsigned int>(newVal);
455 break;
456 }
457 case cool::StorageType::UInt63:
458 {
459 const unsigned long long newVal=std::stoull(strVal);
460 att.setValue<unsigned long long>(newVal);
461 break;
462 }
463 case cool::StorageType::Int64:
464 {
465 const long long newVal=std::stoll(strVal);
466 att.setValue< long long>(newVal);
467 break;
468 }
469 case cool::StorageType::Float:
470 {
471 const float newVal=std::stof(strVal);
472 att.setValue<float>(newVal);
473 break;
474 }
475 case cool::StorageType::Double:
476 {
477 const double newVal=std::stod(strVal);
478 att.setValue<double>(newVal);
479 break;
480 }
481 case cool::StorageType::String255:
482 case cool::StorageType::String4k:
483 case cool::StorageType::String64k:
484 case cool::StorageType::String16M:
485 case cool::StorageType::String128M:
486 {
487 att.setValue<std::string>(thisVal.get<std::string>());
488 break;
489 }
490 case cool::StorageType::Blob128M:
491 case cool::StorageType::Blob16M:
492 case cool::StorageType::Blob64k:
493 {
494 const auto &charVec = CxxUtils::base64_decode(strVal);
495 coral::Blob blob(charVec.size());
496 memcpy(blob.startingAddress(), charVec.data(), charVec.size());
497 att.setValue<coral::Blob>(blob);
498 break;
499 }
500 default:
501 {
502 std::string errorMessage("UNTREATED TYPE! " + std::to_string(typespec));
503 MsgStream gLog(Athena::getMessageSvc(), "CoralCrestManager");
504 gLog << MSG::ERROR << "LoadPayloadForHash:" <<errorMessage<<endmsg;
505 throw std::runtime_error(errorMessage);
506 }
507 }
508 }
509 catch (json::exception& e){
510 MsgStream gLog(Athena::getMessageSvc(), "CoralCrestManager");
511 gLog << MSG::ERROR << "Error CoralCrestManager::createAttributeList: "<<e.what()<<endmsg;
512 throw std::runtime_error(e.what());
513 }
514 }
515 return attr;
516 }
517
518
519
520
const std::regex re(r_e)
#define endmsg
Header for CoralCrestManager class.
static std::string to_string(const std::vector< T > &v)
std::pair< std::vector< unsigned int >, bool > res
if(pathvar)
static std::map< std::string, std::string > getGlobalTagMap(const std::string &crest_path, const std::string &globaltag)
std::vector< std::pair< cool::ValidityKey, std::string > > getIovsForTag(uint64_t since, uint64_t until)
std::vector< std::string > channelIds(cool::ValidityKey since)
IOVDbNamespace::FolderType determineFolderType()
std::vector< uint64_t > loadPayloadForHash(uint64_t since, const std::string &hash)
std::string dumpPayload(cool::ValidityKey since)
Crest::TagDto & getTagDto()
std::vector< coral::AttributeList > getVectorPayload(coral::AttributeListSpecification *pSpec, const std::string &chId)
std::optional< Crest::TagMetaDto > m_TagMeta
std::string getFolderDescription()
coral::AttributeList createAttributeList(coral::AttributeListSpecification *pSpec, nlohmann::json &j, const std::vector< std::pair< std::string, Crest::TypeId > > &tSpec)
std::optional< Crest::CrestContainer > m_crest_cont
std::optional< bool > m_isVectorPayload
std::optional< Crest::TagDto > m_Tag
std::string parseTypeName(const std::string &description)
CoralCrestManager(const std::string &crest_path, const std::string &crestTag)
static const std::string prefix1
std::pair< uint64_t, uint64_t > getIovInterval(const std::string &tag, const uint64_t since, const uint64_t until)
std::string getPayloadSpec()
std::pair< std::vector< cool::ChannelId >, std::vector< std::string > > getChannelList()
coral::AttributeList getPayload(coral::AttributeListSpecification *pSpec, const std::string &chId)
std::pair< uint64_t, uint64_t > getSinceUntilPair(std::vector< uint64_t > &v, const uint64_t since, const uint64_t until)
std::unique_ptr< Crest::CrestApiBase > m_crestCl
Crest::TagInfoDto getTagInfoDto()
coral::AttributeListSpecification * getAttributeListSpec()
static const std::string prefix2
const std::string m_crestTag
void selectIov(cool::ValidityKey since)
It compares timestamp in string format.
void addColumn(const std::string &name, TypeId type)
It adds a column to the payload specification.
void setVectorPayload(bool isVectorPayload)
Set the Vectore mode of the container.
singleton-like access to IMessageSvc via open function and helper
std::string description
glabal timer - how long have I taken so far?
Definition hcg.cxx:93
bool match(std::string s1, std::string s2)
match the individual directories of two strings
Definition hcg.cxx:359
IMessageSvc * getMessageSvc(bool quiet=false)
static const std::map< TypeId, std::string > s_typeToString
std::vector< unsigned char > base64_decode(const std::string &)
Definition base64.cxx:97
std::string jsonAttributeList(const coral::AttributeList &atrlist)
Produce a representation of a coral::AttributeList as a json string.
static const std::string s_delimiterJson
json standard delimiter ', '
static const std::string s_closeJson
json close tag, '}'
static const std::string s_openJson
json open tag, '{'