ATLAS Offline Software
Loading...
Searching...
No Matches
IOVDbMetaDataTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
15
16#include "IOVDbMetaDataTool.h"
17
18#include "GaudiKernel/IIncidentSvc.h"
19#include "GaudiKernel/FileIncident.h"
20#include "GaudiKernel/EventIDBase.h"
21#include "GaudiKernel/EventIDRange.h"
22
32#include "CoralBase/AttributeListSpecification.h"
33#include "nlohmann/json.hpp"
34
35
37 const std::string& name,
38 const IInterface* parent)
39 : base_class(type, name, parent)
40 , m_metaDataStore ("StoreGateSvc/MetaDataStore", name)
41 , m_inputStore ("StoreGateSvc/InputMetaDataStore", name)
42 , m_condStore ("StoreGateSvc/ConditionStore", name)
43 , m_overrideRunNumber(false)
49 , m_modifyFolders(false)
50{
51}
52
53//--------------------------------------------------------------------------
56
57
58//--------------------------------------------------------------------------
59
61{
62 ATH_MSG_DEBUG("in initialize()");
63
64 // Set to be listener for FirstInputFile
65 ServiceHandle<IIncidentSvc> incSvc("IncidentSvc", this->name());
66 ATH_CHECK(incSvc.retrieve());
67 incSvc->addListener(this, "FirstInputFile", 60); // pri has to be < 100 to be after MetaDataSvc.
68
69 // locate the meta data stores
70 ATH_CHECK(m_metaDataStore.retrieve());
71 ATH_CHECK(m_inputStore.retrieve());
72
73 // Check whether folders need to be modified
75 ATH_MSG_DEBUG("initialize(): " << (m_modifyFolders ? "" : "No ") << "need to modify folders");
76
77 // Process direct payloads if configured
78 if (!m_payloads.value().empty()) {
79 // Group by folder: parse "folder:key" format from flat map
80 std::map<std::string, std::map<std::string, std::string>> folderPayloads;
81
82 for (const auto& [key, value] : m_payloads.value()) {
83 // Split key on ':' to get folder and parameter name
84 size_t colonPos = key.find(':');
85 if (colonPos == std::string::npos) {
86 ATH_MSG_ERROR("Invalid payload key format: " << key << " (expected 'folder:key')");
87 return StatusCode::FAILURE;
88 }
89
90 std::string folderName = key.substr(0, colonPos);
91 std::string paramName = key.substr(colonPos + 1);
92 folderPayloads[folderName][paramName] = value;
93 }
94 // before going into loop, prepare these strings
95 static const std::string beginRunKey{"beginRun"};
96 static const std::string endRunKey{"endRun"};
97 static const std::string specType{"string"};
98 //
99 //..and this predicate when building an AttributeListSpecification
100 const auto isIOVKey = [](const std::string& key) {
101 return key == beginRunKey || key == endRunKey;
102 };
103 ATH_MSG_DEBUG("Processing " << folderPayloads.size() << " folder(s) for direct payload registration");
104 for (const auto& [folderName, parameters] : folderPayloads) {
105 //will use these twice, so only search once and cache them
106 auto beginRunItr = parameters.find(beginRunKey);
107 auto endRunItr = parameters.find(endRunKey);
108 if ( (beginRunItr == parameters.end()) || (endRunItr == parameters.end()) ) {
109 ATH_MSG_ERROR("Payload for folder " << folderName << " missing beginRun or endRun");
110 return StatusCode::FAILURE;
111 }
112 // Extract beginRun and endRun from parameters
113 unsigned int beginRun = std::stoul(beginRunItr->second);
114 unsigned int endRun = std::stoul(endRunItr->second);
115
116 ATH_MSG_DEBUG("Registering folder " << folderName << " with " << parameters.size() - 2
117 << " parameters, IOV [" << beginRun << ", " << endRun << "]");
118
119 // Parameter folders are read back as a single AthenaAttributeList, so use that
120 // description (clid 40774348) rather than the CondAttrListCollection default.
121 static const std::string attrListDescr{"<timeStamp>run-event</timeStamp><addrHeader><address_header service_type=\"71\" clid=\"40774348\" /></addrHeader><typeName>AthenaAttributeList</typeName>"};
122 ATH_CHECK(registerFolder(folderName, attrListDescr));
123
124 // Build payload for MetaDataStore
125 // Note: AttributeListSpecification has protected destructor, must use new
126 // The AttributeList constructor with 'true' takes ownership and will call release()
127 coral::AttributeListSpecification* spec = new coral::AttributeListSpecification();
128 for (const auto& [key, value] : parameters) {
129 if (!isIOVKey(key)) {
130 spec->extend(key, specType);
131 }
132 }
133
134 coral::AttributeList attrList(*spec, true);
135 for (const auto& [key, value] : parameters) {
136 if (!isIOVKey(key)) {
137 attrList[key].setValue(value);
138 }
139 }
140
141 // Magic channel 0xFFFF + per-channel IOV: read back as AthenaAttributeList,
142 // matching IOVDbFolder::addMetaAttrList.
143 auto payload = std::make_unique<CondAttrListCollection>(true);
144 const IOVRange range(IOVTime(beginRun, 0), IOVTime(endRun, IOVTime::MAXEVENT));
145 payload->add(0xFFFF, attrList);
146 payload->add(0xFFFF, range);
147
148 ATH_MSG_DEBUG("Created payload with IOV [" << beginRun << ", " << endRun << "]");
149
150 // Add to MetaDataStore
151 ATH_CHECK(addPayload(folderName, payload.release()));
152 }
153
154 // Note: ConditionStore population is NOT done here because during initialize()
155 // there is no valid EventContext, which is required for CondCont::insert().
156 // Instead, use MetaDataToCondAlg (configured via MetaDataToCondAlgCfg) to populate
157 // ConditionStore during event processing when a valid EventContext is available.
158 }
159
160 return(StatusCode::SUCCESS);
161}
162
163//--------------------------------------------------------------------------
164
165StatusCode
167{
168 return StatusCode::SUCCESS;
169}
170
171//--------------------------------------------------------------------------
172
173void IOVDbMetaDataTool::handle(const Incident& inc)
174{
175 const FileIncident* fileInc = dynamic_cast<const FileIncident*>(&inc);
176 if(!fileInc) throw std::runtime_error("Unable to get FileName from FirstInputFile incident");
177
178 const std::string fileName = fileInc->fileName();
179 ATH_MSG_DEBUG("handle() " << inc.type() << " for " << fileName);
180
181 // Check if we need to override run number - only needed for simulation
183
184 StatusCode sc = processInputFileMetaData(fileName);
185 if(!sc.isSuccess()) throw std::runtime_error("Could not process input file meta data");
186 m_filesProcessed.insert(std::move(fileName));
187}
188
190{
191 if (!m_filesProcessed.contains(sid)) {
193 m_filesProcessed.insert(sid);
194 }
195 return StatusCode::SUCCESS;
196}
197
199{
200 return StatusCode::SUCCESS;
201}
202
204{
205 // Check if we have folders to serialize to ByteStream metadata
206 if (m_foldersToSerializeToBSMetadata.value().empty()) {
207 ATH_MSG_DEBUG("No folders configured for serialization");
208 return StatusCode::SUCCESS;
209 }
210
211 // Collect IOV metadata strings first
212 std::vector<std::string> iovMetaStrings;
213 for (const std::string& folderName : m_foldersToSerializeToBSMetadata.value()) {
214 IOVMetaDataContainer* container = findMetaDataContainer(folderName);
215 if (!container) {
216 ATH_MSG_WARNING("Could not find IOVMetaDataContainer for folder " << folderName << ", skipping");
217 continue;
218 }
219
220 std::string jsonStr = serializeContainerToJSON(container);
221 if (!jsonStr.empty()) {
222 iovMetaStrings.push_back("IOVMeta." + folderName + "=" + jsonStr);
223 ATH_MSG_DEBUG("Serialized folder " << folderName << " (" << jsonStr.size() << " bytes JSON)");
224 }
225 }
226
227 if (iovMetaStrings.empty()) {
228 ATH_MSG_DEBUG("No IOV metadata serialized");
229 return StatusCode::SUCCESS;
230 }
231
232 // Store the IOV metadata strings in MetaDataStore for ByteStreamCnvSvc to retrieve
233 // Check if the object already exists and update it, or create a new one
234 if (m_metaDataStore->contains<std::vector<std::string>>("IOVMetaDataStrings")) {
235 // Retrieve existing and append
236 std::vector<std::string>* existingStrings = nullptr;
237 ATH_CHECK(m_metaDataStore->retrieve(existingStrings, "IOVMetaDataStrings"));
238 existingStrings->insert(existingStrings->end(), iovMetaStrings.begin(), iovMetaStrings.end());
239 ATH_MSG_DEBUG("Appended " << iovMetaStrings.size() << " IOV metadata strings to existing collection");
240 } else {
241 // Create new
242 auto iovMetaData = std::make_unique<std::vector<std::string>>(std::move(iovMetaStrings));
243 ATH_CHECK(m_metaDataStore->record(std::move(iovMetaData), "IOVMetaDataStrings"));
244 ATH_MSG_DEBUG("Stored " << iovMetaStrings.size() << " IOV metadata strings in MetaDataStore");
245 }
246
247 return StatusCode::SUCCESS;
248}
249
251{
252 return StatusCode::SUCCESS;
253}
254
255//--------------------------------------------------------------------------
256
257void
259{
260 ATH_MSG_DEBUG("begin checkOverrideRunNumber");
261
262 // Check if override run numbers have been set by properties or by
263 // the EventSelector
264
265 if (m_minMaxRunNumbers.value().size() > 0) {
268 if (m_minMaxRunNumbers.value().size() > 1) m_maxRunNumber = m_minMaxRunNumbers.value()[1];
270
272
273 ATH_MSG_INFO("checkOverrideRunNumber: overriding IOV for range - min: " << m_minRunNumber
274 << " max: " << m_maxRunNumber);
275 return;
276 }
277
278 ATH_MSG_DEBUG("checkOverrideRunNumber: check if tag is set in jobOpts");
279
280 // Get name of event selector from the application manager to
281 // make sure we get the one for MC signal events
282 SmartIF<IProperty> appMgr{serviceLocator()->service("ApplicationMgr")};
283 if (!appMgr) {
284 ATH_MSG_ERROR("checkOverrideRunNumber: Cannot get ApplicationMgr ");
285 return;
286 }
287 StringProperty property("EvtSel", "");
288 StatusCode sc = appMgr->getProperty(&property);
289 if (!sc.isSuccess()) {
290 ATH_MSG_ERROR("checkOverrideRunNumber: unable to get EvtSel: found " << property.value());
291 return;
292 }
293 // Get EventSelector for ApplicationMgr
294 const std::string eventSelector = property.value();
295 SmartIF<IProperty> evtSel{serviceLocator()->service(eventSelector)};
296 if (!evtSel) {
297 ATH_MSG_ERROR("checkOverrideRunNumber: Cannot get EventSelector " << eventSelector);
298 return;
299 }
300
301 // Is flag set to override the run number?
302 BooleanProperty overrideRunNumber("OverrideRunNumberFromInput", false);
303 sc = evtSel->getProperty(&overrideRunNumber);
304 if (!sc.isSuccess()) {
305 // Not all EventSelectors have this property, so we must be tolerant
306 ATH_MSG_DEBUG("resetRunNumber: unable to get OverrideRunNumberFromInput property from EventSelector ");
307 return;
308 }
309 m_overrideRunNumber = overrideRunNumber.value();
311 // New run number
312 IntegerProperty runNumber("RunNumber", 0);
313 sc = evtSel->getProperty(&runNumber);
314 if (!sc.isSuccess()) {
315 ATH_MSG_ERROR("checkOverrideRunNumber: unable to get RunNumber from EventSelector: found "
316 << runNumber.value());
317 return;
318 }
319 m_newRunNumber = runNumber.value();
320 // Old run number
321 IntegerProperty oldRunNumber("OldRunNumber", 0);
322 sc = evtSel->getProperty(&oldRunNumber);
323 if (!sc.isSuccess()) {
324 ATH_MSG_ERROR("checkOverrideRunNumber: unable to get OldRunNumber from EventSelector: found "
325 << oldRunNumber.value());
326 return;
327 }
328 m_oldRunNumber = oldRunNumber.value();
329
330 ATH_MSG_DEBUG("checkOverrideRunNumber: Changing old to new run number: " << m_oldRunNumber
331 << " " << m_newRunNumber << " obtained from " << eventSelector);
332 }
333 else ATH_MSG_DEBUG("checkOverrideRunNumber: OverrideRunNumberFromInput not set for " << eventSelector);
334}
335
336//--------------------------------------------------------------------------
337
338StatusCode
339IOVDbMetaDataTool::registerFolder(const std::string& folderName) const
340{
341 // Set the default folder description for a CondAttrListCollection
342 // which will be read back via IOVDbSvc
343 std::string folderDescr = "<timeStamp>run-event</timeStamp><addrHeader><address_header service_type=\"256\" clid=\"1238547719\" /> </addrHeader><typeName>CondAttrListCollection</typeName>" ;
344
345 return registerFolder(folderName, folderDescr);
346}
347
348//--------------------------------------------------------------------------
349
350StatusCode
351IOVDbMetaDataTool::registerFolder(const std::string& folderName,
352 const std::string& folderDescription) const
353{
354 // lock the tool before getMetaDataContainer() call
355 std::scoped_lock guard( m_mutex );
356
357 ATH_MSG_DEBUG("begin registerFolder ");
358
359 if( ! getMetaDataContainer(folderName, folderDescription) ) {
360 ATH_MSG_ERROR("Unable to register folder " << folderName);
361 return(StatusCode::FAILURE);
362 }
363 else {
364 ATH_MSG_DEBUG("IOVMetaDataContainer for folder " << folderName << " has been registered ");
365 }
366
367 return StatusCode::SUCCESS;
368}
369
370//--------------------------------------------------------------------------
371
372StatusCode IOVDbMetaDataTool::addPayload (const std::string& folderName
373 , CondAttrListCollection* payload) const
374{
375 // lock the tool while it is modifying the folder
376 std::scoped_lock guard( m_mutex );
377
378 ATH_MSG_DEBUG("begin addPayload ");
379
380 // Check if the folder has already been found
381 IOVMetaDataContainer* cont = m_metaDataStore->tryRetrieve<IOVMetaDataContainer>(folderName);
382 if(cont) {
383 ATH_MSG_DEBUG("Retrieved IOVMetaDataContainer from MetaDataStore for folder "
384 << folderName);
385 }
386 else {
387 ATH_MSG_ERROR("addPayload: Could not find IOVMetaDataContainer in MetaDataStore for folder "
388 << folderName
389 << ". One must have previously called registerFolder. ");
390 return StatusCode::FAILURE;
391 }
392
393 // Override run number if requested
395 ATH_CHECK( overrideIOV(payload) );
396 }
397
398 // Add payload to container
399 bool success = cont->merge(payload);
400 if (success) {
401 ATH_MSG_DEBUG("Added new payload for folder " << folderName);
402 }
403 else {
404 ATH_MSG_DEBUG("Could not add new payload for folder "
405 << folderName
406 << " (may be duplicate payload).");
407
408 // To Do: the function implicitly assumes ownership on the payload pointer
409 delete payload;
410 payload = nullptr;
411 }
412
413 // Debug printout
414 if(payload && msgLvl(MSG::DEBUG)) {
415 std::ostringstream stream;
416 payload->dump(stream);
417 ATH_MSG_DEBUG(stream.str());
418 }
419
420 return StatusCode::SUCCESS;
421}
422
423//--------------------------------------------------------------------------
424
425StatusCode
426IOVDbMetaDataTool::modifyPayload (const std::string& folderName,
427 CondAttrListCollection*& coll) const
428{
429 // protected by lock in processInputFileMetaData()
430
433 ATH_MSG_DEBUG("begin modifyPayload for folder " << folderName);
434
435 // check if this folder needs to be modified
436 bool modifyAttr = false;
437 std::string attributeName;
438 const std::vector<std::string>& folders = m_foldersToBeModified.value();
439 const std::vector<std::string>& attrs = m_attributesToBeRemoved.value();
440 for (unsigned int i = 0; i < folders.size(); ++i) {
441 if (folderName == folders[i]) {
442 if (attrs.size() > i) {
443 attributeName = attrs[i];
444 modifyAttr = true;
445 ATH_MSG_DEBUG("modifyPayload: remove attribute " << attributeName);
446 break;
447 }
448 }
449 }
450
451 if (!modifyAttr) {
452 ATH_MSG_DEBUG("modifyPayload: folder " << folderName << " OK ");
453 return StatusCode::SUCCESS;
454 }
455
456 bool iovSizeIsZero = coll->iov_size() == 0;
457 IOVRange testIOV = coll->minRange();
458 IOVTime start = testIOV.start();
459 IOVTime stop = testIOV.stop();
460 // Set the IOV
462 if (iovSizeIsZero) {
463 // Only add in overall range if channels do not have
464 // IOVs - otherwise this is automatically calculated
465 coll1->addNewStart(start);
466 coll1->addNewStop (stop);
467 }
468 // Add in channels
469 unsigned int nchans = coll->size();
470 bool hasChanNames = (coll->name_size() == nchans);
471 for (unsigned int ichan = 0; ichan < nchans; ++ichan) {
472 CondAttrListCollection::ChanNum chan = coll->chanNum(ichan);
473 // Now filter out the unwanted attribute
475 const CondAttrListCollection::AttributeList& oldAttrList = coll->attributeList(chan);
476 for (unsigned int iatt = 0; iatt < oldAttrList.size(); ++iatt) {
477 // skip the unwanted attribute
478 if (attributeName == oldAttrList[iatt].specification().name()) {
479 ATH_MSG_DEBUG("modifyPayload: skipping attribute name " << oldAttrList[iatt].specification().name());
480 continue;
481 }
482
483 // copy the rest
484 newAttrList.extend(oldAttrList[iatt].specification().name(),
485 oldAttrList[iatt].specification().type());
486 const coral::Attribute& oldAttr = oldAttrList[iatt];
487 coral::Attribute& newAttr = newAttrList[oldAttrList[iatt].specification().name()];
488 newAttr = oldAttr;
489 // newAttr.setValue(oldAttr.data());
490 ATH_MSG_DEBUG("modifyPayload: copying attr name "
491 << oldAttrList[iatt].specification().name() << " "
492 /*<< newAttr*/);
493 }
494 coll1->add(chan, newAttrList);
495 if (!iovSizeIsZero) coll1->add(chan, coll->iovRange(chan));
496 if(hasChanNames)coll1->add(chan, coll->chanName(chan));
497 ATH_MSG_DEBUG("modifyPayload: copied attribute list for channel " << chan);
498 }
499 delete coll;
500 coll = coll1;
501 if (msgLvl(MSG::DEBUG)) {
502 std::ostringstream stream;
503 coll->dump(stream);
504 ATH_MSG_DEBUG(stream.str());
505 }
506
507 return StatusCode::SUCCESS;
508}
509
510//--------------------------------------------------------------------------
511
513IOVDbMetaDataTool::findMetaDataContainer(const std::string& folderName) const
514{
515 // lock the tool before this call
516 // Return the folder if it is in the meta data store
517 return m_metaDataStore->tryRetrieve<IOVMetaDataContainer>(folderName);
518}
519
520
522IOVDbMetaDataTool::getMetaDataContainer(const std::string& folderName
523 , const std::string& folderDescription) const
524{
525 // protected by locks in addPayload() and registerFolder()
526 ATH_MSG_DEBUG("begin getMetaDataContainer ");
527
528 IOVMetaDataContainer* cont{nullptr};
529 // See if it is in the meta data store
530 if (!m_metaDataStore->contains<IOVMetaDataContainer>(folderName)) {
531 // Container not found, add in new one
532 cont = new IOVMetaDataContainer(folderName, folderDescription);
533 ATH_MSG_DEBUG("No IOVMetaDataContainer in MetaDataStore for folder " << folderName
534 << ". Created a new instance");
535 StatusCode sc = m_metaDataStore->record(cont, folderName);
536 if (!sc.isSuccess()) {
537 ATH_MSG_ERROR("Could not record IOVMetaDataContainer in MetaDataStore for folder " << folderName);
538 delete cont;
539 cont = nullptr;
540 }
541 }
542 else {
543 ATH_MSG_DEBUG("IOVMetaDataContainer already in MetaDataStore for folder " << folderName);
544 StatusCode sc = m_metaDataStore->retrieve(cont, folderName);
545 if (!sc.isSuccess()) {
546 ATH_MSG_ERROR("Could not retrieve IOVMetaDataContainer in MetaDataStore for folder " << folderName);
547 cont = nullptr;
548 }
549 }
550 return cont;
551}
552
553//--------------------------------------------------------------------------
554
555StatusCode IOVDbMetaDataTool::processInputFileMetaData(const std::string& fileName)
556{
557 // lock the tool while it is processing input metadata
558 std::scoped_lock guard( m_mutex );
559
560 ATH_MSG_DEBUG("processInputFileMetaData: file name " << fileName);
561
562 // Retrieve all meta data containers from InputMetaDataStore
565
566 StatusCode sc = m_inputStore->retrieve(cont, contEnd);
567 if (!sc.isSuccess()) {
568 ATH_MSG_DEBUG("processInputFileMetaData: Could not retrieve IOVMetaDataContainer objects from InputMetaDataStore - cannot process input file meta data");
569 return StatusCode::SUCCESS;
570 }
571
572 ATH_MSG_DEBUG("processInputFileMetaData: Retrieved from IOVMetaDataContainer(s) from InputMetaDataStore");
573
574 // For each container, merge its contents into the MetaDataStore
575 unsigned int ncolls = 0;
576 unsigned int ndupColls = 0;
577 for (; cont != contEnd; ++cont) {
578 IOVMetaDataContainer* contMaster = getMetaDataContainer(cont->folderName()
579 , cont->folderDescription());
580
581 // We assume that the folder is the same for all versions, and
582 // now we loop over versions for the payloads
583 std::list<SG::ObjectWithVersion<IOVMetaDataContainer> > allVersions;
584 sc = m_inputStore->retrieveAllVersions(allVersions, cont.key());
585 if (!sc.isSuccess()) {
586 ATH_MSG_ERROR("Could not retrieve all versions for " << cont.key());
587 return sc;
588 }
589
590 for (SG::ObjectWithVersion<IOVMetaDataContainer>& obj : allVersions) {
591 const IOVPayloadContainer* payload = obj.dataObject->payloadContainer();
592
593 ATH_MSG_DEBUG("processInputFileMetaData: New container: payload size " << payload->size() << " version key " << obj.versionedKey);
594
595 // detailed printout before merge
596 if (msgLvl(MSG::VERBOSE)) {
597 const IOVPayloadContainer* payloadMaster = contMaster->payloadContainer();
598 ATH_MSG_VERBOSE("Before merge, payload minRange for folder " << cont->folderName());
599 if (payloadMaster && payloadMaster->size()) {
600 // Loop over AttrColls and print out minRange
601 IOVPayloadContainer::const_iterator itColl = payloadMaster->begin();
602 IOVPayloadContainer::const_iterator itCollEnd = payloadMaster->end();
603 unsigned int iPayload = 0;
604 for (; itColl != itCollEnd; ++itColl, ++iPayload) {
605 ATH_MSG_VERBOSE(iPayload << " " << (*itColl)->minRange() << " "
606 << (*itColl)->size());
607 }
608 }
609 else {
610 ATH_MSG_VERBOSE(" no payloads yet!");
611 }
612 }
613 }
614
615 // Detailed printout
616 if (msgLvl(MSG::DEBUG)) {
617 ATH_MSG_DEBUG("processInputFileMetaData: Current payload before merge " << contMaster->folderName());
619 IOVPayloadContainer::const_iterator itCollEnd1 = contMaster->payloadContainer()->end();
620 std::ostringstream stream;
621 for (; itColl1 != itCollEnd1; ++itColl1) (*itColl1)->dump(stream);
622 ATH_MSG_DEBUG(stream.str());
623 }
624
625 //
626 // Loop over CondAttrListCollections and do merge
627 //
628 for (SG::ObjectWithVersion<IOVMetaDataContainer>& obj : allVersions) {
629 const IOVPayloadContainer* payload = obj.dataObject->payloadContainer();
630 IOVPayloadContainer::const_iterator itColl = payload->begin();
631 IOVPayloadContainer::const_iterator itCollEnd = payload->end();
632 for (; itColl != itCollEnd; ++itColl) {
633
634 // Make a copy of the collection and merge it into
635 // master container in meta data store
637 // Override run number if requested
639 ATH_CHECK( overrideIOV(coll) );
640 }
641
642 // first check if we need to modify the incoming payload
643 if (!modifyPayload (contMaster->folderName(), coll).isSuccess()) {
644 ATH_MSG_ERROR("processInputFileMetaData: Could not modify the payload for folder " << contMaster->folderName());
645 return StatusCode::FAILURE;
646 }
647
648 ATH_MSG_VERBOSE("processInputFileMetaData: merge minRange: " << coll->minRange());
649 if (!contMaster->merge(coll)) {
650 // Did not merge it in - was a duplicate, so we need to delete it
651 delete coll;
652 ++ndupColls;
653 ATH_MSG_VERBOSE(" => not merged ");
654 }
655 else {
656 ++ncolls;
657 ATH_MSG_VERBOSE(" => merged ");
658 }
659
660 }
661 ATH_MSG_DEBUG("processInputFileMetaData: Merged together containers for folder " << cont->folderName() << " ncoll/ndup "
662 << ncolls << " " << ndupColls);
663
664 // Check for consistency after merge
665 const IOVPayloadContainer* payloadMaster = contMaster->payloadContainer();
666 if (payloadMaster && payloadMaster->size()) {
667 // Loop over AttrColls and print out minRange
668 IOVPayloadContainer::const_iterator itColl = payloadMaster->begin();
669 IOVPayloadContainer::const_iterator itCollEnd = payloadMaster->end();
670 IOVTime lastStop;
671 if ((*itColl)->minRange().start().isTimestamp()) lastStop = IOVTime(0);
672 else lastStop = IOVTime(0,0);
673 bool hasError = false;
674 for (; itColl != itCollEnd; ++itColl) {
675 if ((*itColl)->minRange().start() < lastStop) hasError = true;
676 lastStop = (*itColl)->minRange().stop();
677 }
678 if (hasError) {
679 ATH_MSG_ERROR("processInputFileMetaData: error after merge of file meta data. " );
680 ATH_MSG_ERROR("processInputFileMetaData: Filename " << fileName);
681 ATH_MSG_ERROR("processInputFileMetaData: folder " << contMaster->folderName());
682 ATH_MSG_ERROR("processInputFileMetaData: MinRange for meta data folders ");
683 unsigned int iPayload = 0;
684 itColl = payloadMaster->begin();
685 for (; itColl != itCollEnd; ++itColl, ++iPayload) {
686 ATH_MSG_ERROR(iPayload << " " << (*itColl)->minRange() << " " << (*itColl)->size());
687 }
688 }
689 }
690
691 // detailed printout after merge
692 if (msgLvl(MSG::VERBOSE)) {
693 const IOVPayloadContainer* payloadMaster = contMaster->payloadContainer();
694 ATH_MSG_VERBOSE("processInputFileMetaData: After merge, payload minRange ");
695 if (payloadMaster) {
696 // Loop over AttrColls and print out minRange
697 IOVPayloadContainer::const_iterator itColl = payloadMaster->begin();
698 IOVPayloadContainer::const_iterator itCollEnd = payloadMaster->end();
699 unsigned int iPayload = 0;
700 for (; itColl != itCollEnd; ++itColl, ++iPayload) {
701 ATH_MSG_VERBOSE(iPayload << " " << (*itColl)->minRange() << " "
702 << (*itColl)->size());
703 }
704 }
705 else { ATH_MSG_ERROR(" no payloads yet!"); }
706 }
707
708 // Detailed printout
709 if (msgLvl(MSG::DEBUG)) {
710 ATH_MSG_DEBUG("processInputFileMetaData: Input payload " << cont->folderName());
711 std::ostringstream streamInp;
712 itColl = payload->begin();
713 itCollEnd = payload->end();
714 for (; itColl != itCollEnd; ++itColl) (*itColl)->dump(streamInp);
715 ATH_MSG_DEBUG(streamInp.str());
716 ATH_MSG_DEBUG("processInputFileMetaData: Output payload " << contMaster->folderName());
717 std::ostringstream streamOut;
718 itColl = contMaster->payloadContainer()->begin();
719 itCollEnd = contMaster->payloadContainer()->end();
720 for (; itColl != itCollEnd; ++itColl) (*itColl)->dump(streamOut);
721 ATH_MSG_DEBUG(streamOut.str());
722 }
723 }
724 }
725
726 ATH_MSG_DEBUG("processInputFileMetaData: Total number of attribute collections merged together " << ncolls
727 << " Number of duplicate collections " << ndupColls);
728
729 // Note: ConditionStore population for parameter folders (direct in-file metadata mode)
730 // is now handled by MetaDataToCondAlg, which runs during event processing when
731 // a valid EventContext is available.
732
733 // Serialize requested IOV folders to ByteStream metadata
735
736 return StatusCode::SUCCESS;
737}
738
739//--------------------------------------------------------------------------
740
741std::string
743{
744 const IOVPayloadContainer* payloads = container->payloadContainer();
745 if (!payloads || payloads->size() == 0) {
746 ATH_MSG_WARNING("No payloads for folder " << container->folderName());
747 return "";
748 }
749
750 using json = nlohmann::json;
751 json jsonData;
752
753 jsonData["folder"] = container->folderName();
754 jsonData["description"] = container->folderDescription();
755 jsonData["iovs"] = json::array();
756
757 // Serialize each IOV payload
758 for (const CondAttrListCollection* coll : *payloads) {
759 json iov;
760
761 // Get IOV range
762 IOVRange range = coll->minRange();
763 IOVTime start = range.start();
764 IOVTime stop = range.stop();
765
766 // IOV range
767 if (start.isRunEvent()) {
768 iov["range"]["start"] = {{"run", start.run()}, {"event", start.event()}};
769 iov["range"]["stop"] = {{"run", stop.run()}, {"event", stop.event()}};
770 } else {
771 iov["range"]["start"] = {{"timestamp", start.timestamp()}};
772 iov["range"]["stop"] = {{"timestamp", stop.timestamp()}};
773 }
774
775 // Attributes (serialize each channel)
776 iov["attrs"] = json::object();
777 for (const auto& chanAttrPair : *coll) {
778 CondAttrListCollection::ChanNum chan = chanAttrPair.first;
779 const coral::AttributeList& attrList = chanAttrPair.second;
780
781 std::string chanKey = "chan" + std::to_string(chan);
782 iov["attrs"][chanKey] = json::object();
783
784 for (const auto& attr : attrList) {
785 auto & thisAttribute = iov["attrs"][chanKey][attr.specification().name()];
786 // Serialize attribute value based on type
787 const std::type_info& type = attr.specification().type();
788 if (type == typeid(std::string)) {
789 thisAttribute = attr.data<std::string>();
790 } else if (type == typeid(int)) {
791 thisAttribute = attr.data<int>();
792 } else if (type == typeid(unsigned int)) {
793 thisAttribute = attr.data<unsigned int>();
794 } else if (type == typeid(long)) {
795 thisAttribute = attr.data<long>();
796 } else if (type == typeid(unsigned long)) {
797 thisAttribute = attr.data<unsigned long>();
798 } else if (type == typeid(long long)) {
799 thisAttribute = attr.data<long long>();
800 } else if (type == typeid(unsigned long long)) {
801 thisAttribute = attr.data<unsigned long long>();
802 } else if (type == typeid(float)) {
803 thisAttribute = attr.data<float>();
804 } else if (type == typeid(double)) {
805 thisAttribute = attr.data<double>();
806 } else if (type == typeid(bool)) {
807 thisAttribute = attr.data<bool>();
808 } else {
809 // For other types, convert to string representation
810 std::ostringstream oss;
811 attr.toOutputStream(oss);
812 thisAttribute = oss.str();
813 ATH_MSG_DEBUG("Attribute " << attr.specification().name() << " has unsupported type, converted to string: " << oss.str());
814 }
815 }
816 }
817
818 jsonData["iovs"].push_back(iov);
819 }
820
821 return jsonData.dump();
822}
823
824//--------------------------------------------------------------------------
825
826StatusCode
828{
829 ATH_MSG_DEBUG("overrideIOV ");
830
831 // Override the IOV for run/event IOVs
832
833 // (ONLY TRUE FOR OVERRIDE COMING IN VIA EVENTSELECTOR:)
834 // NOTE: we require that the old run number falls within the
835 // IOVRange of the incoming collection. We override ALL IOVs for
836 // ALL channels forcing the IOVRange to be (newRunNumber,1) to
837 // (newRunNumber+1,1)
838
839 bool iovSizeIsZero = coll->iov_size() == 0;
840 IOVRange testIOV = coll->minRange();
841 IOVTime start = testIOV.start();
842 IOVTime stop = testIOV.stop();
843 IOVTime oldRun(m_oldRunNumber, 0);
844 if (start.isRunEvent() && stop.isRunEvent()) { // only for run/event
845 IOVRange newRange;
846 // Two ways of resetting
848 else if (m_overrideRunNumber) newRange = IOVRange(IOVTime(m_newRunNumber, 0), IOVTime(m_newRunNumber + 1, 0));
849
850 if (m_overrideRunNumber && !testIOV.isInRange(oldRun)) {
851 // old run must be in the range
852 ATH_MSG_ERROR("overrideIOV: old run number does not match. Old run number " << m_oldRunNumber << " IOVRange: " << testIOV);
853 return StatusCode::SUCCESS;
854 }
855
856 ATH_MSG_DEBUG("overrideIOV: overrideMinMaxRunNumber: " << (int)m_overrideMinMaxRunNumber
857 << " overrideRunNumber " << (int)m_overrideRunNumber
858 << " iovSizeIsZero: " << (int)iovSizeIsZero
859 << " newRange " << newRange);
860
861 // Now over ride IOVs - two cases: 1) single IOV for full collection, 2) IOVs for individual channels.
862 // Must treat the reset of collection IOV differently
863 if (iovSizeIsZero) {
864 // Only add in overall range if channels do not have
865 // IOVs - otherwise this is automatically calculated
866 coll->resetMinRange(); // must first reset to 'full range' and then reduce the IOVRange accordingly
867 coll->addNewStart(newRange.start());
868 coll->addNewStop (newRange.stop());
869 }
870 else {
871 // Add in channels
872 unsigned int nchans = coll->size();
873 ATH_MSG_DEBUG("overrideIOV: nchans " << nchans);
874 for (unsigned int ichan = 0; ichan < nchans; ++ichan) {
875 // FIXME: O(N^2)!
876 CondAttrListCollection::ChanNum chan = coll->chanNum(ichan);
877 coll->add(chan, newRange);
878 ATH_MSG_DEBUG("overrideIOV: overriding the IOV of collection chan " << chan);
879 }
880 // must reset the collection range AFTER the channels, because the collection range will be
881 // 'narrowed' to that of the channels
882 coll->resetMinRange();
883 }
884 if (msgLvl(MSG::DEBUG)) {
885 ATH_MSG_DEBUG("overrideIOV: after overriding the IOV of collection");
886 std::ostringstream stream;
887 coll->dump(stream);
888 ATH_MSG_DEBUG(stream.str());
889 }
890 }
891 else ATH_MSG_DEBUG("overrideIOV: IOV is not run/event ");
892
893 return StatusCode::SUCCESS;
894}
895
896
897//--------------------------------------------------------------------------
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
This file defines the class for a collection of AttributeLists where each one is associated with a ch...
Hold mappings of ranges to condition objects.
a traits class that associates a CLID to a type T It also detects whether T inherits from Gaudi DataO...
nlohmann::json json
This is a tool used to manage the IOV Meta Data for a given object into the Meta Data Store.
This class is a container for conditions data.
Basic time unit for IOVSvc.
read-copy-update (RCU) style synchronization for Athena.
static Double_t sc
size_t size() const
Number of registered mappings.
This class is a collection of AttributeLists where each one is associated with a channel number.
const AttributeList & attributeList(ChanNum chanNum) const
attribute list for a given channel number
ChanNum chanNum(unsigned int index) const
channel number for index: (index = 0 to size-1)
void addNewStart(const IOVTime &start)
Add new start time to minRange - make sure that start is >= to new start.
name_size_type name_size() const
number of Chan/Name pairs
bool add(ChanNum chanNum, const AttributeList &attributeList)
Adding in chan/attrList pairs.
void addNewStop(const IOVTime &stop)
Add new stop time to minRange - make sure that stop is <= to new stop.
void dump() const
Dump our contents to std::cout.
const std::string & chanName(ChanNum chanNum) const
find name for particular channel
void resetMinRange()
Reset minRange according to the IOVs of the contained channels.
const IOVRange & minRange() const
Current minimal IOVRange.
size_type size() const
number of Chan/AttributeList pairs
iov_size_type iov_size() const
number of Chan/IOV pairs
coral::AttributeList AttributeList
const IOVRange & iovRange(ChanNum chanNum) const
IOVRange list for a given channel number.
virtual StatusCode processInputFileMetaData(const std::string &fileName) override
Explicit call to process IOV meta data from the input meta data store, transferring it to the main me...
IOVDbMetaDataTool(const std::string &type, const std::string &name, const IInterface *parent)
StoreGateSvc_t m_inputStore
virtual StatusCode metaDataStop() override
Function called when the tool should write out its metadata.
virtual StatusCode endInputFile(const SG::SourceID &) override
Function called when the currently open input file got completely processed.
StringArrayProperty m_foldersToBeModified
unsigned int m_minRunNumber
std::string serializeContainerToJSON(const IOVMetaDataContainer *container) const
Serialize IOVMetaDataContainer to JSON format for ByteStream metadata.
virtual void handle(const Incident &incident) override
Incident service handle listening for BeginInputFile and EndInputFile.
StatusCode overrideIOV(CondAttrListCollection *&coll) const
override IOV with new run number
StatusCode serializeIOVMetadataToBSMetadata()
Serialize IOV metadata to ByteStream metadata (called from processInputFileMetaData).
std::set< std::string > m_filesProcessed
StoreGateSvc_t m_condStore
virtual StatusCode finalize() override
Finalize AlgTool.
virtual StatusCode addPayload(const std::string &folderName, CondAttrListCollection *payload) const override
Add an IOV and Payload for a particular folder - replaces payloads if there is an IOV overlap.
unsigned int m_maxRunNumber
IOVMetaDataContainer * getMetaDataContainer(const std::string &folderName, const std::string &folderDescription) const
return meta data container from the meta data store
UnsignedIntegerArrayProperty m_minMaxRunNumbers
unsigned int m_oldRunNumber
StoreGateSvc_t m_metaDataStore
virtual IOVMetaDataContainer * findMetaDataContainer(const std::string &folderName) const override final
virtual StatusCode beginInputFile(const SG::SourceID &) override
Function called when a new input file is opened.
virtual StatusCode initialize() override
Initialize AlgTool.
Gaudi::Property< std::map< std::string, std::string > > m_payloads
std::shared_mutex m_mutex
unsigned int m_newRunNumber
virtual StatusCode registerFolder(const std::string &folderName, const std::string &folderDescription) const override
Register folder in the IOV Db MetaData - done once at initialize.
void checkOverrideRunNumber()
check if we should override the run number in the incoming meta data
Gaudi::Property< std::vector< std::string > > m_foldersToSerializeToBSMetadata
StatusCode modifyPayload(const std::string &folderName, CondAttrListCollection *&payload) const
Modify a Payload for a particular folder - replaces one of the internal attributes.
StringArrayProperty m_attributesToBeRemoved
This class is a container for conditions data.
bool merge(CondAttrListCollection *payload)
Add in new payload.
const std::string & folderName() const
Folder name.
const IOVPayloadContainer * payloadContainer() const
Access to payload container.
This class is a container for the payload of conditions data.
size_type size() const
size of payload vector
payloadVec::const_iterator const_iterator
const_iterator begin() const
Begin of payload vector.
const_iterator end() const
End of payload vector.
Validity Range object.
Definition IOVRange.h:30
const IOVTime & stop() const
Definition IOVRange.h:39
bool isInRange(const IOVTime &t) const
Definition IOVRange.h:41
const IOVTime & start() const
Definition IOVRange.h:38
Basic time unit for IOVSvc.
Definition IOVTime.h:33
static constexpr uint32_t MAXRUN
Definition IOVTime.h:48
static constexpr uint32_t MAXEVENT
Definition IOVTime.h:51
a const_iterator facade to DataHandle.
Definition SGIterator.h:164
associate a data object with its VersionedKey The object is held by a ReadHandle to delay its retriev...
const std::string & key() const
Get the key string with which the current object was stored.
ElementLink_p1< typename GenerateELinkIndexType_p1< typename LINK::index_type >::type > type