99// granted to it by virtue of its status as an Intergovernmental Organization
1010// or submit itself to any jurisdiction.
1111
12- #include " CCDB/CcdbApi.h"
1312#include < boost/program_options.hpp>
1413#include < ctime>
14+ #include < fstream>
15+ #include < iterator>
1516#include < numeric>
1617#include < regex>
18+ #include < set>
1719#include < string>
1820#include < vector>
21+ #include " CCDB/CcdbApi.h"
1922#include " DataFormatsMCH/DsChannelId.h"
2023#include " MCHConditions/DCSAliases.h"
2124#include " MCHConstants/DetectionElements.h"
@@ -33,20 +36,105 @@ std::string ccdbPath(const std::string badChannelType)
3336 return fmt::format (" MCH/Calib/{}" , badChannelType);
3437}
3538
36- void queryBadChannels (const std::string ccdbUrl,
37- const std::string badChannelType, uint64_t timestamp, bool verbose)
39+ std::set<uint64_t > listTSWhenBadChannelsChange (const std::string ccdbUrl, const std::string badChannelType,
40+ uint64_t startTimestamp, uint64_t endTimestamp, bool verbose)
41+ {
42+ std::set<uint64_t > tsChanges{startTimestamp};
43+
44+ std::cout << std::endl;
45+ o2::ccdb::CcdbApi api;
46+ api.init (ccdbUrl);
47+ auto source = ccdbPath (badChannelType);
48+
49+ // store every timestamps in the time range when the bad channels potentially change
50+ if (verbose) {
51+ std::cout << fmt::format (" \n list of {} files potentially valid in the range {} - {}:\n " , source, startTimestamp, endTimestamp);
52+ }
53+ std::istringstream fileInfo (api.list (source, false , " text/plain" ));
54+ std::string dummy{};
55+ std::string path{};
56+ uint64_t begin = 0 ;
57+ uint64_t end = 0 ;
58+ uint64_t creation = 0 ;
59+ bool inRange = false ;
60+ for (std::string line; std::getline (fileInfo, line);) {
61+ if (line.find (" Validity:" ) == 0 ) {
62+ std::istringstream in (line);
63+ in >> dummy >> begin >> dummy >> end;
64+ if (begin < endTimestamp && end > startTimestamp) {
65+ if (begin >= startTimestamp) {
66+ tsChanges.emplace (begin);
67+ }
68+ if (end < endTimestamp) {
69+ tsChanges.emplace (end);
70+ }
71+ inRange = true ;
72+ }
73+ } else if (verbose) {
74+ if (line.find (" ID:" ) == 0 ) {
75+ std::istringstream in (line);
76+ in >> dummy >> path;
77+ } else if (inRange && line.find (" Created:" ) == 0 ) {
78+ std::istringstream in (line);
79+ in >> dummy >> creation;
80+ std::cout << fmt::format (" - {}\n " , path);
81+ std::cout << fmt::format (" validity range: {} - {}\n " , begin, end);
82+ std::cout << fmt::format (" creation time: {}\n " , creation);
83+ inRange = false ;
84+ }
85+ }
86+ }
87+ if (verbose) {
88+ std::cout << fmt::format (" \n list of timestamps when the bad channels potentially change:\n " );
89+ for (auto ts : tsChanges) {
90+ std::cout << fmt::format (" {}\n " , ts);
91+ }
92+ }
93+
94+ // select timestamps when the bad channels actually change
95+ if (verbose) {
96+ std::cout << fmt::format (" \n list of {} files actually valid in the range {} - {}:\n " , source, startTimestamp, endTimestamp);
97+ }
98+ std::map<std::string, std::string> metadata{};
99+ std::string currentETag{};
100+ for (auto itTS = tsChanges.begin (); itTS != tsChanges.end ();) {
101+ auto headers = api.retrieveHeaders (source, metadata, *itTS);
102+ if (headers[" ETag" ] == currentETag) {
103+ itTS = tsChanges.erase (itTS);
104+ } else {
105+ if (verbose) {
106+ std::cout << fmt::format (" - {}\n " , headers[" Location" ]);
107+ std::cout << fmt::format (" validity range: {} - {}\n " , headers[" Valid-From" ], headers[" Valid-Until" ]);
108+ std::cout << fmt::format (" creation time: {}\n " , headers[" Created" ]);
109+ }
110+ currentETag = headers[" ETag" ];
111+ ++itTS;
112+ }
113+ }
114+ std::cout << fmt::format (" \n list of timestamps when the bad channels actually change:\n " );
115+ for (auto ts : tsChanges) {
116+ std::cout << fmt::format (" {}\n " , ts);
117+ }
118+
119+ return tsChanges;
120+ }
121+
122+ BadChannelsVector queryBadChannels (const std::string ccdbUrl,
123+ const std::string badChannelType, uint64_t timestamp, bool verbose)
38124{
125+ std::cout << std::endl;
39126 o2::ccdb::CcdbApi api;
40127 api.init (ccdbUrl);
41128 std::map<std::string, std::string> metadata;
42129 auto source = ccdbPath (badChannelType);
43- auto * badChannels = api.retrieveFromTFileAny <BadChannelsVector>(source. c_str () , metadata, timestamp);
130+ auto * badChannels = api.retrieveFromTFileAny <BadChannelsVector>(source, metadata, timestamp);
44131 std::cout << " number of bad channels = " << badChannels->size () << std::endl;
45132 if (verbose) {
46133 for (const auto & badChannel : *badChannels) {
47134 std::cout << badChannel.asString () << " \n " ;
48135 }
49136 }
137+ return *badChannels;
50138}
51139
52140void rejectDS (const o2::mch::raw::DsDetId& dsDetId, BadChannelsVector& bv)
@@ -124,13 +212,13 @@ void uploadBadChannels(const std::string ccdbUrl,
124212 const BadChannelsVector& bv,
125213 bool makeDefault)
126214{
215+ std::cout << std::endl;
127216 o2::ccdb::CcdbApi api;
128217 api.init (ccdbUrl);
129218 std::map<std::string, std::string> md;
130219 auto dest = ccdbPath (badChannelType);
131- std::cout << " storing default MCH bad channels (valid from "
132- << startTimestamp << " to " << endTimestamp << " ) to "
133- << dest << " \n " ;
220+ std::cout << fmt::format (" storing {} {}bad channels (valid from {} to {}) to {}\n " , bv.size (),
221+ makeDefault ? " default " : " " , startTimestamp, endTimestamp, dest);
134222
135223 if (makeDefault) {
136224 md[" default" ] = " true" ;
@@ -145,10 +233,12 @@ int main(int argc, char** argv)
145233 po::options_description usage (" Usage" );
146234
147235 std::string ccdbUrl;
236+ std::string ccdbRefUrl;
148237 std::string dpConfName;
149238 std::string badChannelType;
150239 uint64_t startTimestamp;
151240 uint64_t endTimestamp;
241+ bool list;
152242 bool put;
153243 bool query;
154244 bool verbose;
@@ -165,9 +255,11 @@ int main(int argc, char** argv)
165255 usage.add_options ()
166256 (" help,h" , " produce help message" )
167257 (" ccdb,c" ,po::value<std::string>(&ccdbUrl)->default_value (" http://localhost:6464" )," ccdb url" )
168- (" starttimestamp,st" ,po::value<uint64_t >(&startTimestamp)->default_value (now)," timestamp for query or put - (default=now)" )
169- (" endtimestamp,et" , po::value<uint64_t >(&endTimestamp)->default_value (end), " end of validity (for put) - default=1 day from now" )
170- (" put,p" ,po::bool_switch (&put)," upload bad channel default object" )
258+ (" starttimestamp" ,po::value<uint64_t >(&startTimestamp)->default_value (now)," timestamp for query or put - (default=now)" )
259+ (" endtimestamp" , po::value<uint64_t >(&endTimestamp)->default_value (end), " end of validity (for put) - default=1 day from now" )
260+ (" list,l" , po::bool_switch (&list)," list timestamps, within the given range, when the bad channels change" )
261+ (" put,p" ,po::bool_switch (&put)," upload bad channel object" )
262+ (" referenceccdb,r" ,po::value<std::string>(&ccdbRefUrl)->default_value (" http://alice-ccdb.cern.ch" )," reference ccdb url" )
171263 (" upload-default-values,u" ,po::bool_switch (&uploadDefault)," upload default values" )
172264 (" type,t" ,po::value<std::string>(&badChannelType)->default_value (" BadChannel" )," type of bad channel (BadChannel or RejectList)" )
173265 (" query,q" ,po::bool_switch (&query)," dump bad channel object from CCDB" )
@@ -202,6 +294,10 @@ int main(int argc, char** argv)
202294 exit (2 );
203295 }
204296
297+ if (list) {
298+ auto tsChanges = listTSWhenBadChannelsChange (ccdbUrl, badChannelType, startTimestamp, endTimestamp, verbose);
299+ }
300+
205301 if (query) {
206302 queryBadChannels (ccdbUrl, badChannelType, startTimestamp, verbose);
207303 }
@@ -221,7 +317,39 @@ int main(int argc, char** argv)
221317 rejectHVLVs (vm[" alias" ].as <std::vector<std::string>>(), bv);
222318 }
223319
224- uploadBadChannels (ccdbUrl, badChannelType, startTimestamp, endTimestamp, bv, uploadDefault);
320+ if (uploadDefault) {
321+ uploadBadChannels (ccdbUrl, badChannelType, startTimestamp, endTimestamp, bv, true );
322+ } else {
323+ auto tsChanges = listTSWhenBadChannelsChange (ccdbRefUrl, badChannelType, startTimestamp, endTimestamp, false );
324+
325+ std::cout << fmt::format (" \n {} object{} valid in the reference CCDB ({}) for this time range. What do you want to do?\n " ,
326+ tsChanges.size (), (tsChanges.size () > 1 ) ? " s are" : " is" , ccdbRefUrl);
327+ std::cout << fmt::format (" [a] abort: do nothing\n " );
328+ std::cout << fmt::format (" [o] overwrite: create 1 new object for the whole time range to supersede the existing one{}\n " ,
329+ (tsChanges.size () > 1 ) ? " s" : " " );
330+ std::cout << fmt::format (" [u] update: create {} new object{} within the time range adding new bad channels to existing ones\n " ,
331+ tsChanges.size (), (tsChanges.size () > 1 ) ? " s" : " " );
332+ std::string response{};
333+ std::cin >> response;
334+
335+ if (response == " a" || response == " abort" ) {
336+ return 0 ;
337+ } else if (response == " o" || response == " overwrite" ) {
338+ uploadBadChannels (ccdbUrl, badChannelType, startTimestamp, endTimestamp, bv, false );
339+ } else if (response == " u" || response == " update" ) {
340+ tsChanges.emplace (endTimestamp);
341+ auto itStartTS = tsChanges.begin ();
342+ for (auto itStopTS = std::next (itStartTS); itStopTS != tsChanges.end (); ++itStartTS, ++itStopTS) {
343+ auto bv2 = queryBadChannels (ccdbRefUrl, badChannelType, *itStartTS, false );
344+ bv2.insert (bv2.end (), bv.begin (), bv.end ());
345+ uploadBadChannels (ccdbUrl, badChannelType, *itStartTS, *itStopTS, bv2, false );
346+ }
347+ } else {
348+ std::cout << " invalid response (must be a, o or u) --> abort\n " ;
349+ exit (3 );
350+ }
351+ }
225352 }
353+
226354 return 0 ;
227355}
0 commit comments