ATLAS Offline Software
Loading...
Searching...
No Matches
OutputStreamData.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7
8
9//
10// includes
11//
12
14
18#include <TH1.h>
19#include <TTree.h>
20#include <tuple>//for std::ignore
21
22//
23// method implementations
24//
25
26namespace EL
27{
28 namespace Detail
29 {
30 namespace
31 {
33 class DirectoryReset {
34 public:
36 DirectoryReset() : m_dir( *gDirectory ) {}
38 ~DirectoryReset() { m_dir.cd(); }
39 private:
41 TDirectory& m_dir;
42 };
43
44
45
46 struct MyWriter : public SH::DiskWriter
47 {
50
51 public:
52 std::unique_ptr<TFile> m_file;
53
54 explicit MyWriter (std::unique_ptr<TFile> val_file)
55 : m_file (std::move (val_file))
56 {
57 if (m_file == nullptr)
58 throw std::runtime_error ("encountered null pointer for output file");
59 m_path = m_file->GetName();
60 }
61
62 ~MyWriter ()
63 {
64 if (m_file != nullptr)
65 close();
66 }
67 //cppcheck-suppress returnByReference
68 std::string getPath () const
69 {
70 return m_path;
71 }
72
73 TFile *getFile ()
74 {
75 RCU_REQUIRE2_SOFT (m_file != nullptr, "file already closed");
76 return m_file.get();
77 }
78
79 void doClose ()
80 {
81 RCU_REQUIRE2_SOFT (m_file != nullptr, "file already closed");
82 m_file->Write ();
83 m_file->Close ();
84 m_file = nullptr;
85 }
87 private:
88 std::string m_path;
89 };
90
91
92
94 std::unique_ptr<TFile> checkedOpenFile (const std::string& path, const std::string& mode)
95 {
96 std::unique_ptr<TFile> result (TFile::Open (path.c_str(), mode.c_str()));
97 if (result == nullptr)
98 throw std::runtime_error ("failed to open file " + path + " with mode " + mode);
99 return result;
100 }
101 }
102
103
104
105 void OutputStreamData ::
106 testInvariant () const
107 {
108 RCU_INVARIANT (m_writer != nullptr);
109 }
110
111
112
113 OutputStreamData ::
114 OutputStreamData (const std::string& val_fileName, const std::string& mode)
115 : OutputStreamData (checkedOpenFile (val_fileName, mode))
116 {
117 // no invariant used
118 }
119
120
121
122 OutputStreamData ::
123 OutputStreamData (std::unique_ptr<TFile> file)
124 : OutputStreamData (std::make_unique<MyWriter> (std::move (file)))
125 {
126 // no invariant used
127 }
128
129
130
131 OutputStreamData ::
132 OutputStreamData (std::unique_ptr<SH::DiskWriter> val_writer)
133 : m_writer (std::move (val_writer))
134 {
135 RCU_NEW_INVARIANT (this);
136 }
137
138
139
140 const std::string& OutputStreamData ::
141 mainStreamName () const noexcept
142 {
143 RCU_READ_INVARIANT (this);
144 return m_mainStreamName;
145 }
146
147
148
149 void OutputStreamData ::
150 setMainStreamName (const std::string& val_mainStreamName)
151 {
153 if (!m_mainStreamName.empty())
154 throw std::runtime_error ("main stream name already set");
155 m_mainStreamName = val_mainStreamName;
156 }
157
158
159
160 TFile *OutputStreamData ::
161 file () const noexcept
162 {
163 RCU_READ_INVARIANT (this);
164 TFile *result = m_writer->file();
165 RCU_PROVIDE (result != nullptr);
166 return result;
167 }
168
169
170
171 void OutputStreamData ::
172 close ()
173 {
175 saveOutput ();
176 m_writer->close ();
177 }
178
179
180
181 std::string OutputStreamData ::
182 finalFileName () const
183 {
184 RCU_READ_INVARIANT (this);
185 return m_writer->path ();
186 }
187
188
189
190 void OutputStreamData ::
191 saveOutput ()
192 {
194 TFile *const file {m_writer->file()};
195 RCU_ASSERT (file != nullptr);
196 for (std::unique_ptr<TObject>& object : m_output)
197 {
198 std::string name = object->GetName();
199 TDirectory *dir = makeDirectoryFor (name);
200 if (dir != file)
201 {
202 TNamed *named = dynamic_cast<TNamed*>(object.get());
203 if (named)
204 named->SetName (name.c_str());
205 }
206
207 if (RCU::SetDirectory (object.get(), dir))
208 {
209 // SetDirectory transferred ownership to the directory, so release
210 // it here to avoid a double delete.
211 //placate cppcheck using std::ignore
212 std::ignore = object.release();
213 } else
214 {
215 // WriteObject writes a copy and takes no ownership, so we keep
216 // owning the object and let the unique_ptr delete it below.
217 dir->WriteObject (object.get(), name.c_str());
218 }
219 }
220 m_outputHistMap.clear ();
221 m_outputTreeMap.clear ();
222 m_output.clear ();
223 }
224
225
226
227 void OutputStreamData ::
228 addOutput (std::unique_ptr<TObject> outputObject)
229 {
231
232 TTree *const tree = dynamic_cast<TTree*> (outputObject.get());
233 if (tree)
234 {
235 std::string name = tree->GetName();
236 std::string treeName = tree->GetName();
237
238 TDirectory *dir = makeDirectoryFor (treeName);
239
240 // if we are in a sub-directory we need to rename the tree
241 if (name != treeName)
242 tree->SetName (treeName.c_str());
243
244 // pass ownership of the tree to the directory
245 tree->SetDirectory (dir);
246 outputObject.release();
247
248 m_outputTreeMap[name] = tree;
249
250
251 } else
252 {
253 TH1 *const hist = dynamic_cast<TH1*> (outputObject.get());
254
255 m_outputHistMap[outputObject->GetName()] = outputObject.get();
256 m_output.emplace_back (std::move (outputObject));
257 if (hist)
258 hist->SetDirectory (nullptr);
259 }
260 }
261
262
263
264 void OutputStreamData ::
265 addClone (const TObject& prototypeObject)
266 {
267 // no invariant used
268
269 // Do not change the user's "current directory" during any of the
270 // following...
271 DirectoryReset dirReset;
272
273 // Make a clone of the object, and make sure we are already in
274 // the right directory if needed
275 std::string name = prototypeObject.GetName();
276 TDirectory *dir = makeDirectoryFor (name);
277 dir->cd();
278
279 std::unique_ptr<TObject> clone {prototypeObject.Clone()};
280
281 // Hold on to the pointer of the tree in our internal cache.
282 addOutput (std::move (clone));
283 }
284
285
286
287 TDirectory *OutputStreamData ::
288 makeDirectoryFor (std::string& name)
289 {
291
292 TDirectory *result = file();
293 std::string::size_type split = name.rfind ("/");
294 if (split == std::string::npos)
295 {
296 return result;
297 } else
298 {
299 const std::string dirname = name.substr (0, split);
300 name = name.substr (split + 1);
301 TDirectory *subdir = dynamic_cast<TDirectory*>(result->Get (dirname.c_str()));
302 if (!subdir)
303 {
304 result->mkdir (dirname.c_str());
305 subdir = dynamic_cast<TDirectory*>(result->Get (dirname.c_str()));
306 RCU_ASSERT (subdir != nullptr);
307 }
308 result = subdir;
309 RCU_ASSERT (result != nullptr);
310 return result;
311 }
312 }
313
314
315
316 TObject *OutputStreamData ::
317 getOutputHist (const std::string& name) const noexcept
318 {
319 RCU_READ_INVARIANT (this);
320
321 auto iter = m_outputHistMap.find (name);
322 return iter != m_outputHistMap.end() ? iter->second : nullptr;
323 }
324
325
326
327 TTree *OutputStreamData ::
328 getOutputTree (const std::string& name) const noexcept
329 {
330 RCU_READ_INVARIANT (this);
331
332 auto iter = m_outputTreeMap.find (name);
333 return iter != m_outputTreeMap.end() ? iter->second : nullptr;
334 }
335 }
336}
#define RCU_INVARIANT(x)
Definition Assert.h:187
#define RCU_ASSERT(x)
Definition Assert.h:210
#define RCU_CHANGE_INVARIANT(x)
Definition Assert.h:219
#define RCU_REQUIRE2_SOFT(x, y)
Definition Assert.h:143
#define RCU_NEW_INVARIANT(x)
Definition Assert.h:221
#define RCU_PROVIDE(x)
Definition Assert.h:203
#define RCU_READ_INVARIANT(x)
Definition Assert.h:217
std::unordered_map< std::string, TObject * > m_outputHistMap
the output histogram map
TFile * file() const noexcept
the file we are writing to
TDirectory * makeDirectoryFor(std::string &name)
make the directory for the object of the given name
OutputStreamData(const std::string &val_fileName, const std::string &mode)
open the given file and create an output stream for it
void saveOutput()
write the list of output objects to disk and clear it
void addOutput(std::unique_ptr< TObject > outputObject)
add the given output object to this stream
std::vector< std::unique_ptr< TObject > > m_output
the list of objects to write out at the end of job
std::string m_mainStreamName
the name of the main stream
std::unique_ptr< SH::DiskWriter > m_writer
the writer we use
std::unordered_map< std::string, TTree * > m_outputTreeMap
the output tree map
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:132
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:179
This module defines the arguments passed from the BATCH driver to the BATCH worker.
bool SetDirectory(TObject *object, TDirectory *directory)
effects: set the directory this object is associated with returns: whether the object type actively k...
Definition RootUtils.cxx:25
path
python interpreter configuration --------------------------------------—
Definition athena.py:130
STL namespace.
TChain * tree
TFile * file
std::string dirname(std::string name)
Definition utils.cxx:200