ATLAS Offline Software
Loading...
Searching...
No Matches
AthenaOutputStreamTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
9
11
12// Gaudi
13#include "GaudiKernel/IOpaqueAddress.h"
14#include "GaudiKernel/INamedInterface.h"
15#include "GaudiKernel/IClassIDSvc.h"
16#include "GaudiKernel/ThreadLocalContext.h"
17
18// Athena
22#include "SGTools/DataProxy.h"
23#include "SGTools/SGIFolder.h"
27
28
29namespace {
30
33bool hasInputAlias (const SG::DataProxy& dp)
34{
35 std::string inputName = dp.name() + "_Input";
36 return dp.hasAlias (inputName);
37}
38
39
40} // anonymous namespace
41
44 const std::string& name,
45 const IInterface* parent) : base_class(type, name, parent),
46 m_clidSvc("ClassIDSvc", name),
47 m_decSvc("DecisionSvc/DecisionSvc", name) {
48}
49//__________________________________________________________________________
51 ATH_MSG_INFO("Initializing " << name());
52
53 ATH_CHECK( m_clidSvc.retrieve() );
54 ATH_CHECK( m_conversionSvc.retrieve() );
55
56 // Autoconfigure
57 if (m_dataHeaderKey.empty()) {
58 m_dataHeaderKey.setValue(name());
59 // Remove "ToolSvc." from m_dataHeaderKey.
60 if (m_dataHeaderKey.value().starts_with( "ToolSvc.")) {
61 m_dataHeaderKey.setValue(m_dataHeaderKey.value().substr(8));
62 // Remove "Tool" from m_dataHeaderKey.
63 if (m_dataHeaderKey.value().find("Tool") == m_dataHeaderKey.size() - 4) {
64 m_dataHeaderKey.setValue(m_dataHeaderKey.value().substr(0, m_dataHeaderKey.size() - 4));
65 }
66 } else {
67 const INamedInterface* parentAlg = dynamic_cast<const INamedInterface*>(parent());
68 if (parentAlg != 0) {
69 m_dataHeaderKey.setValue(parentAlg->name());
70 }
71 }
72 }
73 if (m_processTag.empty()) {
75 }
76
77 { // handle the AttrKey overwrite
78 const std::string keyword = "[AttributeListKey=";
79 std::string::size_type pos = m_outputName.value().find(keyword);
80 if( (pos != std::string::npos) ) {
81 ATH_MSG_INFO("The AttrListKey will be overwritten/set by the value from the OutputName: " << m_outputName);
82 const std::string attrListKey = m_outputName.value().substr(pos + keyword.size(),
83 m_outputName.value().find(']', pos + keyword.size()) - pos - keyword.size());
84 m_attrListKey = attrListKey;
85 }
86 }
87 if ( ! m_attrListKey.key().empty() ) {
88 ATH_CHECK(m_attrListKey.initialize());
89 m_attrListWrite = m_attrListKey.key() + "Decisions";
90 //ATH_CHECK(m_attrListWrite.initialize());
91 }
92
93 if (!m_outputCollection.value().empty()) {
94 m_outputAttributes += "[OutputCollection=" + m_outputCollection.value() + "]";
95 }
96 if (!m_containerPrefix.value().empty()) {
97 m_outputAttributes += "[PoolContainerPrefix=" + m_containerPrefix.value() + "]";
98 }
99 if (m_containerNameHint.value() != "0") {
100 m_outputAttributes += "[TopLevelContainerName=" + m_containerNameHint.value() + "]";
101 }
102 if (m_branchNameHint.value() != "0") {
103 m_outputAttributes += "[SubLevelBranchName=" + m_branchNameHint.value() + "]";
104 }
105 if (!m_metaDataOutputCollection.value().empty()) {
106 m_metaDataOutputAttributes += "[OutputCollection=" + m_metaDataOutputCollection.value() + "]";
107 }
108 if (!m_metaDataContainerPrefix.value().empty()) {
109 m_metaDataOutputAttributes += "[PoolContainerPrefix=" + m_metaDataContainerPrefix.value() + "]";
110 }
111
112 if (m_extend) ATH_CHECK(m_decSvc.retrieve());
113 return(StatusCode::SUCCESS);
114}
115//__________________________________________________________________________
116StatusCode AthenaOutputStreamTool::connectServices(const std::string& dataStore,
117 const std::string& cnvSvc,
118 bool extendProvenenceRecord) {
119 // Release old data store
120 if (m_store.isValid()) {
121 if (m_store.release().isFailure()) {
122 ATH_MSG_ERROR("Could not release " << m_store.typeAndName() << " store");
123 }
124 }
125 m_store = ServiceHandle<StoreGateSvc>(dataStore, this->name());
126 if (cnvSvc != m_conversionSvc.type() && cnvSvc != "EventPersistencySvc") {
127 if (m_conversionSvc.release().isFailure()) {
128 ATH_MSG_ERROR("Could not release " << m_conversionSvc.type());
129 }
130 m_conversionSvc = ServiceHandle<IConversionSvc>(cnvSvc, this->name());
131 if (m_conversionSvc.retrieve().isFailure() || m_conversionSvc == 0) {
132 ATH_MSG_ERROR("Could not locate " << m_conversionSvc.type());
133 return(StatusCode::FAILURE);
134 }
135 }
136 m_extendProvenanceRecord = extendProvenenceRecord;
137 auto pprop = dynamic_cast<const IProperty*>(parent());
138 if (not pprop){
139 ATH_MSG_ERROR("'parent' could not be cast to IProperty");
140 return(StatusCode::FAILURE);
141 }
142 auto keep = dynamic_cast<const StringProperty&>( pprop->getProperty("KeepProvenanceTagsRegEx") );
143 m_keepProvenancesStr = keep.value();
144 // create RegEx pattern from the property value, specify extended grammar
145 m_keepProvenancesRE = std::regex(m_keepProvenancesStr, std::regex::extended);
146
147 return(connectServices());
148}
149//__________________________________________________________________________
151 // Find the data store
152 if (m_store.retrieve().isFailure() || m_store == 0) {
153 ATH_MSG_ERROR("Could not locate " << m_store.typeAndName() << " store");
154 return(StatusCode::FAILURE);
155 }
156 return(StatusCode::SUCCESS);
157}
158//__________________________________________________________________________
159StatusCode AthenaOutputStreamTool::connectOutput(const std::string& outputName) {
160 ATH_MSG_DEBUG("In connectOutput " << outputName);
161
162 // Use arg if not empty, save the output name
163 if (!outputName.empty()) {
164 m_outputName.setValue(outputName);
165 }
166 if (m_outputName.value().empty()) {
167 ATH_MSG_ERROR("No OutputName provided");
168 return(StatusCode::FAILURE);
169 }
170 // Connect services if not already available
171 if (m_store == 0 || m_conversionSvc == 0) {
173 }
174 // Connect the output file to the service
175 if (m_conversionSvc->connectOutput(m_outputName.value()).isFailure()) {
176 ATH_MSG_ERROR("Unable to connect output " << m_outputName.value());
177 return(StatusCode::FAILURE);
178 } else {
179 ATH_MSG_DEBUG("Connected to " << m_outputName.value());
180 }
181
182 // Remove DataHeader with same key if it exists
183 if (m_store->contains<DataHeader>(m_dataHeaderKey)) {
184 const DataHeader* preDh = nullptr;
185 if (m_store->retrieve(preDh, m_dataHeaderKey).isSuccess()) {
186 if (m_store->removeDataAndProxy(preDh).isFailure()) {
187 ATH_MSG_ERROR("Unable to get proxy for the DataHeader with key " << m_dataHeaderKey);
188 return(StatusCode::FAILURE);
189 }
190 ATH_MSG_DEBUG("Released DataHeader with key " << m_dataHeaderKey);
191 }
192 }
193
194 // Create new DataHeader
195 m_dataHeader = new DataHeader();
196 m_dataHeader->setProcessTag(m_processTag);
197
198 // Retrieve all existing DataHeaders from StoreGate
199 const DataHeader* dh = nullptr;
200 std::vector<std::string> dhKeys;
201 m_store->keys<DataHeader>(dhKeys);
202 //construct string out of loop
203 const std::string boolTypeStr{"bool"};
204 for (const std::string& dhKey : dhKeys) {
205 bool primaryDH = false;
206 if (!m_store->transientContains<DataHeader>(dhKey)) {
207 if (dhKey == "EventSelector") primaryDH = true;
208 ATH_MSG_DEBUG("No transientContains DataHeader with key " << dhKey);
209 }
210 if (m_store->retrieve(dh, dhKey).isFailure()) {
211 ATH_MSG_DEBUG("Unable to retrieve the DataHeader with key " << dhKey);
212 }
213 if (dh->isInput() || hasInputAlias(*m_store->proxy(dh)) || primaryDH) {
214 propagateProvenance( *dh );
215 }
216 }
217
218 // Attach the attribute list to the DataHeader if requested
219 if (!m_attrListKey.key().empty() && m_store->storeID() == StoreID::EVENT_STORE) {
220 auto attrListHandle = SG::makeHandle(m_attrListKey);
221 if (!attrListHandle.isValid()) {
222 ATH_MSG_WARNING("Unable to retrieve AttributeList with key " << m_attrListKey);
223 } else {
224 m_dataHeader->setAttributeList(attrListHandle.cptr());
225 if (m_extend) { // Add streaming decisions
226 ATH_MSG_DEBUG("Adding stream decisions to " << m_attrListWrite);
227 // Look for attribute list created for mini-EventInfo
228 const AthenaAttributeList* attlist(attrListHandle.cptr());
229
230 // Build new attribute list for modification
231 AthenaAttributeList* newone = new AthenaAttributeList(attlist->specification());
232 newone->copyData(*attlist);
233
234 // Now loop over stream definitions and add decisions
235 auto streams = m_decSvc->getStreams();
236 for (auto it = streams.begin();
237 it != streams.end(); ++it) {
238 newone->extend(*it,boolTypeStr);
239 (*newone)[*it].data<bool>() = m_decSvc->isEventAccepted(*it,Gaudi::Hive::currentContext());
240 ATH_MSG_DEBUG("Added stream decision for " << *it << " to " << m_attrListKey);
241 }
242 // record new attribute list with old key + suffix
243 const AthenaAttributeList* attrList2 = nullptr;
245 if (m_store->record(newone,m_attrListWrite).isFailure()) {
246 ATH_MSG_ERROR("Unable to record att list " << m_attrListWrite);
247 }
248 } else {
249 ATH_MSG_DEBUG("Decisions already added by a different stream");
250 }
251 if (m_store->retrieve(attrList2,m_attrListWrite).isFailure()) {
252 ATH_MSG_ERROR("Unable to record att list " << m_attrListWrite);
253 } else {
254 m_dataHeader->setAttributeList(attrList2);
255 }
256 } // list extend check
257 } // list retrieve check
258 } // list property check
259
260 // Record DataHeader in StoreGate
262 if (wh.record(std::unique_ptr<DataHeader>(m_dataHeader)).isFailure()) {
263 ATH_MSG_ERROR("Unable to record DataHeader with key " << m_dataHeaderKey);
264 return(StatusCode::FAILURE);
265 } else {
266 ATH_MSG_DEBUG("Recorded DataHeader with key " << m_dataHeaderKey);
267 }
269 // Set flag that connection is open
270 m_connectionOpen = true;
271 return(StatusCode::SUCCESS);
272}
273
274//__________________________________________________________________________
276{
277 // keep track of provenance entries inserted into the new DataHeader
278 std::set<std::string> insertedTags{};
279 // Add DataHeader token to the new DataHeader
281 std::string pTag;
282 std::unique_ptr<SG::TransientAddress> dhTransAddr;
283 for (const DataHeaderElement& dhe : src_dh) {
284 if (dhe.getPrimaryClassID() == ClassID_traits<DataHeader>::ID()) {
285 pTag = dhe.getKey();
286 dhTransAddr.reset( dhe.getAddress( m_conversionSvc->repSvcType() ) );
287 }
288 }
289 // Update dhTransAddr to handle fast merged files.
290 if( auto dhProxy=m_store->proxy(&src_dh); dhProxy && dhProxy->address() ) {
291 DataHeaderElement dhe(dhProxy, dhProxy->address(), pTag);
292 m_dataHeader->insertProvenance(dhe);
293 insertedTags.insert(std::move(pTag));
294 }
295 else if( dhTransAddr ) {
296 DataHeaderElement dhe(dhTransAddr.get(), dhTransAddr->address(), pTag);
297 m_dataHeader->insertProvenance(dhe);
298 insertedTags.insert(std::move(pTag));
299 }
300 }
301
302 // empty regexpr means do not keep any provenance
303 if( !m_keepProvenancesStr.empty() ) {
304 // Each stream tag is written only once in the provenance record
305 // In files where there are multiple entries per stream tag
306 // the record is in reverse, i.e., the latest appears first.
307 // Therefore, only keep the first entry if there are multiple
308 // matches so that we retain the latest one.
309 for(auto iter=src_dh.beginProvenance(), iEnd=src_dh.endProvenance(); iter != iEnd; ++iter) {
310 const auto & currentKey = (*iter).getKey();
311 if( insertedTags.insert(currentKey).second ) {
312 // first prov with that tag. Now check if we want to keep that tag
313 bool keep = false;
314 auto it = m_keepProvenanceMatch.find( currentKey );
315 if( it != m_keepProvenanceMatch.end() ) {
316 keep = it->second;
317 } else {
318 keep = std::regex_search(currentKey, m_keepProvenancesRE);
319 m_keepProvenanceMatch[currentKey] = keep;
320 }
321 if( keep ) {
322 m_dataHeader->insertProvenance(*iter);
323 }
324 }
325 }
326 }
327}
328
329//__________________________________________________________________________
330StatusCode AthenaOutputStreamTool::commitOutput(bool doCommit) {
331 ATH_MSG_DEBUG("In commitOutput");
332 // Connect the output file to the service
333 if (m_conversionSvc->commitOutput(m_outputName.value(), doCommit).isFailure()) {
334 ATH_MSG_ERROR("Unable to commit output " << m_outputName.value());
335 return(StatusCode::FAILURE);
336 }
337 // Set flag that connection is closed
338 m_connectionOpen = false;
339 return(StatusCode::SUCCESS);
340}
341//__________________________________________________________________________
343 AthCnvSvc* athConversionSvc = dynamic_cast<AthCnvSvc*>(m_conversionSvc.get());
344 if (athConversionSvc != 0) {
345 if (athConversionSvc->disconnectOutput(m_outputName.value()).isFailure()) {
346 ATH_MSG_ERROR("Unable to finalize output " << m_outputName.value());
347 return(StatusCode::FAILURE);
348 }
349 }
350 return(StatusCode::SUCCESS);
351}
352//__________________________________________________________________________
353StatusCode AthenaOutputStreamTool::streamObjects(const TypeKeyPairs& typeKeys, const std::string& outputName) {
354 ATH_MSG_DEBUG("In streamObjects");
355 // Check that a connection has been opened
356 if (!m_connectionOpen) {
357 ATH_MSG_ERROR("Connection NOT open. Please open a connection before streaming out objects.");
358 return(StatusCode::FAILURE);
359 }
360 // Use arg if not empty, save the output name
361 if (!outputName.empty()) {
362 m_outputName.setValue(outputName);
363 }
364 if (m_outputName.value().empty()) {
365 ATH_MSG_ERROR("No OutputName provided");
366 return(StatusCode::FAILURE);
367 }
368 // Now iterate over the type/key pairs and stream out each object
369 std::vector<DataObject*> dataObjects;
370 for (TypeKeyPairs::const_iterator first = typeKeys.begin(), last = typeKeys.end();
371 first != last; ++first) {
372 const std::string& type = (*first).first;
373 const std::string& key = (*first).second;
374 // Find the clid for type name from the CLIDSvc
375 CLID clid;
376 if (m_clidSvc->getIDOfTypeName(type, clid).isFailure()) {
377 ATH_MSG_ERROR("Could not get clid for typeName " << type);
378 return(StatusCode::FAILURE);
379 }
380 DataObject* dObj = 0;
381 // Two options: no key or explicit key
382 if (key.empty()) {
383 ATH_MSG_DEBUG("Get data object with no key");
384 // Get DataObject without key
385 dObj = m_store->accessData(clid);
386 } else {
387 ATH_MSG_DEBUG("Get data object with key");
388 // Get DataObjects with key
389 dObj = m_store->accessData(clid, key);
390 }
391 if (dObj == 0) {
392 // No object - print warning and return
393 ATH_MSG_DEBUG("No object found for type " << type << " key " << key);
394 return(StatusCode::SUCCESS);
395 } else {
396 ATH_MSG_DEBUG("Found object for type " << type << " key " << key);
397 }
398 // Save the dObj
399 dataObjects.push_back(dObj);
400 }
401 // Stream out objects
402 if (dataObjects.size() == 0) {
403 ATH_MSG_DEBUG("No data objects found");
404 return(StatusCode::SUCCESS);
405 }
406 StatusCode status = streamObjects(dataObjects, m_outputName.value());
407 if (!status.isSuccess()) {
408 ATH_MSG_ERROR("Could not stream out objects");
409 return(status);
410 }
411 return(StatusCode::SUCCESS);
412}
413//__________________________________________________________________________
414StatusCode AthenaOutputStreamTool::streamObjects(const DataObjectVec& dataObjects, const std::string& outputName) {
415 // Check that a connection has been opened
416 if (!m_connectionOpen) {
417 ATH_MSG_ERROR("Connection NOT open. Please open a connection before streaming out objects.");
418 return(StatusCode::FAILURE);
419 }
420 // Connect the output file to the service
421 std::string outputConnectionString = outputName;
422 const std::string defaultMetaDataString = "[OutputCollection=MetaDataHdr][PoolContainerPrefix=MetaData]";
423 if (std::string::size_type mpos = outputConnectionString.find(defaultMetaDataString); mpos!=std::string::npos) {
424 // If we're in here we're writing MetaData
425 // Now let's see if we should be overwriting the MetaData attributes
426 // For the time-being this happens when we're writing MetaData in the augmentation mode
427 if (!m_metaDataOutputAttributes.empty()) {
428 // Note: This won't work quite right if only one attribute is set though!
429 outputConnectionString.replace(mpos, defaultMetaDataString.length(), m_metaDataOutputAttributes);
430 }
431 }
432 for (std::string::size_type pos = m_outputAttributes.find('['); pos != std::string::npos; pos = m_outputAttributes.find('[', ++pos)) {
433 if (outputConnectionString.find(m_outputAttributes.substr(pos, m_outputAttributes.find('=', pos) + 1 - pos)) == std::string::npos) {
434 outputConnectionString += m_outputAttributes.substr(pos, m_outputAttributes.find(']', pos) + 1 - pos);
435 }
436 }
437
438 // Check that the DataHeader is still valid
439 DataObject* dataHeaderObj = m_store->accessData(ClassID_traits<DataHeader>::ID(), m_dataHeaderKey);
440 std::map<DataObject*, IOpaqueAddress*> written;
441 for (DataObject* dobj : dataObjects) {
442 // Do not write the DataHeader via the explicit list
443 if (dobj->clID() == ClassID_traits<DataHeader>::ID()) {
444 ATH_MSG_DEBUG("Explicit request to write DataHeader: " << dobj->name() << " - skipping it.");
445 // Do not stream out same object twice
446 } else if (written.find(dobj) != written.end()) {
447 // Print warning and skip
448 ATH_MSG_DEBUG("Trying to write DataObject twice (clid/key): " << dobj->clID() << " " << dobj->name());
449 ATH_MSG_DEBUG(" Skipping this one.");
450 } else {
451 // Write object
452 IOpaqueAddress* addr = new TokenAddress(0, dobj->clID(), outputConnectionString);
453 addr->addRef();
454 if (m_conversionSvc->createRep(dobj, addr).isSuccess()) {
455 written.insert(std::pair<DataObject*, IOpaqueAddress*>(dobj, addr));
456 } else {
457 ATH_MSG_ERROR("Could not create Rep for DataObject (clid/key):" << dobj->clID() << " " << dobj->name());
458 return(StatusCode::FAILURE);
459 }
460 }
461 }
462 // End of loop over DataObjects, write DataHeader
463 if ((m_conversionSvc.type() == "AthenaPoolCnvSvc" || m_conversionSvc.type() == "AthenaPoolSharedIOCnvSvc") && dataHeaderObj != nullptr) {
464 IOpaqueAddress* addr = new TokenAddress(0, dataHeaderObj->clID(), outputConnectionString);
465 addr->addRef();
466 if (m_conversionSvc->createRep(dataHeaderObj, addr).isSuccess()) {
467 written.insert(std::pair<DataObject*, IOpaqueAddress*>(dataHeaderObj, addr));
468 } else {
469 ATH_MSG_ERROR("Could not create Rep for DataHeader");
470 return(StatusCode::FAILURE);
471 }
472 }
473 for (DataObject* dobj : dataObjects) {
474 // call fillRepRefs of persistency service
475 SG::DataProxy* proxy = dynamic_cast<SG::DataProxy*>(dobj->registry());
476 if (proxy != nullptr && written.find(dobj) != written.end()) {
477 IOpaqueAddress* addr(written.find(dobj)->second);
478 if ((m_conversionSvc->fillRepRefs(addr, dobj)).isSuccess()) {
479 if (dobj->clID() != 1 || addr->par()[0] != "\n") {
480 if (dobj->clID() != ClassID_traits<DataHeader>::ID()) {
481 m_dataHeader->insert(proxy, addr);
482 } else {
483 m_dataHeader->insert(proxy, addr, m_processTag);
484 }
485 if (proxy->address() == nullptr) {
486 proxy->setAddress(addr);
487 }
488 addr->release();
489 }
490 } else {
491 ATH_MSG_ERROR("Could not fill Object Refs for DataObject (clid/key):" << dobj->clID() << " " << dobj->name());
492 return(StatusCode::FAILURE);
493 }
494 } else {
495 ATH_MSG_WARNING("Could cast DataObject " << dobj->clID() << " " << dobj->name());
496 }
497 }
498 m_dataHeader->addHash(&*m_store);
499 if ((m_conversionSvc.type() == "AthenaPoolCnvSvc" || m_conversionSvc.type() == "AthenaPoolSharedIOCnvSvc") && dataHeaderObj != nullptr) {
500 // End of DataObjects, fill refs for DataHeader
501 SG::DataProxy* proxy = dynamic_cast<SG::DataProxy*>(dataHeaderObj->registry());
502 if (proxy != nullptr && written.find(dataHeaderObj) != written.end()) {
503 IOpaqueAddress* addr(written.find(dataHeaderObj)->second);
504 if ((m_conversionSvc->fillRepRefs(addr, dataHeaderObj)).isSuccess()) {
505 if (dataHeaderObj->clID() != 1 || addr->par()[0] != "\n") {
506 if (dataHeaderObj->clID() != ClassID_traits<DataHeader>::ID()) {
507 m_dataHeader->insert(proxy, addr);
508 } else {
509 m_dataHeader->insert(proxy, addr, m_processTag);
510 }
511 addr->release();
512 }
513 } else {
514 ATH_MSG_ERROR("Could not fill Object Refs for DataHeader");
515 return(StatusCode::FAILURE);
516 }
517 } else {
518 ATH_MSG_ERROR("Could not cast DataHeader");
519 return(StatusCode::FAILURE);
520 }
521 }
522 return(StatusCode::SUCCESS);
523}
524//__________________________________________________________________________
526 const std::string hltKey = "HLTAutoKey";
529 if (m_store->retrieve(beg, ending).isFailure() || beg == ending) {
530 ATH_MSG_DEBUG("No DataHeaders present in StoreGate");
531 } else {
532 for ( ; beg != ending; ++beg) {
533 if (m_store->transientContains<DataHeader>(beg.key()) && beg->isInput()) {
534 for (std::vector<DataHeaderElement>::const_iterator it = beg->begin(), itLast = beg->end();
535 it != itLast; ++it) {
536 // Only insert the primary clid, not the ones for the symlinks!
537 CLID clid = it->getPrimaryClassID();
538 if (clid != ClassID_traits<DataHeader>::ID()) {
539 //check the typename is known ... we make an exception if the key contains 'Aux.' ... aux containers may not have their keys known yet in some cases
540 //see https://its.cern.ch/jira/browse/ATLASG-59 for the solution
541 std::string typeName;
542 if (m_clidSvc->getTypeNameOfID(clid, typeName).isFailure() && it->getKey().find("Aux.") == std::string::npos) {
543 if (m_skippedItems.find(it->getKey()) == m_skippedItems.end()) {
544 ATH_MSG_WARNING("Skipping " << it->getKey() << " with unknown clid " << clid << " . Further warnings for this item are suppressed" );
545 m_skippedItems.insert(it->getKey());
546 }
547 continue;
548 }
549 ATH_MSG_DEBUG("Adding " << typeName << "#" << it->getKey() << " (clid " << clid << ") to itemlist");
550 const std::string keyName = it->getKey();
551 if (keyName.size() > 10 && keyName.compare(0, 10,hltKey)==0) {
552 p2BWrittenFromTool->add(clid, hltKey + "*").ignore();
553 } else if (keyName.size() > 10 && keyName.compare(keyName.size() - 10, 10, hltKey)==0) {
554 p2BWrittenFromTool->add(clid, "*" + hltKey).ignore();
555 } else {
556 p2BWrittenFromTool->add(clid, keyName).ignore();
557 }
558 }
559 }
560 }
561 }
562 }
563 ATH_MSG_DEBUG("Adding DataHeader for stream " << name());
564 return(StatusCode::SUCCESS);
565}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_INFO(x,...)
This is the implementation of IAthenaOutputStreamTool.
This file contains the class definition for the DataHeader and DataHeaderElement classes.
uint32_t CLID
The Class ID type.
An AttributeList represents a logical row of attributes in a metadata table.
This file contains the class definition for the TokenAddress class.
Base class for all conversion services.
Definition AthCnvSvc.h:66
virtual StatusCode disconnectOutput(const std::string &output)
Disconnect output files from the service.
An AttributeList represents a logical row of attributes in a metadata table.
StringProperty m_metaDataContainerPrefix
std::map< std::string, bool > m_keepProvenanceMatch
Cache provenance RegEx matching result in a map.
StatusCode finalizeOutput() override
Finalize the output stream after the last commit, e.g.
AthenaOutputStreamTool(const std::string &type, const std::string &name, const IInterface *parent)
Standard AlgTool Constructor.
std::set< std::string > m_skippedItems
set of skipped item keys, because of missing CLID
bool m_extendProvenanceRecord
Flag as to whether to extend provenance via the DataHeader.
DataHeader * m_dataHeader
Current DataHeader for streamed objects.
std::vector< DataObject * > DataObjectVec
Stream out a vector of objects Must convert to DataObject, e.g.
StatusCode connectOutput(const std::string &outputName="") override
Connect to the output stream Must connectOutput BEFORE streaming Only specify "outputName" if one wan...
ServiceHandle< IDecisionSvc > m_decSvc
Ref to DecisionSvc.
ServiceHandle< IClassIDSvc > m_clidSvc
Ref to ClassIDSvc to convert type name to clid.
std::vector< TypeKeyPair > TypeKeyPairs
virtual StatusCode streamObjects(const TypeKeyPairs &typeKeys, const std::string &outputName="") override
bool m_connectionOpen
Flag to tell whether connectOutput has been called.
ServiceHandle< IConversionSvc > m_conversionSvc
Keep reference to the data conversion service.
std::regex m_keepProvenancesRE
RegEx pattern created from m_keepProvenancesStr.
StatusCode connectServices()
Do the real connection to services.
void propagateProvenance(const DataHeader &src_dh)
copy provenance records when creating new DataHeaders
ServiceHandle< StoreGateSvc > m_store
virtual StatusCode initialize() override
AthAlgTool Interface method implementations:
virtual StatusCode getInputItemList(SG::IFolder *m_p2BWrittenFromTool) override
std::string m_keepProvenancesStr
RegEx string to match provenance tags to keep in the output DataHeader. Retrieved from an OutputStrea...
SG::ReadHandleKey< AthenaAttributeList > m_attrListKey
StatusCode commitOutput(bool doCommit=false) override
Commit the output stream after having streamed out objects Must commitOutput AFTER streaming.
StringProperty m_metaDataOutputCollection
This class provides a persistent form for the TransientAddress.
Definition DataHeader.h:37
This class provides the layout for summary information stored for data written to POOL.
Definition DataHeader.h:123
std::vector< DataHeaderElement >::const_iterator beginProvenance() const
std::vector< DataHeaderElement >::const_iterator endProvenance() const
bool isInput() const
Check whether StatusFlag is "Input".
a const_iterator facade to DataHandle.
Definition SGIterator.h:164
a run-time configurable list of data objects
Definition SGIFolder.h:21
virtual StatusCode add(const std::string &typeName, const std::string &skey)=0
add a data object identifier to the list
@ EVENT_STORE
Definition StoreID.h:26
This class provides a Generic Transient Address for POOL tokens.
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())