ATLAS Offline Software
Loading...
Searching...
No Matches
RootOutputStreamTool.cxx
Go to the documentation of this file.
1
2
3/*
4 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
5*/
6
7// RootOutputStreamTool.cxx
8// Implementation file for class Athena::RootOutputStreamTool
9// Author Peter van Gemmeren <gemmeren@anl.gov>
11
12// AthenaRootComps includes
14#include "RootSvc.h"
15#include "RootConnection.h"
16#include "RootBranchAddress.h"
17
18// Gaudi
19#include "GaudiKernel/IConversionSvc.h"
20#include "GaudiKernel/IOpaqueAddress.h"
21#include "GaudiKernel/IRegistry.h"
22#include "GaudiKernel/DataObject.h"
23
24// Athena
25#include "GaudiKernel/IClassIDSvc.h"
27
28// stl
29#include <set>
30
31namespace Athena {
32
33RootOutputStreamTool::RootOutputStreamTool(const std::string& type, const std::string& name, const IInterface* parent) :
34 base_class(type, name, parent),
35 m_storeSvc("StoreGateSvc", name),
36 m_conversionSvc("Athena::RootCnvSvc/AthenaRootCnvSvc", name),
37 m_clidSvc("ClassIDSvc", name) {
38 // Properties
39 declareProperty("Store", m_storeSvc, "Store from which to stream out event data");
40 declareProperty("TreeName", m_treeName = "CollectionTree", "Name of the output event tree");
41 declareProperty("OutputFile", m_outputName, "Name of the output file");
42}
43
46
48 ATH_MSG_INFO("Initializing " << name());
49
50 // Get the ClassID service
51 ATH_CHECK(m_clidSvc.retrieve());
52 // Get the conversion service
53 ATH_CHECK(m_conversionSvc.retrieve());
54 return StatusCode::SUCCESS;
55}
56
58 // Release the data store service
59 if (m_storeSvc != 0) {
60 if (!m_storeSvc.release().isSuccess()) {
61 ATH_MSG_WARNING("Could not release " << m_storeSvc.type() << " store.");
62 }
63 }
64 // Release the conversion service
65 if (!m_conversionSvc.release().isSuccess()) {
66 ATH_MSG_WARNING("Cannot release conversion service.");
67 }
68 // Release the ClassID service
69 if (!m_clidSvc.release().isSuccess()) {
70 ATH_MSG_WARNING("Cannot release ClassID service.");
71 }
72 return StatusCode::SUCCESS;
73}
74
75StatusCode RootOutputStreamTool::connectServices(const std::string& dataStore, const std::string& cnvSvc, bool extendProvenenceRecord) {
76 ATH_MSG_VERBOSE("connectServices dataStore = " << dataStore << ", cnvSvc = " << cnvSvc << ", extendProv = " << extendProvenenceRecord);
77 // Release the old data store service
78 if (m_storeSvc != 0) {
79 if (!m_storeSvc.release().isSuccess()) {
80 ATH_MSG_WARNING("Could not release " << m_storeSvc.type() << " store.");
81 }
82 }
83 m_storeSvc = ServiceHandle<StoreGateSvc>(dataStore, this->name());
84 // Get the data store service
85 ATH_CHECK(m_storeSvc.retrieve());
86 return StatusCode::SUCCESS;
87}
88
89StatusCode RootOutputStreamTool::connectOutput(const std::string& outputName) {
90 ATH_MSG_VERBOSE("connectOutput outputName = [" << outputName <<"]");
91 // Set output file name property
92 if (!outputName.empty()) {
93 m_outputName = outputName;
94 } else {
95 return StatusCode::FAILURE;
96 }
97 // Connect the output file to the service
98 if (!m_conversionSvc->connectOutput(m_outputName + "(" + m_treeName + ")", "recreate").isSuccess()) {
99 ATH_MSG_ERROR("Unable to connect output " << m_outputName);
100 return StatusCode::FAILURE;
101 } else {
102 ATH_MSG_DEBUG("Connected to " << m_outputName);
103 }
104 return StatusCode::SUCCESS;
105}
106
107StatusCode RootOutputStreamTool::commitOutput(bool/* doCommit*/) {
108 ATH_MSG_VERBOSE("commitOutput");
109 if (m_outputName.empty()) {
110 ATH_MSG_ERROR("Unable to commit, no output connected.");
111 return StatusCode::FAILURE;
112 }
113 // Connect the output file to the service
114 if (!m_conversionSvc->commitOutput(m_outputName, false).isSuccess()) {
115 ATH_MSG_ERROR("Unable to commit output " << m_outputName);
116 return StatusCode::FAILURE;
117 } else {
118 ATH_MSG_DEBUG("Committed: " << m_outputName);
119 }
120 m_outputName.clear();
121 return StatusCode::SUCCESS;
122}
123
125 ATH_MSG_VERBOSE("finalizeOutput");
126 return StatusCode::SUCCESS;
127}
128
129StatusCode RootOutputStreamTool::streamObjects(const IAthenaOutputStreamTool::TypeKeyPairs& typeKeys, const std::string& outputName) {
130 ATH_MSG_VERBOSE("streamObjects(type/keys)...");
131 // Now iterate over the type/key pairs and stream out each object
132 std::vector<DataObject*> dataObjects;
133 dataObjects.reserve(typeKeys.size());
134 for (IAthenaOutputStreamTool::TypeKeyPairs::const_iterator first = typeKeys.begin(), last = typeKeys.end();
135 first != last; ++first) {
136 const std::string& type = (*first).first;
137 const std::string& key = (*first).second;
138 // Find the clid for type name from the classIDSvc
139 CLID clid = 0;
140 if (!m_clidSvc->getIDOfTypeName(type, clid).isSuccess()) {
141 ATH_MSG_ERROR("Could not get clid for typeName " << type);
142 return StatusCode::FAILURE;
143 }
144 DataObject* dObj = 0;
145 // Two options: no key or explicit key
146 if (key.empty()) {
147 ATH_MSG_DEBUG("Get data object with no key");
148 // Get DataObject without key
149 dObj = m_storeSvc->accessData(clid);
150 } else {
151 ATH_MSG_DEBUG("Get data object with key");
152 // Get DataObjects with key
153 dObj = m_storeSvc->accessData(clid, key);
154 }
155 if (dObj == 0) {
156 // No object - print warning and continue with next object
157 ATH_MSG_WARNING("No object found for type " << type << " key " << key);
158 continue;
159 } else {
160 ATH_MSG_DEBUG("Found object for type " << type << " key " << key);
161 }
162 // Save the dObj
163 dataObjects.push_back(dObj);
164 }
165 return this->streamObjects(dataObjects, outputName);
166}
167
168StatusCode RootOutputStreamTool::streamObjects(const DataObjectVec& dataObjects, const std::string&
169 /*outputName*/) {
170 ATH_MSG_VERBOSE("streamObjects(dobjs)");
171 if (m_outputName.empty()) {
172 ATH_MSG_ERROR("Unable to commit, no output connected.");
173 return StatusCode::FAILURE;
174 }
175 ATH_MSG_VERBOSE("streaming out... [" << m_conversionSvc.typeAndName() << "]");
176 std::set<DataObject*> written;
177 for (std::vector<DataObject*>::const_iterator doIter = dataObjects.begin(), doLast = dataObjects.end();
178 doIter != doLast; ++doIter) {
179 ATH_MSG_VERBOSE(" --> [" << (*doIter)->clID() << "/" << (*doIter)->name() << "]...");
180 // Do not stream out same object twice
181 if (written.find(*doIter) != written.end()) {
182 // Print warning and skip
183 ATH_MSG_DEBUG("Trying to write DataObject twice (clid/key): " << (*doIter)->clID() << ", " << (*doIter)->name());
184 ATH_MSG_DEBUG(" Skipping this one.");
185 } else {
186 written.insert(*doIter);
187 // Write object
188 IOpaqueAddress* addr = 0;
189 if ((m_conversionSvc->createRep(*doIter, addr)).isSuccess()) {
190 IRegistry* ireg = (*doIter)->registry();
191 // FIXME: that's a wild hack to handle RootBranchAddress's stickyness.
192 // if the transient address already has a RootBranchAddress (ie: it was
193 // read from a d3pd-file) calling setAddress will invalidate the
194 // previous RBA which will screw things up the next time around.
195 // The real fix would probably involve changing a bit the logic either
196 // in convsvc::createRep above, or -rather- have the side effect of
197 // properly setting up the RootConnection (in createRep) be explicitly
198 // written somewhere. (here?)
199 if (dynamic_cast<RootBranchAddress*>(ireg->address())) {
200 delete addr; addr = 0;
201 } else {
202 ireg->setAddress(addr);
203 }
204 // SG::DataProxy* proxy = dynamic_cast<SG::DataProxy*>((*doIter)->registry());
205 // if (!proxy) {
206 // ATH_MSG_WARNING("Could cast DataObject "
207 // << (*doIter)->clID() << " " << (*doIter)->name());
208 // }
209 } else {
210 ATH_MSG_ERROR("Could not create Rep for DataObject (clid/key): " << (*doIter)->clID() << ", " << (*doIter)->name());
211 return StatusCode::FAILURE;
212 }
213 }
214 }
215 return StatusCode::SUCCESS;
216}
217
218StatusCode RootOutputStreamTool::getInputItemList(SG::IFolder* /*m_p2BWrittenFromTool*/) {
219 ATH_MSG_VERBOSE("getInputItemList");
220 return StatusCode::SUCCESS;
221}
222
223}//> namespace Athena
#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)
uint32_t CLID
The Class ID type.
This file contains the class definition for the Athena::RootConnection class.
This file contains the class definition for the RootSvc class.
virtual StatusCode getInputItemList(SG::IFolder *m_p2BWrittenFromTool) override
ServiceHandle< ::IClassIDSvc > m_clidSvc
ServiceHandle to clid service.
virtual StatusCode commitOutput(bool doCommit=false) override
Commit the output stream after having streamed out objects Must commitOutput AFTER streaming.
virtual StatusCode finalizeOutput() override
Finalize the output stream after the last commit, e.g.
ServiceHandle< ::StoreGateSvc > m_storeSvc
ServiceHandle to the data store service.
virtual StatusCode connectOutput(const std::string &outputName) override
Connect to the output stream Must connectOutput BEFORE streaming Only specify "outputName" if one wan...
virtual StatusCode finalize() override
virtual StatusCode initialize() override
Gaudi AlgTool Interface method implementations:
virtual StatusCode streamObjects(const IAthenaOutputStreamTool::TypeKeyPairs &typeKeys, const std::string &outputName="") override
Stream out objects.
std::string m_outputName
Name of the output file.
ServiceHandle< ::IConversionSvc > m_conversionSvc
ServiceHandle to the data conversion service.
RootOutputStreamTool(const std::string &type, const std::string &name, const IInterface *parent)
Standard AlgTool Constructor.
virtual ~RootOutputStreamTool()
Destructor.
std::string m_treeName
Name of the output tuple.
virtual StatusCode connectServices(const std::string &dataStore, const std::string &cnvSvc, bool extendProvenenceRecord) override
Specify which data store and conversion service to use and whether to extend provenence Only use if o...
std::vector< TypeKeyPair > TypeKeyPairs
a run-time configurable list of data objects
Definition SGIFolder.h:21
Some weak symbol referencing magic... These are declared in AthenaKernel/getMessageSvc....