171 std::unordered_map<std::string, bool> accountedSpecs;
172 auto defHost = options.
get<std::string>(
"condition-backend");
173 auto checkRate = options.
get<
int>(
"condition-tf-per-query");
174 auto checkMult = options.
get<
int>(
"condition-tf-per-query-multiplier");
175 helper.useTFSlice = options.
get<
int>(
"condition-use-slice-for-prescaling");
176 helper.timeToleranceMS = options.
get<int64_t>(
"condition-time-tolerance");
177 helper.queryPeriodGlo = checkRate > 0 ? checkRate : std::numeric_limits<int>::max();
178 helper.queryPeriodFactor = checkMult == 0 ? 1 : checkMult;
179 std::string extraCond{};
180 if (helper.useTFSlice) {
181 extraCond =
". Use TFSlice";
182 if (helper.useTFSlice > 0) {
183 extraCond += fmt::format(
" + max TFcounter jump <= {}", helper.useTFSlice);
186 LOGP(info,
"CCDB Backend at: {}, validity check for every {} TF{}{}", defHost, helper.queryPeriodGlo,
187 helper.queryPeriodFactor == 1 ? std::string{} : (helper.queryPeriodFactor > 0 ? fmt::format(
", (query for high-rate objects downscaled by {})", helper.queryPeriodFactor) : fmt::format(
", (query downscaled as TFcounter%{})", -helper.queryPeriodFactor)),
189 LOGP(info,
"Hook to enable signposts for CCDB messages at {}", (
void*)&private_o2_log_ccdb->stacktrace);
190 auto remapString = options.
get<std::string>(
"condition-remap");
192 if (!
result.error.empty()) {
195 helper.remappings =
result.remappings;
196 helper.apis[
""].init(defHost);
197 LOGP(info,
"Initialised default CCDB host {}", defHost);
199 for (
auto&
entry : helper.remappings) {
200 if (helper.apis.find(
entry.second) == helper.apis.end()) {
202 LOGP(info,
"Initialised custom CCDB host {}",
entry.second);
204 LOGP(info,
"{} is remapped to {}",
entry.first,
entry.second);
206 helper.createdNotBefore =
std::to_string(options.
get<int64_t>(
"condition-not-before"));
207 helper.createdNotAfter =
std::to_string(options.
get<int64_t>(
"condition-not-after"));
209 for (
auto& route : outputRoutes) {
210 if (route.matcher.lifetime != Lifetime::Condition) {
214 if (accountedSpecs.find(specStr) != accountedSpecs.end()) {
217 accountedSpecs[specStr] =
true;
218 helper.routes.push_back(route);
220 for (
auto& metadata : route.matcher.metadata) {
222 LOGP(info,
"- {}: {}", metadata.name, metadata.defaultValue.asString());
258 std::string ccdbMetadataPrefix =
"ccdb-metadata-";
265 O2_SIGNPOST_START(ccdb, sid,
"populateCacheWith",
"Starting to populate cache with CCDB objects");
266 for (
auto& route : helper->routes) {
267 int64_t timestampToUse = timestamp;
272 auto&&
v = allocator.makeVector<
char>(
output);
273 std::map<std::string, std::string> metadata;
274 std::map<std::string, std::string> headers;
275 std::string
path =
"";
276 std::string
etag =
"";
277 int chRate = helper->queryPeriodGlo;
278 bool checkValidity =
false;
279 for (
auto& meta : route.matcher.metadata) {
280 if (meta.name ==
"ccdb-path") {
281 path = meta.defaultValue.get<std::string>();
282 }
else if (meta.name ==
"ccdb-run-dependent" && meta.defaultValue.get<
int>() > 0) {
283 if (meta.defaultValue.get<
int>() == 1) {
284 metadata[
"runNumber"] = dtc.runNumber;
285 }
else if (meta.defaultValue.get<
int>() == 2) {
286 timestampToUse = std::stoi(dtc.runNumber);
288 LOGP(fatal,
"Undefined ccdb-run-dependent option {} for spec {}/{}/{}", meta.defaultValue.get<
int>(), concrete.origin.as<std::string>(), concrete.description.as<std::string>(),
int(concrete.subSpec));
290 }
else if (
isPrefix(ccdbMetadataPrefix, meta.name)) {
291 std::string
key = meta.name.substr(ccdbMetadataPrefix.size());
292 auto value = meta.defaultValue.get<std::string>();
295 }
else if (meta.name ==
"ccdb-query-rate") {
296 chRate = std::max(1, meta.defaultValue.get<
int>()) * helper->queryPeriodFactor;
299 const auto url2uuid = helper->mapURL2UUID.find(
path);
300 if (url2uuid != helper->mapURL2UUID.end()) {
301 etag = url2uuid->second.etag;
303 uint64_t validUntil = url2uuid->second.cacheValidUntil;
308 bool cacheExpired = (validUntil <= timestampToUse) || (timestamp <
cachePopulatedAt);
309 if (isOnline || cacheExpired) {
310 if (!helper->useTFSlice) {
311 checkValidity = chRate > 0 ? (std::abs(
int(timingInfo.tfCounter - url2uuid->second.lastCheckedTF)) >= chRate) : (timingInfo.tfCounter % -chRate) == 0;
313 checkValidity = chRate > 0 ? (std::abs(
int(timingInfo.timeslice - url2uuid->second.lastCheckedSlice)) >= chRate) : (timingInfo.timeslice % -chRate) == 0;
314 if (!checkValidity && helper->useTFSlice > std::abs(chRate)) {
315 checkValidity = std::abs(
int(timingInfo.tfCounter) - url2uuid->second.lastCheckedTF) > helper->useTFSlice;
320 checkValidity =
true;
323 O2_SIGNPOST_EVENT_EMIT(ccdb, sid,
"populateCacheWith",
"checkValidity is %{public}s for tf%{public}s %zu of %{public}s", checkValidity ?
"true" :
"false", helper->useTFSlice ?
"ID" :
"Slice", helper->useTFSlice ? timingInfo.timeslice : timingInfo.tfCounter,
path.data());
325 const auto& api = helper->getAPI(
path);
326 if (checkValidity && (!api.isSnapshotMode() ||
etag.empty())) {
327 LOGP(detail,
"Loading {} for timestamp {}",
path, timestampToUse);
328 api.loadFileToMemory(
v,
path, metadata, timestampToUse, &headers,
etag, helper->createdNotAfter, helper->createdNotBefore);
329 if ((headers.count(
"Error") != 0) || (
etag.empty() &&
v.empty())) {
330 LOGP(fatal,
"Unable to find CCDB object {}/{}",
path, timestampToUse);
335 if (headers.find(
"default") != headers.end()) {
336 LOGP(detail,
"******** Default entry used for {} ********",
path);
338 helper->mapURL2UUID[
path].lastCheckedTF = timingInfo.tfCounter;
339 helper->mapURL2UUID[
path].lastCheckedSlice = timingInfo.timeslice;
341 helper->mapURL2UUID[
path].etag = headers[
"ETag"];
342 helper->mapURL2UUID[
path].cachePopulatedAt = timestampToUse;
343 helper->mapURL2UUID[
path].cacheMiss++;
344 helper->mapURL2UUID[
path].size =
v.size();
345 helper->mapURL2UUID[
path].minSize = std::min(
v.size(), helper->mapURL2UUID[
path].minSize);
346 helper->mapURL2UUID[
path].maxSize = std::max(
v.size(), helper->mapURL2UUID[
path].maxSize);
347 helper->totalFetchedBytes +=
v.size();
348 helper->totalRequestedBytes +=
v.size();
349 api.appendFlatHeader(
v, headers);
351 helper->mapURL2DPLCache[
path] = cacheId;
352 O2_SIGNPOST_EVENT_EMIT(ccdb, sid,
"populateCacheWith",
"Caching %{public}s for %{public}s (DPL id %" PRIu64
")",
path.data(), headers[
"ETag"].data(), cacheId.value);
357 helper->mapURL2UUID[
path].etag = headers[
"ETag"];
358 helper->mapURL2UUID[
path].cachePopulatedAt = timestampToUse;
359 helper->mapURL2UUID[
path].cacheValidUntil = headers[
"Cache-Valid-Until"].empty() ? 0 : std::stoul(headers[
"Cache-Valid-Until"]);
360 helper->mapURL2UUID[
path].cacheMiss++;
361 helper->mapURL2UUID[
path].size =
v.size();
362 helper->mapURL2UUID[
path].minSize = std::min(
v.size(), helper->mapURL2UUID[
path].minSize);
363 helper->mapURL2UUID[
path].maxSize = std::max(
v.size(), helper->mapURL2UUID[
path].maxSize);
364 helper->totalFetchedBytes +=
v.size();
365 helper->totalRequestedBytes +=
v.size();
366 api.appendFlatHeader(
v, headers);
368 helper->mapURL2DPLCache[
path] = cacheId;
369 O2_SIGNPOST_EVENT_EMIT(ccdb, sid,
"populateCacheWith",
"Caching %{public}s for %{public}s (DPL id %" PRIu64
")",
path.data(), headers[
"ETag"].data(), cacheId.value);
375 helper->mapURL2UUID[
path].cacheValidUntil = headers[
"Cache-Valid-Until"].empty() ? 0 : std::stoul(headers[
"Cache-Valid-Until"]);
379 auto cacheId = helper->mapURL2DPLCache[
path];
380 O2_SIGNPOST_EVENT_EMIT(ccdb, sid,
"populateCacheWith",
"Reusing %{public}s for %{public}s (DPL id %" PRIu64
")",
path.data(), headers[
"ETag"].data(), cacheId.value);
381 helper->mapURL2UUID[
path].cacheHit++;
382 helper->totalRequestedBytes += helper->mapURL2UUID[
path].size;
386 O2_SIGNPOST_END(ccdb, sid,
"populateCacheWith",
"Finished populating cache with CCDB objects");
392 std::shared_ptr<CCDBFetcherHelper> helper = std::make_shared<CCDBFetcherHelper>();
397 LOGP(info,
"CCDB cache miss/hit ratio ({} fetched / {} requested bytes):", helper->totalFetchedBytes, helper->totalRequestedBytes);
398 for (
auto&
entry : helper->mapURL2UUID) {
399 LOGP(info,
" {}: {}/{} ({}-{} bytes)",
entry.first,
entry.second.cacheMiss,
entry.second.cacheHit,
entry.second.minSize,
entry.second.maxSize);
405 O2_SIGNPOST_START(ccdb, sid,
"fetchFromCCDB",
"Fetching CCDB objects for timeslice %" PRIu64, (uint64_t)timingInfo.
timeslice);
406 static Long64_t orbitResetTime = -1;
407 static size_t lastTimeUsed = -1;
409 LOGP(info,
"Dummy creation time is not supported for CCDB objects. Setting creation to last one used {}.", lastTimeUsed);
415 const std::string
path =
"CTP/Calib/OrbitReset";
416 std::map<std::string, std::string> metadata;
417 std::map<std::string, std::string> headers;
420 bool checkValidity = std::abs(
int(
counter - helper->lastCheckedTFCounterOrbReset)) >= helper->queryPeriodGlo;
421 const auto url2uuid = helper->mapURL2UUID.find(
path);
422 if (url2uuid != helper->mapURL2UUID.end()) {
423 etag = url2uuid->second.etag;
425 checkValidity =
true;
427 O2_SIGNPOST_EVENT_EMIT(ccdb, sid,
"fetchFromCCDB",
"checkValidity is %{public}s for tf%{public}s %d of %{public}s",
428 checkValidity ?
"true" :
"false", helper->useTFSlice ?
"ID" :
"Slice",
counter,
path.data());
430 Long64_t newOrbitResetTime = orbitResetTime;
432 const auto& api = helper->getAPI(
path);
433 if (checkValidity && (!api.isSnapshotMode() ||
etag.empty())) {
434 helper->lastCheckedTFCounterOrbReset =
counter;
435 api.loadFileToMemory(
v,
path, metadata, timingInfo.
creation, &headers,
etag, helper->createdNotAfter, helper->createdNotBefore);
436 if ((headers.count(
"Error") != 0) || (
etag.empty() &&
v.empty())) {
437 LOGP(fatal,
"Unable to find CCDB object {}/{}",
path, timingInfo.
creation);
442 helper->mapURL2UUID[
path].etag = headers[
"ETag"];
443 helper->mapURL2UUID[
path].cacheMiss++;
444 helper->mapURL2UUID[
path].size =
v.size();
445 helper->mapURL2UUID[
path].minSize = std::min(
v.size(), helper->mapURL2UUID[
path].minSize);
446 helper->mapURL2UUID[
path].maxSize = std::max(
v.size(), helper->mapURL2UUID[
path].maxSize);
447 helper->totalFetchedBytes +=
v.size();
448 helper->totalRequestedBytes +=
v.size();
450 api.appendFlatHeader(
v, headers);
452 helper->mapURL2DPLCache[
path] = cacheId;
453 O2_SIGNPOST_EVENT_EMIT(ccdb, sid,
"fetchFromCCDB",
"Caching %{public}s for %{public}s (DPL id %" PRIu64
")",
path.data(), headers[
"ETag"].data(), cacheId.value);
454 }
else if (
v.size()) {
456 helper->mapURL2UUID[
path].etag = headers[
"ETag"];
457 helper->mapURL2UUID[
path].cacheMiss++;
458 helper->mapURL2UUID[
path].size =
v.size();
459 helper->mapURL2UUID[
path].minSize = std::min(
v.size(), helper->mapURL2UUID[
path].minSize);
460 helper->mapURL2UUID[
path].maxSize = std::max(
v.size(), helper->mapURL2UUID[
path].maxSize);
461 helper->totalFetchedBytes +=
v.size();
462 helper->totalRequestedBytes +=
v.size();
464 api.appendFlatHeader(
v, headers);
466 helper->mapURL2DPLCache[
path] = cacheId;
467 O2_SIGNPOST_EVENT_EMIT(ccdb, sid,
"fetchFromCCDB",
"Caching %{public}s for %{public}s (DPL id %" PRIu64
")",
path.data(), headers[
"ETag"].data(), cacheId.value);
473 auto cacheId = helper->mapURL2DPLCache[
path];
474 O2_SIGNPOST_EVENT_EMIT(ccdb, sid,
"fetchFromCCDB",
"Reusing %{public}s for %{public}s (DPL id %" PRIu64
")",
path.data(), headers[
"ETag"].data(), cacheId.value);
475 helper->mapURL2UUID[
path].cacheHit++;
476 helper->totalRequestedBytes += helper->mapURL2UUID[
path].size;
479 if (newOrbitResetTime != orbitResetTime) {
480 O2_SIGNPOST_EVENT_EMIT(ccdb, sid,
"fetchFromCCDB",
"Orbit reset time changed from %lld to %lld", orbitResetTime, newOrbitResetTime);
481 orbitResetTime = newOrbitResetTime;
487 if (std::abs(int64_t(timingInfo.
creation) - timestamp) > helper->timeToleranceMS) {
488 static bool notWarnedYet =
true;
490 LOGP(warn,
"timestamp {} for orbit {} and orbit reset time {} differs by >{} from the TF creation time {}, use the latter", timestamp, timingInfo.
firstTForbit, orbitResetTime / 1000, helper->timeToleranceMS, timingInfo.
creation);
491 notWarnedYet =
false;
498 O2_SIGNPOST_EVENT_EMIT(ccdb, sid,
"fetchFromCCDB",
"Fetching objects. Run %{public}s. OrbitResetTime %lld. Creation %lld. Timestamp %lld. firstTForbit %" PRIu32,
#define O2_DECLARE_DYNAMIC_LOG(name)
#define O2_SIGNPOST_END(log, id, name, format,...)
#define O2_SIGNPOST_EVENT_EMIT(log, id, name, format,...)
#define O2_SIGNPOST_START(log, id, name, format,...)
long orbitResetTimeMUS
The start time of the first orbit in microseconds(!)
DeploymentMode deploymentMode
Where we thing this is running.