Skip to content

Commit 8a7ef25

Browse files
authored
add possibility to update existing objects (#13341)
1 parent 1e78fb8 commit 8a7ef25

File tree

2 files changed

+147
-15
lines changed

2 files changed

+147
-15
lines changed

Detectors/MUON/MCH/Conditions/README.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ Usage:
3030
(default=now)
3131
--endtimestamp arg (=1677773918645) end of validity (for put) - default=1
3232
day from now
33-
-p [ --put ] upload bad channel default object
33+
-l [ --list ] list timestamps, within the given
34+
range, when the bad channels change
35+
-p [ --put ] upload bad channel object
36+
-r [ --referenceccdb ] arg (=http://alice-ccdb.cern.ch)
37+
reference ccdb url
3438
-u [ --upload-default-values ] upload default values
3539
-t [ --type ] arg (=BadChannel) type of bad channel (BadChannel or
3640
RejectList)
@@ -40,12 +44,12 @@ Usage:
4044
-d [ --ds ] arg dual sampas indices to reject
4145
-e [ --de ] arg DE ids to reject
4246
-a [ --alias ] arg DCS alias (HV or LV) to reject
43-
4447
```
4548

46-
For instance, to create a debug RejectList object which declares solar number 32 as bad within a local CCDB, from Tuesday 1 November 2022 00:00:01 UTC to Saturday 31 December 2022 23:59:59, use :
49+
For instance, to create in a local CCDB a RejectList object which declares solar number 32 as bad, from Tuesday 1 November 2022 00:00:01 UTC to Saturday 31 December 2022 23:59:59, use :
4750

4851
```shell
4952
$ o2-mch-bad-channels-ccdb -p -s 32 -t RejectList --starttimestamp 1667260801000 --endtimestamp 1672531199000
50-
storing default MCH bad channels (valid from 1667260801000 to 1672531199000) to MCH/Calib/RejectList
5153
```
54+
55+
The program will search the reference CCDB (defined with `--referenceccdb`) for existing objects valid during this period and propose you to either overwrite them or update them. In the first case, a single object will be created, valid for the whole period, containing only the new bad channels. In the second case, as many objects as necessary will be created with appropriate validity ranges, adding the new bad channels to the existing ones.

Detectors/MUON/MCH/Conditions/src/bad-channels-ccdb.cxx

Lines changed: 139 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@
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("\nlist 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("\nlist 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("\nlist 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("\nlist 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

52140
void 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

Comments
 (0)