ATLAS Offline Software
RootNtupleOutputMetadataTool.cxx
Go to the documentation of this file.
1 
3 /*
4  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
5 */
6 
7 // RootNtupleOutputMetadataTool.cxx
8 // Implementation file for class Athena::RootNtupleOutputMetadataTool
9 // Author Jack Cranshaw <cranshaw@anl.gov>
11 
12 // AthenaRootComps includes
14 #include "RootBranchAddress.h"
15 
16 // Gaudi
17 #include "GaudiKernel/IClassIDSvc.h"
18 #include "GaudiKernel/IConversionSvc.h"
19 #include "GaudiKernel/IOpaqueAddress.h"
20 #include "GaudiKernel/IRegistry.h"
21 #include "GaudiKernel/DataObject.h"
22 
23 // Athena
24 #include "AthenaKernel/CLASS_DEF.h"
26 #include "StoreGate/StoreGateSvc.h"
27 #include "SGTools/BuiltinsClids.h"
28 
29 #include "TString.h"
31 
32 // ROOT includes
33 #include "TROOT.h"
34 #include "TFile.h"
35 #include "TTree.h"
36 
37 namespace Athena {
38 
40  const std::string& name,
41  const IInterface* parent) :
42  base_class(type, name, parent),
43  m_imetaStore("InputMetaDataStore", name),
44  m_ometaStore("MetaDataStore", name),
45  m_clidSvc("ClassIDSvc", name),
46  m_metaWritten(false)
47 {
48  // Properties
49  declareProperty("InputStore",
51  "Input metadata store");
52  declareProperty("OutputStore",
54  "Output metadata store");
55  declareProperty("StreamName",
56  m_tupleName = "StreamNTUP_RED",
57  "Name of the output stream tool associated with FIXME");
58  declareProperty("TupleName",
59  m_tupleName = "atlas_ntuple",
60  "Name of the output n-tuple FIXME");
61  declareProperty("OutputFile",
63  "Name of the output file FIXME");
64 }
65 
67 {}
68 
71 {
72  ATH_MSG_INFO("Initializing " << name());
73 
74  if (!::AthAlgTool::initialize().isSuccess()) {
75  ATH_MSG_FATAL("Cannot initialize AlgTool base class.");
76  return(StatusCode::FAILURE);
77  }
78  // Get the ClassID service
79  if (!m_clidSvc.retrieve().isSuccess()) {
80  ATH_MSG_FATAL("Cannot get ClassID service via IClassIDSvc interface.");
81  return(StatusCode::FAILURE);
82  } else {
83  ATH_MSG_DEBUG("Found ClassID service.");
84  }
85  // Get the storegate services
86  if (!m_imetaStore.retrieve().isSuccess()) {
87  ATH_MSG_FATAL("Failure retrieving input metadata store.");
88  return(StatusCode::FAILURE);
89  } else {
90  ATH_MSG_DEBUG("Found input store.");
91  }
92  if (!m_ometaStore.retrieve().isSuccess()) {
93  ATH_MSG_FATAL("Failure retrieving output metadata store.");
94  return(StatusCode::FAILURE);
95  } else {
96  ATH_MSG_DEBUG("Found output store.");
97  }
98  ServiceHandle<IIncidentSvc> incSvc("IncidentSvc", this->name());
99  if (!incSvc.retrieve().isSuccess()) {
100  ATH_MSG_ERROR("Cannot get the IncidentSvc");
101  return StatusCode::FAILURE;
102  } else {
103  ATH_MSG_INFO("Retrieved IncidentSvc");
104  }
105  incSvc->addListener(this, "BeginInputFile", 50);
106  incSvc->addListener(this, "EndInputFile", 50);
107  m_treesWritten.clear();
108 
109  return(StatusCode::SUCCESS);
110 }
111 
114 {
115  ATH_MSG_DEBUG("stop() for metadata write in Tool");
116  // Make sure metadata is written
117  if(writeMetadata().isFailure()) {
118  ATH_MSG_ERROR("Could not connect for metadata writing");
119  return StatusCode::RECOVERABLE;
120  }
121 
122  return StatusCode::SUCCESS;
123 }
124 
127 {
128  // Release the data store service
129  if (m_imetaStore != 0) {
130  if (!m_imetaStore.release().isSuccess()) {
131  ATH_MSG_WARNING("Could not release " << m_imetaStore.type() << " store.");
132  }
133  }
134  if (m_ometaStore != 0) {
135  if (!m_ometaStore.release().isSuccess()) {
136  ATH_MSG_WARNING("Could not release " << m_ometaStore.type() << " store.");
137  }
138  }
139  // Release the ClassID service
140  if (!m_clidSvc.release().isSuccess()) {
141  ATH_MSG_WARNING("Cannot release ClassID service.");
142  }
143  return(::AthAlgTool::finalize());
144 }
145 
151 
152 void
154 {
155  ATH_MSG_DEBUG("handle() incident type: " << inc.type());
156  if (inc.type()=="BeginInputFile") {
157  // Have to clean out any previous file metadata trees
160  StatusCode pc = m_ometaStore->retrieve(titer,tend);
161  if (pc.isSuccess()) {
162  for (; titer != tend; ++titer) {
163  if (m_ometaStore->removeDataAndProxy(&*titer).isFailure()) {
164  ATH_MSG_ERROR("Unable to remove TransferTree after writing");
165  }
166  }
167  }
168  m_treesWritten.clear();
169  }
170  else if (inc.type()=="EndInputFile") {
171  if(copyMetadata().isFailure()) ATH_MSG_ERROR("Could not copy input metadata");
172  if(writeMetadata().isFailure()) ATH_MSG_ERROR("Could not connect for metadata writing");
173  }
174 }
175 
178 {
179  ATH_MSG_INFO("RootNtupleOutputMetadataTool::writeMetadata outputName = ["
180  << m_outputName <<"]");
181  // open the file thru the i/o svc
182  ServiceHandle<IIoSvc> iosvc("IoSvc/AthIoSvc", name());
183  if (!iosvc.retrieve().isSuccess()) {
184  ATH_MSG_ERROR("could not retrieve the AthIoSvc");
185  return StatusCode::FAILURE;
186  }
187  IIoSvc::Fd fd = iosvc->open(m_outputName, IIoSvc::RECREATE);
188  if (fd < 0) {
189  ATH_MSG_ERROR("could not open-recreate file [" << m_outputName << "]");
190  return StatusCode::FAILURE;
191  }
192  if (!m_metaWritten) {
193  // Write the strings
196  StatusCode pc = m_ometaStore->retrieve(iter,end);
197  bool failure = false;
198  if (pc.isSuccess()) {
199  for (; iter != end; ++iter) {
200  std::string key = iter.key();
201  if (this->addMetadata(key,&(*iter),typeid(std::string)).isFailure()) failure=true;
202  }
203  }
204  if (failure) {
205  ATH_MSG_ERROR("Problem writing metadata");
206  return StatusCode::FAILURE;
207  }
208  m_metaWritten = true;
209  }
212  StatusCode pc = m_ometaStore->retrieve(titer,tend);
213  bool failure = false;
214  if (pc.isSuccess()) {
215  for (; titer != tend; ++titer) {
216  std::string key = titer.key();
217  if (m_treesWritten.find(key) == m_treesWritten.end()) {
218  const TTree* x = (TTree*)titer->tree();
219  try {
220  if (this->addMetadata(key,x,typeid(TTree)).isFailure()) failure=true;
221  }
222  catch (...) {
223  ATH_MSG_INFO("Error adding metadata for TTree " << key);
224  }
225  m_treesWritten.insert(key);
226  }
227  else {ATH_MSG_WARNING("Tree " << key << " already written");}
228  }
229  }
230  if (failure) {
231  ATH_MSG_ERROR("Problem writing metadata trees");
232  return StatusCode::FAILURE;
233  }
234 
235  return(StatusCode::SUCCESS);
236 }
237 
240 {
243  StatusCode pc = m_imetaStore->retrieve(iter,end);
244  bool failure = false;
245  if (pc.isSuccess()) {
246  for (; iter != end; ++iter) {
247  if (!m_ometaStore->contains<std::string>(iter.key())) {
248  std::string* toCopy = new std::string(*iter);
249  if (m_ometaStore->record(toCopy,iter.key()).isFailure()) failure=true;
250  }
251  }
252  }
253  if (failure) {
254  ATH_MSG_ERROR("Problem copying metadata");
255  return StatusCode::FAILURE;
256  }
259  pc = m_imetaStore->retrieve(titer,tend);
260  failure = false;
261  if (pc.isSuccess()) {
262  for (; titer != tend; ++titer) {
263  auto toCopy = std::make_unique<TransferTree>(*titer);
264  if (!m_ometaStore->contains<TransferTree>(titer.key())) {
265  if (m_ometaStore->record(std::move(toCopy),titer.key()).isFailure()) failure=true;
266  }
267  else ATH_MSG_INFO("Retrieve TTree with null pointer from input metadata store");
268  }
269  }
270  if (failure) {
271  ATH_MSG_ERROR("Problem copying metadata trees");
272  return StatusCode::FAILURE;
273  }
274 
275  return(StatusCode::SUCCESS);
276 }
277 
279 RootNtupleOutputMetadataTool::addMetadata(const std::string& /*key*/, const void* obj, const std::type_info& /*ti*/) {
280  // HACK for compilation, set m_file and m_tree = 0
281  //TFile* m_file = 0;
282  //TTree* m_tree = 0;
283  // Reject null pointers
284  if (obj==0) {
285  REPORT_MESSAGE (MSG::ERROR) << "Attempt to write null pointer metadata";
286  return StatusCode::FAILURE;
287  }
288  // Will crash past here anyway if m_file and m_tree are both null.
289  std::abort();
290 #if 0
291  // Determine directory to write into
292  std::string metaname;
293  TDirectory* dir = 0;
294  if (m_tree != 0) {
295  dir = m_tree->GetDirectory();
296  }
297  else {
298  REPORT_MESSAGE (MSG::WARNING) << "No TTree to navigate from";
299  dir = m_file->CurrentDirectory();
300  if (dir == 0) {
301  REPORT_MESSAGE (MSG::ERROR) << "No file directory to navigate from";
302  return StatusCode::FAILURE;
303  }
304  }
305  std::string thekey = key;
306  std::string::size_type sep = key.find('/');
307  if (sep != std::string::npos) {
308  metaname = key.substr (0, sep);
309 
310  if (m_tree != 0) {
311  // Go to the root directory of the file.
312  while (dynamic_cast<TDirectoryFile*> (dir) != 0 &&
313  dir->GetMotherDir())
314  dir = dir->GetMotherDir();
315  thekey = m_tree->GetName();
316  }
317  }
318  else {
319  if (m_tree != 0) {
320  metaname = m_tree->GetName();
321  }
322  else {
323  metaname = "eventless";
324  }
325  metaname += "Meta";
326  }
327 
328  TDirectory::TContext ctx (dir);
329  TDirectory* metadir = dir->GetDirectory (metaname.c_str());
330  if (!metadir) {
331  metadir = dir->mkdir (metaname.c_str());
332  if (!metadir) {
333  REPORT_MESSAGE (MSG::ERROR)
334  << "Can't create metadata dir " << metaname
335  << "in dir " << dir->GetName();
336  return StatusCode::RECOVERABLE;
337  }
338  }
339 
340  // Set info and casts for appropriate type
341  TClass* cls = gROOT->GetClass(ti);
342  if (!cls)
343  return StatusCode::RECOVERABLE;
344 
345  // If we're writing strings in a common directory, make sure name is unique.
346  if (ti == typeid(TString) || ti == typeid(std::string)) {
347  TObjString ostmp;
348  if (ti == typeid(TString)) {
349  ostmp.String() = *reinterpret_cast<const TString*> (obj);
350  obj = &ostmp;
351  cls = gROOT->GetClass ("TObjString");
352  }
353  else if (ti == typeid(std::string)) {
354  ostmp.String() = *reinterpret_cast<const std::string*> (obj);
355  obj = &ostmp;
356  cls = gROOT->GetClass ("TObjString");
357  }
358  if (key.size() > 0 && key[key.size()-1] == '/') {
359  int i = 1;
360  while (metadir->FindObject (thekey.c_str())) {
361  ++i;
362  std::ostringstream ss;
363  if (m_tree)
364  ss << m_tree->GetName();
365  else
366  ss << dir->GetName();
367  ss << "-" << i;
368  thekey = ss.str();
369  }
370  }
371 
372  // Treat like hadd and create new version each time
373  if (metadir->WriteObjectAny (obj, cls, thekey.c_str(), "new") == 0) {
374  REPORT_MESSAGE (MSG::ERROR)
375  << "Can't write metadata object " << thekey
376  << " for file " << metadir->GetFile()->GetName();
377  return StatusCode::RECOVERABLE;
378  }
379  }
380  else if (ti == typeid(TTree)) {
381  TTree* readTree = ((const TTree*)obj)->GetTree();
382  metadir->cd();
383 
384  // If we're writing in a common directory, make sure name is unique.
385  if (key.size() > 0) {
386  TTree* outTree = (TTree*)metadir->FindObject (thekey.c_str());
387  if (outTree == 0) {
388  outTree = readTree->CloneTree();
389  }
390  else {
391  TList tc;
392  tc.Add((TObject*)readTree);
393  Long64_t temp = outTree->Merge((TCollection*)&tc);
394  if (temp==0) {
395  REPORT_MESSAGE (MSG::ERROR) << "Unable to merge with existing tree in file";
396  return StatusCode::RECOVERABLE;
397  }
398  }
399  outTree->Write();
400  }
401  else {
402  REPORT_MESSAGE (MSG::ERROR) << "Did not use proper key for metadata tree ";
403  return StatusCode::RECOVERABLE;
404  }
405  }
406  else {
407  REPORT_MESSAGE (MSG::ERROR) << "addMetadata typeid not supported";
408  return StatusCode::FAILURE;
409  }
410  return(StatusCode::SUCCESS);
411 #endif
412 }
413 
414 }//> namespace Athena
readTree
void readTree(AccumulateMap &map, TTree *tree, size_t nLayers, size_t nCoords)
Reads a matrix tree, accumulating its entries into a map.
Definition: FPGATrackSimMatrixIO.cxx:92
python.tests.PyTestsLib.finalize
def finalize(self)
_info( "content of StoreGate..." ) self.sg.dump()
Definition: PyTestsLib.py:50
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
PowhegControl_ttHplus_NLO.ss
ss
Definition: PowhegControl_ttHplus_NLO.py:83
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
Athena::RootNtupleOutputMetadataTool::postExecute
virtual StatusCode postExecute() override
Definition: RootNtupleOutputMetadataTool.cxx:150
IIoSvc::RECREATE
@ RECREATE
Definition: IIoSvc.h:46
SG::detail::IteratorBase::key
const std::string & key() const
Get the key string with which the current object was stored.
Definition: SGIterator.cxx:155
initialize
void initialize()
Definition: run_EoverP.cxx:894
CaloClusterListBadChannel.cls
cls
Definition: CaloClusterListBadChannel.py:8
BuiltinsClids.h
x
#define x
Athena::RootNtupleOutputMetadataTool::m_tupleName
std::string m_tupleName
Name of the output tuple.
Definition: RootNtupleOutputMetadataTool.h:90
Athena::RootNtupleOutputMetadataTool::~RootNtupleOutputMetadataTool
virtual ~RootNtupleOutputMetadataTool()
Destructor.
Definition: RootNtupleOutputMetadataTool.cxx:66
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
RootNtupleOutputMetadataTool.h
m_file
std::unique_ptr< TFile > m_file
description: this is a custom writer for the old-school drivers that don't use an actual writer
Definition: OutputStreamData.cxx:52
python.TriggerHandler.tend
string tend
Definition: TriggerHandler.py:300
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:85
Athena
Some weak symbol referencing magic...
Definition: AthLegacySequence.h:21
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
TransferTree
Definition: TransferTree.h:11
Athena::RootNtupleOutputMetadataTool::addMetadata
StatusCode addMetadata(const std::string &key, const void *obj, const std::type_info &ti)
Definition: RootNtupleOutputMetadataTool.cxx:279
Athena::RootNtupleOutputMetadataTool::RootNtupleOutputMetadataTool
RootNtupleOutputMetadataTool()
Default constructor:
Athena::RootNtupleOutputMetadataTool::m_imetaStore
ServiceHandle< StoreGateSvc > m_imetaStore
ServiceHandle to the data store service.
Definition: RootNtupleOutputMetadataTool.h:77
TransferTree.h
test_pyathena.parent
parent
Definition: test_pyathena.py:15
Athena::RootNtupleOutputMetadataTool::preStream
virtual StatusCode preStream() override
Definition: RootNtupleOutputMetadataTool.cxx:149
Athena::RootNtupleOutputMetadataTool::stop
virtual StatusCode stop() override
Definition: RootNtupleOutputMetadataTool.cxx:113
Athena::RootNtupleOutputMetadataTool::copyMetadata
StatusCode copyMetadata()
Connect to the output stream Must writeMetadata BEFORE streaming Only specify "outputName" if one wan...
Definition: RootNtupleOutputMetadataTool.cxx:239
beamspotman.dir
string dir
Definition: beamspotman.py:623
Athena::RootNtupleOutputMetadataTool::preExecute
virtual StatusCode preExecute() override
Definition: RootNtupleOutputMetadataTool.cxx:148
ReadFromCoolCompare.fd
fd
Definition: ReadFromCoolCompare.py:196
grepfile.sep
sep
Definition: grepfile.py:38
Athena::RootNtupleOutputMetadataTool::m_metaWritten
bool m_metaWritten
Definition: RootNtupleOutputMetadataTool.h:92
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
Athena::RootNtupleOutputMetadataTool::m_ometaStore
ServiceHandle< StoreGateSvc > m_ometaStore
Definition: RootNtupleOutputMetadataTool.h:78
Athena::RootNtupleOutputMetadataTool::m_treesWritten
std::set< std::string > m_treesWritten
Definition: RootNtupleOutputMetadataTool.h:84
REPORT_MESSAGE
#define REPORT_MESSAGE(LVL)
Report a message.
Definition: Control/AthenaKernel/AthenaKernel/errorcheck.h:365
Athena::RootNtupleOutputMetadataTool::m_outputName
std::string m_outputName
Name of the output name.
Definition: RootNtupleOutputMetadataTool.h:87
RootBranchAddress.h
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Athena::RootNtupleOutputMetadataTool::preFinalize
virtual StatusCode preFinalize() override
Definition: RootNtupleOutputMetadataTool.cxx:147
Athena::RootNtupleOutputMetadataTool::writeMetadata
StatusCode writeMetadata()
Definition: RootNtupleOutputMetadataTool.cxx:177
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
IIoSvc::Fd
int Fd
unix-y file descriptor
Definition: IIoSvc.h:38
Athena::RootNtupleOutputMetadataTool::m_clidSvc
ServiceHandle< IClassIDSvc > m_clidSvc
ServiceHandle to clid service.
Definition: RootNtupleOutputMetadataTool.h:80
Athena::RootNtupleOutputMetadataTool::finalize
virtual StatusCode finalize() override
Definition: RootNtupleOutputMetadataTool.cxx:126
Athena::RootNtupleOutputMetadataTool::postInitialize
virtual StatusCode postInitialize() override
AthenaOutputTool Interface method implementations:
Definition: RootNtupleOutputMetadataTool.cxx:146
python.PyAthena.obj
obj
Definition: PyAthena.py:132
Athena::RootNtupleOutputMetadataTool::initialize
virtual StatusCode initialize() override
Gaudi AlgTool Interface method implementations:
Definition: RootNtupleOutputMetadataTool.cxx:70
StoreGateSvc.h
SG::ConstIterator
Definition: SGIterator.h:163
CLASS_DEF.h
macros to associate a CLID to a type
IIoSvc.h
Athena::RootNtupleOutputMetadataTool::handle
virtual void handle(const Incident &incident) override
Incident service handle listening for Begin/End InputFile incidents.
Definition: RootNtupleOutputMetadataTool.cxx:153
python.SystemOfUnits.pc
float pc
Definition: SystemOfUnits.py:99
ServiceHandle< IIncidentSvc >
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37