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