ATLAS Offline Software
Loading...
Searching...
No Matches
IOVDbMetaDataTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 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
74 m_modifyFolders = (m_foldersToBeModified.value().size()>0);
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
95 ATH_MSG_DEBUG("Processing " << folderPayloads.size() << " folder(s) for direct payload registration");
96
97 // Store payloads for ConditionStore registration (after MetaDataStore registration)
98 std::map<std::string, std::pair<std::unique_ptr<CondAttrListCollection>, EventIDRange>> payloadsForCondStore;
99
100 for (const auto& [folderName, parameters] : folderPayloads) {
101 // Extract beginRun and endRun from parameters
102 if (!parameters.contains("beginRun") || !parameters.contains("endRun")) {
103 ATH_MSG_ERROR("Payload for folder " << folderName << " missing beginRun or endRun");
104 return StatusCode::FAILURE;
105 }
106
107 unsigned int beginRun = std::stoul(parameters.at("beginRun"));
108 unsigned int endRun = std::stoul(parameters.at("endRun"));
109
110 // Create filtered parameters map without beginRun/endRun
111 std::map<std::string, std::string> filteredParams;
112 std::ranges::copy_if(parameters, std::inserter(filteredParams, filteredParams.end()),
113 [](const auto& p) { return p.first != "beginRun" && p.first != "endRun"; });
114
115 ATH_MSG_DEBUG("Registering folder " << folderName << " with " << filteredParams.size()
116 << " parameters, IOV [" << beginRun << ", " << endRun << "]");
117
118 ATH_CHECK(registerFolder(folderName));
119
120 // Build payload for MetaDataStore
121 // Note: AttributeListSpecification has protected destructor, must use new
122 // The AttributeList constructor with 'true' takes ownership and will call release()
123 coral::AttributeListSpecification* spec = new coral::AttributeListSpecification();
124 for (const auto& [key, value] : filteredParams) {
125 spec->extend(key, "string");
126 }
127
128 coral::AttributeList attrList(*spec, true);
129 for (const auto& [key, value] : filteredParams) {
130 attrList[key].setValue(value);
131 }
132
133 auto payload = std::make_unique<CondAttrListCollection>(true);
134 payload->addNewStart(IOVTime(beginRun, 0));
135 payload->addNewStop(IOVTime(endRun, IOVTime::MAXEVENT));
136 payload->add(0, attrList);
137
138 ATH_MSG_DEBUG("Created payload with IOV [" << beginRun << ", " << endRun << "]");
139
140 // Store payload copy for ConditionStore registration
141 EventIDRange iovRange(EventIDBase(beginRun, EventIDBase::UNDEFEVT, 0, 0, 0),
142 EventIDBase(endRun, EventIDBase::UNDEFEVT, EventIDBase::UNDEFNUM, EventIDBase::UNDEFNUM, EventIDBase::UNDEFNUM));
143 payloadsForCondStore[folderName] = std::make_pair(std::make_unique<CondAttrListCollection>(*payload), iovRange);
144
145 // Add to MetaDataStore
146 ATH_CHECK(addPayload(folderName, payload.release()));
147 }
148
149 // Now populate ConditionStore with all payloads
150 if (!payloadsForCondStore.empty()) {
151 ATH_MSG_INFO("Registering " << payloadsForCondStore.size() << " payload(s) to ConditionStore");
152
153 ATH_CHECK(m_condStore.retrieve());
154
155 ServiceHandle<Athena::IRCUSvc> rcuSvc("Athena::RCUSvc", name());
156 ATH_CHECK(rcuSvc.retrieve());
157
158 for (auto& [folderName, payloadPair] : payloadsForCondStore) {
159 auto& [payload, iovRange] = payloadPair;
160
161 // Check if CondCont<AthenaAttributeList> already exists using contains() to avoid warnings
162 CondCont<AthenaAttributeList>* cc = nullptr;
163 if (!m_condStore->contains<CondCont<AthenaAttributeList>>(folderName)) {
164 ATH_MSG_INFO("Creating CondCont<AthenaAttributeList> for " << folderName);
165
169 folderName);
170 if (!cb) {
171 ATH_MSG_ERROR("Failed to create CondCont for " << folderName);
172 return StatusCode::FAILURE;
173 }
174
175 if (m_condStore->recordObject(cb, folderName, true, false) == nullptr) {
176 ATH_MSG_ERROR("Failed to record CondCont for " << folderName);
177 return StatusCode::FAILURE;
178 }
179 }
180
181 ATH_CHECK(m_condStore->retrieve(cc, folderName));
182
183 // Extract AthenaAttributeList from CondAttrListCollection
184 if (payload->size() != 1) {
185 ATH_MSG_ERROR("Expected single-entry CondAttrListCollection for " << folderName << ", got " << payload->size() << " entries");
186 return StatusCode::FAILURE;
187 }
188
189 auto itr = payload->begin();
190 const coral::AttributeList& attrList = itr->second;
191 auto athAttrList = std::make_unique<AthenaAttributeList>(attrList);
192
193 ATH_CHECK(cc->insert(iovRange, std::move(athAttrList), Gaudi::Hive::currentContext()));
194 ATH_MSG_INFO("Inserted payload into CondCont for " << folderName << " with IOV " << iovRange);
195 }
196 }
197 }
198
199 return(StatusCode::SUCCESS);
200}
201
202//--------------------------------------------------------------------------
203
204StatusCode
206{
207 return StatusCode::SUCCESS;
208}
209
210//--------------------------------------------------------------------------
211
212void IOVDbMetaDataTool::handle(const Incident& inc)
213{
214 const FileIncident* fileInc = dynamic_cast<const FileIncident*>(&inc);
215 if(!fileInc) throw std::runtime_error("Unable to get FileName from FirstInputFile incident");
216
217 const std::string fileName = fileInc->fileName();
218 ATH_MSG_DEBUG("handle() " << inc.type() << " for " << fileName);
219
220 // Check if we need to override run number - only needed for simulation
222
223 StatusCode sc = processInputFileMetaData(fileName);
224 if(!sc.isSuccess()) throw std::runtime_error("Could not process input file meta data");
225 m_filesProcessed.insert(std::move(fileName));
226}
227
229{
230 if (!m_filesProcessed.contains(sid)) {
232 m_filesProcessed.insert(sid);
233 }
234 return StatusCode::SUCCESS;
235}
236
238{
239 return StatusCode::SUCCESS;
240}
241
243{
244 // Check if we have folders to serialize to ByteStream metadata
245 if (m_foldersToSerializeToBSMetadata.value().empty()) {
246 ATH_MSG_DEBUG("No folders configured for serialization");
247 return StatusCode::SUCCESS;
248 }
249
250 // Collect IOV metadata strings first
251 std::vector<std::string> iovMetaStrings;
252 for (const std::string& folderName : m_foldersToSerializeToBSMetadata.value()) {
254 if (!container) {
255 ATH_MSG_WARNING("Could not find IOVMetaDataContainer for folder " << folderName << ", skipping");
256 continue;
257 }
258
259 std::string jsonStr = serializeContainerToJSON(container);
260 if (!jsonStr.empty()) {
261 iovMetaStrings.push_back("IOVMeta." + folderName + "=" + jsonStr);
262 ATH_MSG_DEBUG("Serialized folder " << folderName << " (" << jsonStr.size() << " bytes JSON)");
263 }
264 }
265
266 if (iovMetaStrings.empty()) {
267 ATH_MSG_DEBUG("No IOV metadata serialized");
268 return StatusCode::SUCCESS;
269 }
270
271 // Store the IOV metadata strings in MetaDataStore for ByteStreamCnvSvc to retrieve
272 // Check if the object already exists and update it, or create a new one
273 if (m_metaDataStore->contains<std::vector<std::string>>("IOVMetaDataStrings")) {
274 // Retrieve existing and append
275 std::vector<std::string>* existingStrings = nullptr;
276 ATH_CHECK(m_metaDataStore->retrieve(existingStrings, "IOVMetaDataStrings"));
277 existingStrings->insert(existingStrings->end(), iovMetaStrings.begin(), iovMetaStrings.end());
278 ATH_MSG_DEBUG("Appended " << iovMetaStrings.size() << " IOV metadata strings to existing collection");
279 } else {
280 // Create new
281 auto iovMetaData = std::make_unique<std::vector<std::string>>(std::move(iovMetaStrings));
282 ATH_CHECK(m_metaDataStore->record(std::move(iovMetaData), "IOVMetaDataStrings"));
283 ATH_MSG_DEBUG("Stored " << iovMetaStrings.size() << " IOV metadata strings in MetaDataStore");
284 }
285
286 return StatusCode::SUCCESS;
287}
288
290{
291 return StatusCode::SUCCESS;
292}
293
294//--------------------------------------------------------------------------
295
296void
298{
299 ATH_MSG_DEBUG("begin checkOverrideRunNumber");
300
301 // Check if override run numbers have been set by properties or by
302 // the EventSelector
303
304 if (m_minMaxRunNumbers.value().size() > 0) {
307 if (m_minMaxRunNumbers.value().size() > 1) m_maxRunNumber = m_minMaxRunNumbers.value()[1];
309
311
312 ATH_MSG_INFO("checkOverrideRunNumber: overriding IOV for range - min: " << m_minRunNumber
313 << " max: " << m_maxRunNumber);
314 return;
315 }
316
317 ATH_MSG_DEBUG("checkOverrideRunNumber: check if tag is set in jobOpts");
318
319 // Get name of event selector from the application manager to
320 // make sure we get the one for MC signal events
321 SmartIF<IProperty> appMgr{serviceLocator()->service("ApplicationMgr")};
322 if (!appMgr) {
323 ATH_MSG_ERROR("checkOverrideRunNumber: Cannot get ApplicationMgr ");
324 return;
325 }
326 StringProperty property("EvtSel", "");
327 StatusCode sc = appMgr->getProperty(&property);
328 if (!sc.isSuccess()) {
329 ATH_MSG_ERROR("checkOverrideRunNumber: unable to get EvtSel: found " << property.value());
330 return;
331 }
332 // Get EventSelector for ApplicationMgr
333 const std::string eventSelector = property.value();
334 SmartIF<IProperty> evtSel{serviceLocator()->service(eventSelector)};
335 if (!evtSel) {
336 ATH_MSG_ERROR("checkOverrideRunNumber: Cannot get EventSelector " << eventSelector);
337 return;
338 }
339
340 // Is flag set to override the run number?
341 BooleanProperty overrideRunNumber("OverrideRunNumberFromInput", false);
342 sc = evtSel->getProperty(&overrideRunNumber);
343 if (!sc.isSuccess()) {
344 // Not all EventSelectors have this property, so we must be tolerant
345 ATH_MSG_DEBUG("resetRunNumber: unable to get OverrideRunNumberFromInput property from EventSelector ");
346 return;
347 }
348 m_overrideRunNumber = overrideRunNumber.value();
350 // New run number
351 IntegerProperty runNumber("RunNumber", 0);
352 sc = evtSel->getProperty(&runNumber);
353 if (!sc.isSuccess()) {
354 ATH_MSG_ERROR("checkOverrideRunNumber: unable to get RunNumber from EventSelector: found "
355 << runNumber.value());
356 return;
357 }
358 m_newRunNumber = runNumber.value();
359 // Old run number
360 IntegerProperty oldRunNumber("OldRunNumber", 0);
361 sc = evtSel->getProperty(&oldRunNumber);
362 if (!sc.isSuccess()) {
363 ATH_MSG_ERROR("checkOverrideRunNumber: unable to get OldRunNumber from EventSelector: found "
364 << oldRunNumber.value());
365 return;
366 }
367 m_oldRunNumber = oldRunNumber.value();
368
369 ATH_MSG_DEBUG("checkOverrideRunNumber: Changing old to new run number: " << m_oldRunNumber
370 << " " << m_newRunNumber << " obtained from " << eventSelector);
371 }
372 else ATH_MSG_DEBUG("checkOverrideRunNumber: OverrideRunNumberFromInput not set for " << eventSelector);
373}
374
375//--------------------------------------------------------------------------
376
377StatusCode
378IOVDbMetaDataTool::registerFolder(const std::string& folderName) const
379{
380 // Set the default folder description for a CondAttrListCollection
381 // which will be read back via IOVDbSvc
382 std::string folderDescr = "<timeStamp>run-event</timeStamp><addrHeader><address_header service_type=\"256\" clid=\"1238547719\" /> </addrHeader><typeName>CondAttrListCollection</typeName>" ;
383
384 return registerFolder(folderName, folderDescr);
385}
386
387//--------------------------------------------------------------------------
388
389StatusCode
390IOVDbMetaDataTool::registerFolder(const std::string& folderName,
391 const std::string& folderDescription) const
392{
393 // lock the tool before getMetaDataContainer() call
394 std::scoped_lock guard( m_mutex );
395
396 ATH_MSG_DEBUG("begin registerFolder ");
397
398 if( ! getMetaDataContainer(folderName, folderDescription) ) {
399 ATH_MSG_ERROR("Unable to register folder " << folderName);
400 return(StatusCode::FAILURE);
401 }
402 else {
403 ATH_MSG_DEBUG("IOVMetaDataContainer for folder " << folderName << " has been registered ");
404 }
405
406 return StatusCode::SUCCESS;
407}
408
409//--------------------------------------------------------------------------
410
411StatusCode IOVDbMetaDataTool::addPayload (const std::string& folderName
412 , CondAttrListCollection* payload) const
413{
414 // lock the tool while it is modifying the folder
415 std::scoped_lock guard( m_mutex );
416
417 ATH_MSG_DEBUG("begin addPayload ");
418
419 // Check if the folder has already been found
420 IOVMetaDataContainer* cont = m_metaDataStore->tryRetrieve<IOVMetaDataContainer>(folderName);
421 if(cont) {
422 ATH_MSG_DEBUG("Retrieved IOVMetaDataContainer from MetaDataStore for folder "
423 << folderName);
424 }
425 else {
426 ATH_MSG_ERROR("addPayload: Could not find IOVMetaDataContainer in MetaDataStore for folder "
427 << folderName
428 << ". One must have previously called registerFolder. ");
429 return StatusCode::FAILURE;
430 }
431
432 // Override run number if requested
434 ATH_CHECK( overrideIOV(payload) );
435 }
436
437 // Add payload to container
438 bool success = cont->merge(payload);
439 if (success) {
440 ATH_MSG_DEBUG("Added new payload for folder " << folderName);
441 }
442 else {
443 ATH_MSG_DEBUG("Could not add new payload for folder "
444 << folderName
445 << " (may be duplicate payload).");
446
447 // To Do: the function implicitly assumes ownership on the payload pointer
448 delete payload;
449 payload = nullptr;
450 }
451
452 // Debug printout
453 if(payload && msgLvl(MSG::DEBUG)) {
454 std::ostringstream stream;
455 payload->dump(stream);
456 ATH_MSG_DEBUG(stream.str());
457 }
458
459 return StatusCode::SUCCESS;
460}
461
462//--------------------------------------------------------------------------
463
464StatusCode
465IOVDbMetaDataTool::modifyPayload (const std::string& folderName,
466 CondAttrListCollection*& coll) const
467{
468 // protected by lock in processInputFileMetaData()
469
472 ATH_MSG_DEBUG("begin modifyPayload for folder " << folderName);
473
474 // check if this folder needs to be modified
475 bool modifyAttr = false;
476 std::string attributeName;
477 const std::vector<std::string>& folders = m_foldersToBeModified.value();
478 const std::vector<std::string>& attrs = m_attributesToBeRemoved.value();
479 for (unsigned int i = 0; i < folders.size(); ++i) {
480 if (folderName == folders[i]) {
481 if (attrs.size() > i) {
482 attributeName = attrs[i];
483 modifyAttr = true;
484 ATH_MSG_DEBUG("modifyPayload: remove attribute " << attributeName);
485 break;
486 }
487 }
488 }
489
490 if (!modifyAttr) {
491 ATH_MSG_DEBUG("modifyPayload: folder " << folderName << " OK ");
492 return StatusCode::SUCCESS;
493 }
494
495 bool iovSizeIsZero = coll->iov_size() == 0;
496 IOVRange testIOV = coll->minRange();
497 IOVTime start = testIOV.start();
498 IOVTime stop = testIOV.stop();
499 // Set the IOV
501 if (iovSizeIsZero) {
502 // Only add in overall range if channels do not have
503 // IOVs - otherwise this is automatically calculated
504 coll1->addNewStart(start);
505 coll1->addNewStop (stop);
506 }
507 // Add in channels
508 unsigned int nchans = coll->size();
509 bool hasChanNames = (coll->name_size() == nchans);
510 for (unsigned int ichan = 0; ichan < nchans; ++ichan) {
511 CondAttrListCollection::ChanNum chan = coll->chanNum(ichan);
512 // Now filter out the unwanted attribute
514 const CondAttrListCollection::AttributeList& oldAttrList = coll->attributeList(chan);
515 for (unsigned int iatt = 0; iatt < oldAttrList.size(); ++iatt) {
516 // skip the unwanted attribute
517 if (attributeName == oldAttrList[iatt].specification().name()) {
518 ATH_MSG_DEBUG("modifyPayload: skipping attribute name " << oldAttrList[iatt].specification().name());
519 continue;
520 }
521
522 // copy the rest
523 newAttrList.extend(oldAttrList[iatt].specification().name(),
524 oldAttrList[iatt].specification().type());
525 const coral::Attribute& oldAttr = oldAttrList[iatt];
526 coral::Attribute& newAttr = newAttrList[oldAttrList[iatt].specification().name()];
527 newAttr = oldAttr;
528 // newAttr.setValue(oldAttr.data());
529 ATH_MSG_DEBUG("modifyPayload: copying attr name "
530 << oldAttrList[iatt].specification().name() << " "
531 /*<< newAttr*/);
532 }
533 coll1->add(chan, newAttrList);
534 if (!iovSizeIsZero) coll1->add(chan, coll->iovRange(chan));
535 if(hasChanNames)coll1->add(chan, coll->chanName(chan));
536 ATH_MSG_DEBUG("modifyPayload: copied attribute list for channel " << chan);
537 }
538 delete coll;
539 coll = coll1;
540 if (msgLvl(MSG::DEBUG)) {
541 std::ostringstream stream;
542 coll->dump(stream);
543 ATH_MSG_DEBUG(stream.str());
544 }
545
546 return StatusCode::SUCCESS;
547}
548
549//--------------------------------------------------------------------------
550
552IOVDbMetaDataTool::findMetaDataContainer(const std::string& folderName) const
553{
554 // lock the tool before this call
555 // Return the folder if it is in the meta data store
556 return m_metaDataStore->tryRetrieve<IOVMetaDataContainer>(folderName);
557}
558
559
561IOVDbMetaDataTool::getMetaDataContainer(const std::string& folderName
562 , const std::string& folderDescription) const
563{
564 // protected by locks in addPayload() and registerFolder()
565 ATH_MSG_DEBUG("begin getMetaDataContainer ");
566
567 IOVMetaDataContainer* cont{nullptr};
568 // See if it is in the meta data store
569 if (!m_metaDataStore->contains<IOVMetaDataContainer>(folderName)) {
570 // Container not found, add in new one
571 cont = new IOVMetaDataContainer(folderName, folderDescription);
572 ATH_MSG_DEBUG("No IOVMetaDataContainer in MetaDataStore for folder " << folderName
573 << ". Created a new instance");
574 StatusCode sc = m_metaDataStore->record(cont, folderName);
575 if (!sc.isSuccess()) {
576 ATH_MSG_ERROR("Could not record IOVMetaDataContainer in MetaDataStore for folder " << folderName);
577 delete cont;
578 cont = nullptr;
579 }
580 }
581 else {
582 ATH_MSG_DEBUG("IOVMetaDataContainer already in MetaDataStore for folder " << folderName);
583 StatusCode sc = m_metaDataStore->retrieve(cont, folderName);
584 if (!sc.isSuccess()) {
585 ATH_MSG_ERROR("Could not retrieve IOVMetaDataContainer in MetaDataStore for folder " << folderName);
586 cont = nullptr;
587 }
588 }
589 return cont;
590}
591
592//--------------------------------------------------------------------------
593
594StatusCode IOVDbMetaDataTool::processInputFileMetaData(const std::string& fileName)
595{
596 // lock the tool while it is processing input metadata
597 std::scoped_lock guard( m_mutex );
598
599 ATH_MSG_DEBUG("processInputFileMetaData: file name " << fileName);
600
601 // Retrieve all meta data containers from InputMetaDataStore
604
605 StatusCode sc = m_inputStore->retrieve(cont, contEnd);
606 if (!sc.isSuccess()) {
607 ATH_MSG_DEBUG("processInputFileMetaData: Could not retrieve IOVMetaDataContainer objects from InputMetaDataStore - cannot process input file meta data");
608 return StatusCode::SUCCESS;
609 }
610
611 ATH_MSG_DEBUG("processInputFileMetaData: Retrieved from IOVMetaDataContainer(s) from InputMetaDataStore");
612
613 // For each container, merge its contents into the MetaDataStore
614 unsigned int ncolls = 0;
615 unsigned int ndupColls = 0;
616 for (; cont != contEnd; ++cont) {
617 IOVMetaDataContainer* contMaster = getMetaDataContainer(cont->folderName()
618 , cont->folderDescription());
619
620 // We assume that the folder is the same for all versions, and
621 // now we loop over versions for the payloads
622 std::list<SG::ObjectWithVersion<IOVMetaDataContainer> > allVersions;
623 sc = m_inputStore->retrieveAllVersions(allVersions, cont.key());
624 if (!sc.isSuccess()) {
625 ATH_MSG_ERROR("Could not retrieve all versions for " << cont.key());
626 return sc;
627 }
628
629 for (SG::ObjectWithVersion<IOVMetaDataContainer>& obj : allVersions) {
630 const IOVPayloadContainer* payload = obj.dataObject->payloadContainer();
631
632 ATH_MSG_DEBUG("processInputFileMetaData: New container: payload size " << payload->size() << " version key " << obj.versionedKey);
633
634 // detailed printout before merge
635 if (msgLvl(MSG::VERBOSE)) {
636 const IOVPayloadContainer* payloadMaster = contMaster->payloadContainer();
637 ATH_MSG_VERBOSE("Before merge, payload minRange for folder " << cont->folderName());
638 if (payloadMaster && payloadMaster->size()) {
639 // Loop over AttrColls and print out minRange
640 IOVPayloadContainer::const_iterator itColl = payloadMaster->begin();
641 IOVPayloadContainer::const_iterator itCollEnd = payloadMaster->end();
642 unsigned int iPayload = 0;
643 for (; itColl != itCollEnd; ++itColl, ++iPayload) {
644 ATH_MSG_VERBOSE(iPayload << " " << (*itColl)->minRange() << " "
645 << (*itColl)->size());
646 }
647 }
648 else {
649 ATH_MSG_VERBOSE(" no payloads yet!");
650 }
651 }
652 }
653
654 // Detailed printout
655 if (msgLvl(MSG::DEBUG)) {
656 ATH_MSG_DEBUG("processInputFileMetaData: Current payload before merge " << contMaster->folderName());
658 IOVPayloadContainer::const_iterator itCollEnd1 = contMaster->payloadContainer()->end();
659 std::ostringstream stream;
660 for (; itColl1 != itCollEnd1; ++itColl1) (*itColl1)->dump(stream);
661 ATH_MSG_DEBUG(stream.str());
662 }
663
664 //
665 // Loop over CondAttrListCollections and do merge
666 //
667 for (SG::ObjectWithVersion<IOVMetaDataContainer>& obj : allVersions) {
668 const IOVPayloadContainer* payload = obj.dataObject->payloadContainer();
669 IOVPayloadContainer::const_iterator itColl = payload->begin();
670 IOVPayloadContainer::const_iterator itCollEnd = payload->end();
671 for (; itColl != itCollEnd; ++itColl) {
672
673 // Make a copy of the collection and merge it into
674 // master container in meta data store
676 // Override run number if requested
678 ATH_CHECK( overrideIOV(coll) );
679 }
680
681 // first check if we need to modify the incoming payload
682 if (!modifyPayload (contMaster->folderName(), coll).isSuccess()) {
683 ATH_MSG_ERROR("processInputFileMetaData: Could not modify the payload for folder " << contMaster->folderName());
684 return StatusCode::FAILURE;
685 }
686
687 ATH_MSG_VERBOSE("processInputFileMetaData: merge minRange: " << coll->minRange());
688 if (!contMaster->merge(coll)) {
689 // Did not merge it in - was a duplicate, so we need to delete it
690 delete coll;
691 ++ndupColls;
692 ATH_MSG_VERBOSE(" => not merged ");
693 }
694 else {
695 ++ncolls;
696 ATH_MSG_VERBOSE(" => merged ");
697 }
698
699 }
700 ATH_MSG_DEBUG("processInputFileMetaData: Merged together containers for folder " << cont->folderName() << " ncoll/ndup "
701 << ncolls << " " << ndupColls);
702
703 // Check for consistency after merge
704 const IOVPayloadContainer* payloadMaster = contMaster->payloadContainer();
705 if (payloadMaster && payloadMaster->size()) {
706 // Loop over AttrColls and print out minRange
707 IOVPayloadContainer::const_iterator itColl = payloadMaster->begin();
708 IOVPayloadContainer::const_iterator itCollEnd = payloadMaster->end();
709 IOVTime lastStop;
710 if ((*itColl)->minRange().start().isTimestamp()) lastStop = IOVTime(0);
711 else lastStop = IOVTime(0,0);
712 bool hasError = false;
713 for (; itColl != itCollEnd; ++itColl) {
714 if ((*itColl)->minRange().start() < lastStop) hasError = true;
715 lastStop = (*itColl)->minRange().stop();
716 }
717 if (hasError) {
718 ATH_MSG_ERROR("processInputFileMetaData: error after merge of file meta data. " );
719 ATH_MSG_ERROR("processInputFileMetaData: Filename " << fileName);
720 ATH_MSG_ERROR("processInputFileMetaData: folder " << contMaster->folderName());
721 ATH_MSG_ERROR("processInputFileMetaData: MinRange for meta data folders ");
722 unsigned int iPayload = 0;
723 itColl = payloadMaster->begin();
724 for (; itColl != itCollEnd; ++itColl, ++iPayload) {
725 ATH_MSG_ERROR(iPayload << " " << (*itColl)->minRange() << " " << (*itColl)->size());
726 }
727 }
728 }
729
730 // detailed printout after merge
731 if (msgLvl(MSG::VERBOSE)) {
732 const IOVPayloadContainer* payloadMaster = contMaster->payloadContainer();
733 ATH_MSG_VERBOSE("processInputFileMetaData: After merge, payload minRange ");
734 if (payloadMaster) {
735 // Loop over AttrColls and print out minRange
736 IOVPayloadContainer::const_iterator itColl = payloadMaster->begin();
737 IOVPayloadContainer::const_iterator itCollEnd = payloadMaster->end();
738 unsigned int iPayload = 0;
739 for (; itColl != itCollEnd; ++itColl, ++iPayload) {
740 ATH_MSG_VERBOSE(iPayload << " " << (*itColl)->minRange() << " "
741 << (*itColl)->size());
742 }
743 }
744 else { ATH_MSG_ERROR(" no payloads yet!"); }
745 }
746
747 // Detailed printout
748 if (msgLvl(MSG::DEBUG)) {
749 ATH_MSG_DEBUG("processInputFileMetaData: Input payload " << cont->folderName());
750 std::ostringstream streamInp;
751 itColl = payload->begin();
752 itCollEnd = payload->end();
753 for (; itColl != itCollEnd; ++itColl) (*itColl)->dump(streamInp);
754 ATH_MSG_DEBUG(streamInp.str());
755 ATH_MSG_DEBUG("processInputFileMetaData: Output payload " << contMaster->folderName());
756 std::ostringstream streamOut;
757 itColl = contMaster->payloadContainer()->begin();
758 itCollEnd = contMaster->payloadContainer()->end();
759 for (; itColl != itCollEnd; ++itColl) (*itColl)->dump(streamOut);
760 ATH_MSG_DEBUG(streamOut.str());
761 }
762 }
763 }
764
765 ATH_MSG_DEBUG("processInputFileMetaData: Total number of attribute collections merged together " << ncolls
766 << " Number of duplicate collections " << ndupColls);
767
768 // Also populate ConditionStore for parameter folders when reading from file metadata
769 // without intermediate sqlite files (direct in-file metadata mode).
770 // Only do this if IOVDbSvc hasn't registered the folder (checked by CondCont existence).
771 // Note: We're already holding m_mutex lock, so we populate ConditionStore directly
772 // without calling addPayload() to avoid deadlock.
773 //
774 // This can only be done when we have a valid EventContext (i.e., during event processing),
775 // not during file opening when this method is typically called.
776 const EventContext& currentCtx = Gaudi::Hive::currentContext();
777 if (currentCtx.valid()) {
778 constexpr std::array folderNames{"/Digitization/Parameters", "/Simulation/Parameters"};
779 for (std::string_view folderName : folderNames) {
780 // Skip if folder doesn't exist in MetaDataStore (e.g., old files without these folders)
781 if (!m_metaDataStore->contains<IOVMetaDataContainer>(std::string(folderName))) {
782 continue;
783 }
784
785 // Skip if folder is in Payloads (write-only mode for overlay)
786 // When Payloads contains entries for a folder, we're explicitly providing the data
787 // and don't need to read from input file
788 bool inPayloads = false;
789 for (const auto& [key, value] : m_payloads) {
790 if (key.find(std::string(folderName) + ":") == 0) {
791 inPayloads = true;
792 break;
793 }
794 }
795 if (inPayloads) {
796 ATH_MSG_DEBUG("Folder " << folderName << " is in Payloads, skipping auto-read from input");
797 continue;
798 }
799
800 // Check MetaDataStore (merged view of metadata from all input files)
801 IOVMetaDataContainer* contMaster = nullptr;
802 if (m_metaDataStore->retrieve(contMaster, std::string(folderName)).isSuccess() && contMaster) {
803 const IOVPayloadContainer* payloadMaster = contMaster->payloadContainer();
804 if (payloadMaster && payloadMaster->size() > 0) {
805 // Ensure ConditionStore is available
806 if (!m_condStore.isValid()) {
807 ATH_CHECK(m_condStore.retrieve());
808 }
809
810 // Check if CondCont already exists - if so, IOVDbSvc is managing it
811 if (m_condStore->contains<CondCont<AthenaAttributeList>>(std::string(folderName))) {
812 ATH_MSG_DEBUG("CondCont for " << folderName << " already exists, skipping");
813 continue;
814 }
815
816 // Get the first payload (should only be one for parameter folders)
817 const CondAttrListCollection* coll = dynamic_cast<const CondAttrListCollection*>(*(payloadMaster->begin()));
818 if (coll) {
819 // Create new CondCont using CondContFactory
820 CondCont<AthenaAttributeList>* cc = nullptr;
821 ServiceHandle<Athena::IRCUSvc> rcuSvc("Athena::RCUSvc", name());
822 ATH_CHECK(rcuSvc.retrieve());
823
827 std::string(folderName));
828 if (!cb) {
829 ATH_MSG_ERROR("Failed to create CondCont for " << folderName);
830 return StatusCode::FAILURE;
831 }
832
833 if (m_condStore->recordObject(cb, std::string(folderName), true, false) == nullptr) {
834 ATH_MSG_ERROR("Failed to record CondCont for " << folderName);
835 return StatusCode::FAILURE;
836 }
837
838 // Retrieve the CondCont
839 ATH_CHECK(m_condStore->retrieve(cc, std::string(folderName)));
840
841 // Extract AthenaAttributeList from CondAttrListCollection and insert into CondCont
842 auto itr = coll->begin();
843 const coral::AttributeList& attrList = itr->second;
844 auto athAttrList = std::make_unique<AthenaAttributeList>(attrList);
845
846 // Create EventIDRange from the collection's IOV
847 IOVRange iovRange = coll->minRange();
848 EventIDBase start, stop;
849 start.set_run_number(iovRange.start().run());
850 start.set_lumi_block(iovRange.start().event());
851 stop.set_run_number(iovRange.stop().run());
852 stop.set_lumi_block(iovRange.stop().event());
853 EventIDRange range(start, stop);
854
855 // Insert into CondCont (we already checked that currentCtx is valid)
856 ATH_CHECK(cc->insert(range, std::move(athAttrList), currentCtx));
857
858 ATH_MSG_DEBUG("Populated ConditionStore for " << folderName << " from file metadata");
859 }
860 }
861 }
862 }
863 }
864
865 // Serialize requested IOV folders to ByteStream metadata
867
868 return StatusCode::SUCCESS;
869}
870
871//--------------------------------------------------------------------------
872
873std::string
875{
876 const IOVPayloadContainer* payloads = container->payloadContainer();
877 if (!payloads || payloads->size() == 0) {
878 ATH_MSG_WARNING("No payloads for folder " << container->folderName());
879 return "";
880 }
881
882 using json = nlohmann::json;
883 json jsonData;
884
885 jsonData["folder"] = container->folderName();
886 jsonData["description"] = container->folderDescription();
887 jsonData["iovs"] = json::array();
888
889 // Serialize each IOV payload
890 for (const CondAttrListCollection* coll : *payloads) {
891 json iov;
892
893 // Get IOV range
894 IOVRange range = coll->minRange();
895 IOVTime start = range.start();
896 IOVTime stop = range.stop();
897
898 // IOV range
899 if (start.isRunEvent()) {
900 iov["range"]["start"] = {{"run", start.run()}, {"event", start.event()}};
901 iov["range"]["stop"] = {{"run", stop.run()}, {"event", stop.event()}};
902 } else {
903 iov["range"]["start"] = {{"timestamp", start.timestamp()}};
904 iov["range"]["stop"] = {{"timestamp", stop.timestamp()}};
905 }
906
907 // Attributes (serialize each channel)
908 iov["attrs"] = json::object();
909 for (const auto& chanAttrPair : *coll) {
910 CondAttrListCollection::ChanNum chan = chanAttrPair.first;
911 const coral::AttributeList& attrList = chanAttrPair.second;
912
913 std::string chanKey = "chan" + std::to_string(chan);
914 iov["attrs"][chanKey] = json::object();
915
916 for (const auto& attr : attrList) {
917 auto & thisAttribute = iov["attrs"][chanKey][attr.specification().name()];
918 // Serialize attribute value based on type
919 const std::type_info& type = attr.specification().type();
920 if (type == typeid(std::string)) {
921 thisAttribute = attr.data<std::string>();
922 } else if (type == typeid(int)) {
923 thisAttribute = attr.data<int>();
924 } else if (type == typeid(unsigned int)) {
925 thisAttribute = attr.data<unsigned int>();
926 } else if (type == typeid(long)) {
927 thisAttribute = attr.data<long>();
928 } else if (type == typeid(unsigned long)) {
929 thisAttribute = attr.data<unsigned long>();
930 } else if (type == typeid(long long)) {
931 thisAttribute = attr.data<long long>();
932 } else if (type == typeid(unsigned long long)) {
933 thisAttribute = attr.data<unsigned long long>();
934 } else if (type == typeid(float)) {
935 thisAttribute = attr.data<float>();
936 } else if (type == typeid(double)) {
937 thisAttribute = attr.data<double>();
938 } else if (type == typeid(bool)) {
939 thisAttribute = attr.data<bool>();
940 } else {
941 // For other types, convert to string representation
942 std::ostringstream oss;
943 attr.toOutputStream(oss);
944 thisAttribute = oss.str();
945 ATH_MSG_DEBUG("Attribute " << attr.specification().name() << " has unsupported type, converted to string: " << oss.str());
946 }
947 }
948 }
949
950 jsonData["iovs"].push_back(iov);
951 }
952
953 return jsonData.dump();
954}
955
956//--------------------------------------------------------------------------
957
958StatusCode
960{
961 ATH_MSG_DEBUG("overrideIOV ");
962
963 // Override the IOV for run/event IOVs
964
965 // (ONLY TRUE FOR OVERRIDE COMING IN VIA EVENTSELECTOR:)
966 // NOTE: we require that the old run number falls within the
967 // IOVRange of the incoming collection. We override ALL IOVs for
968 // ALL channels forcing the IOVRange to be (newRunNumber,1) to
969 // (newRunNumber+1,1)
970
971 bool iovSizeIsZero = coll->iov_size() == 0;
972 IOVRange testIOV = coll->minRange();
973 IOVTime start = testIOV.start();
974 IOVTime stop = testIOV.stop();
975 IOVTime oldRun(m_oldRunNumber, 0);
976 if (start.isRunEvent() && stop.isRunEvent()) { // only for run/event
977 IOVRange newRange;
978 // Two ways of resetting
980 else if (m_overrideRunNumber) newRange = IOVRange(IOVTime(m_newRunNumber, 0), IOVTime(m_newRunNumber + 1, 0));
981
982 if (m_overrideRunNumber && !testIOV.isInRange(oldRun)) {
983 // old run must be in the range
984 ATH_MSG_ERROR("overrideIOV: old run number does not match. Old run number " << m_oldRunNumber << " IOVRange: " << testIOV);
985 return StatusCode::SUCCESS;
986 }
987
988 ATH_MSG_DEBUG("overrideIOV: overrideMinMaxRunNumber: " << (int)m_overrideMinMaxRunNumber
989 << " overrideRunNumber " << (int)m_overrideRunNumber
990 << " iovSizeIsZero: " << (int)iovSizeIsZero
991 << " newRange " << newRange);
992
993 // Now over ride IOVs - two cases: 1) single IOV for full collection, 2) IOVs for individual channels.
994 // Must treat the reset of collection IOV differently
995 if (iovSizeIsZero) {
996 // Only add in overall range if channels do not have
997 // IOVs - otherwise this is automatically calculated
998 coll->resetMinRange(); // must first reset to 'full range' and then reduce the IOVRange accordingly
999 coll->addNewStart(newRange.start());
1000 coll->addNewStop (newRange.stop());
1001 }
1002 else {
1003 // Add in channels
1004 unsigned int nchans = coll->size();
1005 ATH_MSG_DEBUG("overrideIOV: nchans " << nchans);
1006 for (unsigned int ichan = 0; ichan < nchans; ++ichan) {
1007 // FIXME: O(N^2)!
1008 CondAttrListCollection::ChanNum chan = coll->chanNum(ichan);
1009 coll->add(chan, newRange);
1010 ATH_MSG_DEBUG("overrideIOV: overriding the IOV of collection chan " << chan);
1011 }
1012 // must reset the collection range AFTER the channels, because the collection range will be
1013 // 'narrowed' to that of the channels
1014 coll->resetMinRange();
1015 }
1016 if (msgLvl(MSG::DEBUG)) {
1017 ATH_MSG_DEBUG("overrideIOV: after overriding the IOV of collection");
1018 std::ostringstream stream;
1019 coll->dump(stream);
1020 ATH_MSG_DEBUG(stream.str());
1021 }
1022 }
1023 else ATH_MSG_DEBUG("overrideIOV: IOV is not run/event ");
1024
1025 return StatusCode::SUCCESS;
1026}
1027
1028
1029//--------------------------------------------------------------------------
#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
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.
const_iterator begin() const
Access to Chan/AttributeList pairs via iterators.
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.
Hold mapping of ranges to condition objects.
Definition CondCont.h:889
SG::DataObjectSharedPtr< DataObject > Create(Athena::IRCUSvc &rcusvc, const CLID &clid, const std::string &key) const
static CondContFactory & Instance()
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
uint32_t event() const noexcept
Definition IOVTime.h:106
uint32_t run() const noexcept
Definition IOVTime.h:105
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.
CxxUtils::RefCountedPtr< T > DataObjectSharedPtr
ElementLink_p1< typename GenerateELinkIndexType_p1< typename LINK::index_type >::type > type