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