ATLAS Offline Software
Loading...
Searching...
No Matches
CrestContainer.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#include "CrestContainer.h"
6#include "CrestApi/CrestCondException.h"
7#include <cstdarg>
8#include <fstream>
9#include <iomanip>
10
11using json = nlohmann::json;
12
18
27
28bool compareStrTimestamp(std::string& as, std::string& bs) {
29 auto a = std::stol(as);
30 auto b = std::stol(bs);
31 return a < b;
32}
33
34void Crest::CrestContainer::addColumn(const std::string &name, TypeId type)
35{
36 m_payload_spec.emplace_back(name, type);
37}
38
39void Crest::CrestContainer::addColumn(const std::string &name, const std::string& type)
40{
41
42 for(auto& t: s_typeToString){
43 if(t.second.compare(type)==0){
44 addColumn(name, t.first);
45 return;
46 }
47 }
48 throw CommonCrestException("The type of parameter is not defined.");
49}
50
51void Crest::CrestContainer::addNullRecord(const std::string&name)
52{
53 auto it = std::find_if(m_payload_spec.begin(), m_payload_spec.end(),
54 [&name](const auto &column)
55 { return column.first == name; });
56
57 if (it != m_payload_spec.end())
58 {
59 m_row[name] = nlohmann::json::value_t::null;
60 }
61}
62
63void Crest::CrestContainer::addRecord(const std::string&name, int number, ...)
64{
65 va_list ap;
66 va_start(ap, number);
67
68 for (auto &column : m_payload_spec)
69 {
70 if (column.first != name)
71 {
72 continue;
73 }
74
75 switch (column.second)
76 {
77 case TypeId::Bool:
78 m_row[name] = va_arg(ap, int)==1;
79 break;
80 case TypeId::UChar:
81 m_row[name] = static_cast<unsigned char>(va_arg(ap, int));
82 break;
83 case TypeId::Int16:
84 case TypeId::Int32:
85 m_row[name] = va_arg(ap, int);
86 break;
87 case TypeId::UInt16:
88 case TypeId::UInt32:
89 m_row[name] = va_arg(ap, unsigned int);
90 break;
91 case TypeId::UInt63:
92 m_row[name] = va_arg(ap, uint64_t);
93 break;
94 case TypeId::Int64:
95 m_row[name] = va_arg(ap, int64_t);
96 break;
97 case TypeId::Float:
98 case TypeId::Double:
99 m_row[name] = va_arg(ap, double);
100 break;
102 case TypeId::String4k:
106 case TypeId::Blob64k:
107 case TypeId::Blob16M:
108 case TypeId::Blob128M:
109 m_row[name] = std::string(va_arg(ap, const char *));
110 break;
111 default:
112 throw CommonCrestException("Unsupported column type.");
113 }
114 }
115 va_end(ap);
116}
117
118void Crest::CrestContainer::addData(const std::string&channel_id)
119{
120 addExternalData(channel_id, getRow());
121}
122
123void Crest::CrestContainer::addExternalData(const std::string& channel_id, const nlohmann::json &data)
124{
125 nlohmann::json arr_data = m_isVectorPayload ? nlohmann::json::array() : nlohmann::json();
127 for (const auto &data_row : data)
128 {
129 arr_data.emplace_back(createRowArray(data_row));
130 }
131 m_payload[channel_id] = std::move(arr_data);
132 }
133 else{
134 m_payload[channel_id] = createRowArray(data);
135 }
136 m_vector_data.clear();
137 m_row.clear();
138}
139
140nlohmann::json Crest::CrestContainer::createRowArray(const nlohmann::json &data_row) const
141{
142 nlohmann::json row_arr_data = nlohmann::json::array();
143 for (const auto &column : m_payload_spec)
144 {
145 if (data_row.find(column.first) == data_row.end())
146 {
147 std::string msg = "The data does not contain the column: " + column.first;
148 throw CommonCrestException(msg.c_str());
149 }
150 row_arr_data.push_back(data_row[column.first]);
151 }
152 return row_arr_data;
153}
154
155void Crest::CrestContainer::addIov(const uint64_t since)
156{
157 m_iov_data["since"] = since;
158 m_iov_data["data"] = m_payload;
159 m_full_data[since]=m_payload;
160 m_payload.clear();
161}
162
163void Crest::CrestContainer::selectIov(const uint64_t since){
164 m_iov_data["since"]=since;
165 if(m_full_data.contains(since)){
166 m_iov_data["data"]=m_full_data[since];
167 m_payload=m_full_data[since];
168 }
169 else{
170 m_iov_data["data"]={};
171 m_payload={};
172 }
173}
174
176 if(m_full_data.size()==0)
177 {
178 throw CommonCrestException("No IOV in CrestContainer");
179 }
180 return m_full_data.begin()->first;
181}
182
183std::vector<std::string> Crest::CrestContainer::channelIds(){
184 std::vector<std::string> chs;
185 for (auto& x : m_iov_data["data"].items()){
186 chs.push_back(x.key());
187 }
188 sort(chs.begin(), chs.end(), compareStrTimestamp);
189 return chs;
190}
191const std::vector<std::pair<std::string, Crest::TypeId>> &Crest::CrestContainer::getMPayloadSpec()
192{
193 return m_payload_spec;
194}
195
196const nlohmann::json Crest::CrestContainer::getPayloadChannel(const std::string& channel_id)
197{
198 if (m_payload.empty())
199 {
200 m_payload = m_iov_data["data"];
201 }
202 auto it = m_payload.find(channel_id);
203 if (it == m_payload.end())
204 {
205 std::string msg = "Channel id " + std::string(channel_id) + " is not found.";
206 throw CommonCrestException(msg.c_str());
207 }
208 return it.value();
209}
210
211int Crest::CrestContainer::getColumnIndex(const std::string &name)
212{
213 auto it = std::find_if(m_payload_spec.begin(), m_payload_spec.end(),
214 [&name](const auto &column)
215 { return column.first == name; });
216
217 if (it != m_payload_spec.end())
218 {
219 return std::distance(m_payload_spec.begin(), it);
220 }
221 else
222 {
223 throw CommonCrestException("The column name is not found.");
224 }
225}
226
228{
230 {
231 m_vector_data.push_back(m_row);
232 m_row.clear();
233 }
234 else
235 {
236 std::string msg = "The payload is not a vector.";
237 throw CommonCrestException(msg.c_str());
238 }
239}
240
241const nlohmann::json &Crest::CrestContainer::getRow()
242{
244 return m_vector_data;
245 return m_row;
246}
247
249{
250 if (m_payload.empty() && m_iov_data.empty())
251 {
252 std::string msg = "The payload is empty.";
253 throw CommonCrestException(msg.c_str());
254 }
255 if (m_payload.empty())
256 {
257 m_payload = m_iov_data["data"];
258 }
259 return m_payload;
260}
261
263{
264 if (m_iov_data.empty())
265 {
266 std::string msg = "The iov data is empty.";
267 throw CommonCrestException(msg.c_str());
268 }
269 return m_iov_data;
270}
271
272void Crest::CrestContainer::setIovData(const nlohmann::json &j)
273{
274 m_iov_data = j;
275}
276
277void Crest::CrestContainer::setPayload(const nlohmann::json &j)
278{
279 m_payload = j;
280}
281
283{
284 return getPayload().dump();
285}
286
288{
289 return m_iov_data.dump();
290}
291
293{
294 json pspec_data=json::array();
295 for (auto &column : m_payload_spec)
296 {
297 json j={};
298 std::map<TypeId, std::string>::const_iterator pos = Crest::s_typeToString.find(column.second);
299 if (pos == Crest::s_typeToString.end()) {
300 throw CommonCrestException("Type do not exist in the map.");
301 } else {
302 j[column.first] = pos->second;
303 }
304 pspec_data.push_back(j);
305 }
306 return pspec_data;
307}
308
309void Crest::CrestContainer::setPayloadSpec(const nlohmann::json &j)
310{
311 if (j.is_array())
312 {
313 for (const auto &column : j)
314 {
315 for (const auto &[name, type] : column.items())
316 {
317 addColumn(name, static_cast<TypeId>(std::stoi(type.get<std::string>())));
318 }
319 }
320 }
321 else
322 {
323 for (const auto &[name, type] : j.items())
324 {
325 addColumn(name, static_cast<TypeId>(type.get<int>()));
326 }
327 }
328}
329
331{
332 m_iov_data.clear();
333 m_row.clear();
334 m_vector_data.clear();
335 m_full_data={};
336}
337
339 m_payload.clear();
340 m_iov_data.clear();
341 m_row.clear();
342 m_vector_data.clear();
343 m_full_data={};
344}
345
346// Function to dump JSON object into a file
347void Crest::CrestContainer::dumpJsonToFile(const nlohmann::json &j, const std::string &filename)
348{
349 std::ofstream file(filename);
350 if (file.is_open())
351 {
352 file << std::setprecision(6) << j.dump(4);
353 file.close();
354 }
355 else
356 {
357 std::cerr << "CondContainer::dumpJsonToFile: Error opening file: " << filename << std::endl;
358 throw std::runtime_error("CondContainer::dumpJsonToFile: Error opening file.");
359 }
360}
361
362// Function to read file and create JSON object
363nlohmann::json Crest::CrestContainer::readJsonFromFile(const std::string &filename, const std::string &spec_filename)
364{
365
366 std::ifstream specfile(spec_filename);
367 nlohmann::json jspec;
368 if (specfile.is_open())
369 {
370 specfile >> jspec;
371 specfile.close();
372 }
373 else
374 {
375 std::cerr << "CondContainer::readJsonFromFile: Error opening file: " << spec_filename << std::endl;
376 throw std::runtime_error("CondContainer::readJsonFromFile: Error opening file. ");
377 }
378 // Set the payload spec
379 setPayloadSpec(jspec);
380 // Read data file
381 std::ifstream file(filename);
382 nlohmann::json j;
383 if (file.is_open())
384 {
385 file >> j;
386 file.close();
387 }
388 else
389 {
390 std::cerr << "CondContainer::readJsonFromFile: Error opening file: " << filename << std::endl;
391 throw std::runtime_error("CondContainer::readJsonFromFile: Error opening file. ");
392 }
393 return j;
394}
395
396void Crest::CrestContainer::parseOldFormat(const std::string& colName, const TypeId& typespec,const nlohmann::json & thisVal){
397 try{
398 if (thisVal.is_null()){
399 m_row[colName] ="NULL";
400 return;
401 }
402 std::string strVal = to_string(thisVal);
403 if(strVal.size()>2&& strVal[0]=='"'&& strVal[strVal.size()-1]=='"')
404 strVal=strVal.substr(1,strVal.size()-2);
405 if((strVal.compare("NULL")==0||strVal.compare("null")==0)&&
406 (typespec==TypeId::Bool || typespec==TypeId::Int16 || typespec==TypeId::UInt16
407 || typespec==TypeId::Int32 || typespec==TypeId::UInt32
408 || typespec==TypeId::Int64 || typespec==TypeId::UInt63
409 || typespec==TypeId::Float || typespec==TypeId::Double)){
410 m_row[colName] ="NULL";
411 return;
412 }
413 switch (typespec) {
414 case TypeId::Bool:
415 {
416 const bool newVal=(strVal == "true");
417 m_row[colName] = newVal;
418 break;
419 }
420 case TypeId::UChar:
421 {
422 m_row[colName]=std::stoul(strVal);
423 break;
424 }
425 case TypeId::Int16:
426 {
427 m_row[colName]=std::stol(strVal);
428 break;
429 }
430 case TypeId::UInt16:
431 {
432 m_row[colName]=std::stoul(strVal);
433 break;
434 }
435 case TypeId::Int32:
436 {
437 m_row[colName]=std::stoi(strVal);
438 break;
439 }
440 case TypeId::UInt32:
441 {
442 m_row[colName]=std::stoull(strVal);
443 break;
444 }
445 case TypeId::UInt63:
446 {
447 m_row[colName]=std::stoull(strVal);
448 break;
449 }
450 case TypeId::Int64:
451 {
452 m_row[colName]=std::stoll(strVal);
453 break;
454 }
455 case TypeId::Float:
456 {
457 m_row[colName]=std::stof(strVal);
458 break;
459 }
460 case TypeId::Double:
461 {
462 m_row[colName]=std::stod(strVal);
463 break;
464 }
466 case TypeId::String4k:
470 {
471 m_row[colName]=thisVal.get<std::string>();
472 break;
473 }
474 case TypeId::Blob128M:
475 case TypeId::Blob16M:
476 case TypeId::Blob64k:
477 {
478 m_row[colName]=thisVal.get<std::string>();
479 break;
480 }
481 default:
482 {
483 throw std::runtime_error("UNTREATED TYPE!");
484 }
485 }
486
487 }
488 catch(json::exception& e){
489 std::cerr << e.what() << std::endl;
490 throw std::runtime_error(e.what());
491 }
492}
493
494void Crest::CrestContainer::parseData(const nlohmann::json & values){
495 if (values.is_array() && values.size() == m_payload_spec.size())
496 {
497 for (size_t i = 0; i < values.size(); ++i)
498 {
499 const auto & [colName,colType] = m_payload_spec[i];
500 //const std::string & colName = spec.first;
501 //TypeId colType = spec.second;
502 if(values[i].is_string() &&( colType== TypeId::UChar || colType==TypeId::Bool || colType==TypeId::Int16 || colType==TypeId::UInt16
503 || colType==TypeId::Int32 || colType==TypeId::UInt32 || colType==TypeId::Int64 || colType==TypeId::UInt63 || colType==TypeId::Float || colType==TypeId::Double))
504 {
505 parseOldFormat(colName,colType,values[i]);
506 continue;
507 }
508 if(values[i].is_null()){
509 m_row[colName] = nullptr;
510 continue;
511 }
512 switch (colType)
513 {
514 case TypeId::Bool:
515 m_row[colName] = values[i].get<bool>();
516 break;
517 case TypeId::UChar:
518 m_row[colName] = values[i].get<unsigned char>();
519 break;
520 case TypeId::Int16:
521 case TypeId::Int32:
522 m_row[colName] = values[i].get<int>();
523 break;
524 case TypeId::UInt16:
525 case TypeId::UInt32:
526 m_row[colName] = values[i].get<unsigned int>();
527 break;
528 case TypeId::UInt63:
529 m_row[colName] = values[i].get<uint64_t>();
530 break;
531 case TypeId::Int64:
532 m_row[colName] = values[i].get<int64_t>();
533 break;
534 case TypeId::Float:
535 case TypeId::Double:
536 m_row[colName] = values[i].get<double>();
537 break;
539 case TypeId::String4k:
543 m_row[colName] = values[i].get<std::string>();
544 break;
545 case TypeId::Blob128M:
546 case TypeId::Blob64k:
547 case TypeId::Blob16M:
548 m_row[colName] = values[i].get<std::string>();
549 break;
550 default:
551 throw CommonCrestException("CrestContainer::parseData: Unsupported column type.");
552 }
553 }
554 }
555 else
556 {
557 if(!values.is_array())
558 std::cerr << "CrestContainer::parseData values is not array"<<std::endl;
559 else
560 std::cerr << "CrestContainer::parseData values number="<<values.size() << " m_payload_spec.size()="<<m_payload_spec.size()<<std::endl;
561 throw CommonCrestException("CrestContainer::parseData: Mismatch in number of values.");
562 }
563}
564
565std::vector<uint64_t> Crest::CrestContainer::fromJson(uint64_t since,const nlohmann::json &j_in){
567 {
568 nlohmann::json j = j_in;
569 if (j.is_string()){
570 std::istringstream ss(to_string(j));
571 std::string st;
572 ss >> std::quoted(st);
573 j = json::parse(st);
574 }
575 // Accessing the "data" object
576 if (j.contains("data") && j["data"].is_object())
577 {
578 //const auto &data = j["data"];
579 readCommonType(since,j_in);
580 }
581 else if(j.is_object()){
582 readCommonType(since,j);
583 }
584 else
585 {
586 std::cerr << "CrestContainer::fromJson json:"<<j<<std::endl;
587 throw CommonCrestException("CrestContainer::fromJson: JSON is not a JSON object.");
588 }
589 std::vector<uint64_t> ret;
590 ret.push_back(since);
591 return ret;
592 }
594 {
595 return readDcsFullType(j_in);
596 }
597 else
598 {
599 throw CommonCrestException("CrestContainer::fromJson: Unsupported type of payload.");
600 }
601}
602std::vector<uint64_t> Crest::CrestContainer::readDcsFullType(const nlohmann::json &j_in)
603{
604 nlohmann::json j = j_in;
605 if (j.is_string()){
606 std::istringstream ss(to_string(j));
607 std::string st;
608 ss >> std::quoted(st);
609 j = json::parse(st);
610 }
611 nlohmann::json dcs_data;
612 if (j.contains("data") && j["data"].is_object())
613 {
614 dcs_data = j["data"];
615 }
616 else
617 dcs_data=j;
618 std::vector<uint64_t> ret;
619 if(j.is_object())
620 {
621 for (const auto& [key, value] : dcs_data.items()){
622 uint64_t since=std::stoull(key);
623 readCommonType(since,value);
624 ret.push_back(since);
625 }
626 }
627 return ret;
628}
629void Crest::CrestContainer::readCommonType(uint64_t since, const nlohmann::json &j_in)
630{
631 if(j_in.empty()){
632 addIov(since);
633 return;
634 }
635 // Loop over each channel in the data
636 for (const auto &channel : j_in.items())
637 {
638 std::string channelKey = channel.key();
639 const auto &data_ch = channel.value();
640 nlohmann::json vecJson(json::value_t::array);
642 vecJson=data_ch;
643 else
644 vecJson.push_back(data_ch);
645
646 for (const auto &values : vecJson)
647 {
648 parseData(values);
651 }
652 addData(channelKey);
653 }
654 addIov(since);
655}
656
657nlohmann::json Crest::CrestContainer::getStoreSetDto(uint64_t period)
658{
659 nlohmann::json j;
660 nlohmann::json resources = nlohmann::json::array();
662 nlohmann::json storeDto;
663 // Loop over the iov list container to add the data to the storeDto
664 for (const auto& [key, value] : m_full_data)
665 {
666 storeDto["since"] = key;
667 storeDto["data"] = value.dump();
668 storeDto["streamerInfo"] = "";//m_streamer_info_data.dump();
669 resources.push_back(storeDto);
670 }
671 }
673 uint64_t since = getFirstTime();
674 nlohmann::json storeDto;
675 nlohmann::json dcs_payload;
676 nlohmann::json curPayload=m_full_data[since];
677 for (const auto& [key, value] : m_full_data)
678 {
679 curPayload.update(value);
680 dcs_payload[std::to_string(key)]=curPayload;
681 if(period>0 && (key-since)>period){
682 storeDto["since"]=since;
683 storeDto["data"]=dcs_payload.dump();
684 storeDto["streamerInfo"] = "";
685 resources.push_back(storeDto);
686 since=key;
687 dcs_payload={};
688 }
689 }
690 if(dcs_payload.size()>0){
691 storeDto["since"]=since;
692 storeDto["data"]=dcs_payload.dump();
693 storeDto["streamerInfo"] = "";
694 resources.push_back(storeDto);
695 }
696 }
697 j["resources"] = resources;
698 j["format"] = "StoreSetDto";
699 j["datatype"] = "data";
700 j["size"] = resources.size();
701
702 return j;
703}
704
bool compareStrTimestamp(std::string &as, std::string &bs)
Header file for CrestContainer class.
static std::string to_string(const std::vector< T > &v)
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
nlohmann::json json
static Double_t a
static Double_t ss
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
#define x
std::string getJsonPayload()
It returns the json representation of the container.
std::vector< uint64_t > fromJson(uint64_t since, const nlohmann::json &j)
It reads a json object to fill the container.
bool isVectorPayload()
It sets the Vector mode of the container.
int getColumnIndex(const std::string &name)
It returns the index of the column with the given name.
nlohmann::json m_payload
nlohmann::json getStoreSetDto(uint64_t period=-1)
It return StoreSetDto in json format.
void dumpJsonToFile(const nlohmann::json &j, const std::string &filename)
It creates a file with the json representation of the container.
void parseOldFormat(const std::string &colName, const TypeId &typespec, const nlohmann::json &j)
void addIov(const uint64_t since)
It adds an IOV to the json object m_iov_data.
std::string getJsonIovData()
It returns the json representation of the container.
std::vector< std::string > channelIds()
Return list of channel id in string format.
void addRecord(const std::string &name, int number,...)
It adds a record to the payload.
void readCommonType(uint64_t since, const nlohmann::json &j_in)
nlohmann::json getPayloadSpec()
Return payload specification in json format.
void selectIov(const uint64_t since)
It select timestamp as active.
CrestContainer(ModeId mode=ModeId::Standard)
Constructor of CrestContainer.
uint64_t getFirstTime()
It return minimal timestamp in concainer.
void addColumn(const std::string &name, TypeId type)
It adds a column to the payload specification.
const nlohmann::json & getIovData()
Return selected IOV in json format.
void addExternalData(const std::string &channel_id, const nlohmann::json &data)
It associate the payload row to a channel_id.
nlohmann::json m_vector_data
nlohmann::json m_iov_data
const nlohmann::json getPayloadChannel(const std::string &channel_id)
Return payload in json format for selected channel id.
std::vector< std::pair< std::string, TypeId > > m_payload_spec
void parseData(const nlohmann::json &values)
It reads a json object, parse it and fill the container.
void addNullRecord(const std::string &name)
It adds a null value to the payload.
~CrestContainer()
Destructor of CrestContainer.
const std::vector< std::pair< std::string, TypeId > > & getMPayloadSpec()
Return tag specification in vector format.
std::map< uint64_t, nlohmann::json > m_full_data
void flush()
It reinitializes the containers.
nlohmann::json createRowArray(const nlohmann::json &data_row) const
const nlohmann::json & getPayload()
Return current payload in json format.
void setPayloadSpec(const nlohmann::json &j)
std::vector< uint64_t > readDcsFullType(const nlohmann::json &j_in)
const nlohmann::json & getRow()
void setIovData(const nlohmann::json &j)
void clear()
It clear data the container.
void addData(const std::string &channel_id)
It associate the payload row to a channel_id.
void putRow2Vector()
It adds row data to vector.
nlohmann::json readJsonFromFile(const std::string &filename, const std::string &spec_filename)
It reads a json file and returns the json object.
void setPayload(const nlohmann::json &j)
void setVectorPayload(bool isVectorPayload)
Set the Vectore mode of the container.
static const std::map< TypeId, std::string > s_typeToString
MsgStream & msg
Definition testRead.cxx:32
TFile * file
std::string number(const double &d, const std::string &s)
Definition utils.cxx:186