The Gaudi Framework  master (b9786168)
Loading...
Searching...
No Matches
RConverter.cpp
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2024 CERN for the benefit of the LHCb and ATLAS collaborations *
3* *
4* This software is distributed under the terms of the Apache version 2 licence, *
5* copied verbatim in the file "LICENSE". *
6* *
7* In applying this licence, CERN does not waive the privileges and immunities *
8* granted to it by virtue of its status as an Intergovernmental Organization *
9* or submit itself to any jurisdiction. *
10\***********************************************************************************/
11#define ROOTHISTCNV_RCONVERTER_CPP
12
13// Include files
14#include "RConverter.h"
15#include "RootObjAddress.h"
21#include <GaudiKernel/SmartIF.h>
22
23#include <TDirectory.h>
24#include <TFile.h>
25#include <TTree.h>
26#include <list>
27#include <string>
28
29namespace {
30 std::map<std::string, TFile*> s_fileMap;
31}
32
33//-----------------------------------------------------------------------------
35//-----------------------------------------------------------------------------
36{
37 MsgStream log( msgSvc(), "RConverter::createDir" );
38
39 // Get rid of leading /NTUPLES
40 std::string full = diskDirectory( loc );
41
42 std::string fil, cur, s;
43 TDirectory* gDir = gDirectory;
44
45 TFile* tf = nullptr;
46 if ( findTFile( loc, tf ).isSuccess() ) { tf->cd(); }
47
48 std::vector<std::string> lpath;
49 int i = 1;
50
51 auto p = full.find( ":", 0 );
52 if ( p != std::string::npos ) {
53 fil = full.substr( 0, p );
54 i = p + 1;
55 fil += ":/";
56 gDirectory->cd( fil.c_str() );
57 }
58
59 while ( ( p = full.find( "/", i ) ) != std::string::npos ) {
60 s = full.substr( i, p - i );
61 lpath.push_back( s );
62 i = p + 1;
63 }
64 lpath.push_back( full.substr( i ) );
65
66 if ( full.compare( 0, 1, "/" ) == 0 ) gDirectory->cd( "/" );
67
68 for ( const auto& litr : lpath ) {
69 cur = litr;
70 if ( !gDirectory->GetKey( litr.c_str() ) ) { gDirectory->mkdir( litr.c_str() ); }
71 gDirectory->cd( litr.c_str() );
72 }
73
74 gDirectory = gDir;
75
77}
78//-----------------------------------------------------------------------------
79std::string RootHistCnv::RConverter::diskDirectory( const std::string& loc )
80//-----------------------------------------------------------------------------
81{
82 // Get rid of leading /NTUPLES/{INPUT_STREAM} or /stat/{INPUT_STREAM}
83 std::string dir;
84 long lf1 = loc.find( "/NTUPLES/" );
85 long lf2 = loc.find( "/stat/" );
86 long ll;
87 if ( lf1 != -1 ) {
88 ll = loc.find( "/", lf1 + 9 );
89
90 } else if ( lf2 != -1 ) {
91 ll = loc.find( "/", lf2 + 6 );
92
93 } else {
94 MsgStream log( msgSvc(), "RConverter" );
95 log << MSG::ERROR << "diskDirectory(" << loc << ")"
96 << " --> no leading /NTUPLES/ or /stat/" << endmsg;
97 return loc;
98 }
99 // dir = loc.substr(ll+8);
100
101 if ( ll == -1 ) {
102 dir = "/";
103 } else {
104 dir = loc.substr( ll );
105 }
106
107 return dir;
108}
109
110//-----------------------------------------------------------------------------
111std::string RootHistCnv::RConverter::directory( const std::string& loc )
112//-----------------------------------------------------------------------------
113{
114 return diskDirectory( loc );
115}
116
117//-----------------------------------------------------------------------------
118void RootHistCnv::RConverter::setDirectory( const std::string& loc )
119//-----------------------------------------------------------------------------
120{
121 MsgStream log( msgSvc(), "RConverter" );
122 TFile* tf = nullptr;
123
124 std::string full = diskDirectory( loc );
125
126 // get associated TFile
127 if ( findTFile( loc, tf ).isSuccess() ) {
128 tf->cd();
129 } else {
130 log << MSG::ERROR << "error getting TFile name " << loc << endmsg;
131 }
132
133 int p, i = 1;
134 std::string cur, sdir;
135
136 gDirectory->cd( "/" );
137 while ( ( p = full.find( "/", i ) ) != -1 ) {
138 sdir = full.substr( i, p - i );
139 if ( !gDirectory->GetKey( sdir.c_str() ) ) {
140 log << MSG::ERROR << "cannot cd to " << full << " from " << gDirectory->GetPath() << endmsg;
141 return;
142 }
143 gDirectory->cd( sdir.c_str() );
144
145 i = p + 1;
146 }
147 gDirectory->cd( full.substr( i ).c_str() );
148}
149
150//-----------------------------------------------------------------------------
151void RootHistCnv::RConverter::setDiskDirectory( const std::string& loc )
152//-----------------------------------------------------------------------------
153{
154 setDirectory( loc );
155}
156
157//-----------------------------------------------------------------------------
159//-----------------------------------------------------------------------------
160{
161 return gDirectory->GetPath();
162}
163
164//-----------------------------------------------------------------------------
165StatusCode RootHistCnv::RConverter::createAddress( DataObject* pObj, TDirectory* pDir, TObject* pTObj,
166 IOpaqueAddress*& refpAddr )
167//-----------------------------------------------------------------------------
168{
169 // Get address again....it does not change
170 IRegistry* pReg = pObj->registry();
171 if ( pReg ) {
172 refpAddr = pReg->address();
173 if ( !refpAddr ) {
174 refpAddr = new RootObjAddress( repSvcType(), objType(), pReg->name(), "", (unsigned long)( pDir ),
175 (unsigned long)( pTObj ), pTObj );
176
177 return StatusCode::SUCCESS;
178 }
179 }
180 return StatusCode::FAILURE;
181}
182
183//--------------------------------------------------------------------------
184StatusCode RootHistCnv::RConverter::createAddress( const std::string& rzdir, const CLID& clid, const std::string& title,
185 TObject* pTObj, IOpaqueAddress*& refpAddress )
186//--------------------------------------------------------------------------
187{
188 auto pA = new RootObjAddress( repSvcType(), clid, rzdir, title, 0, 0, pTObj );
189
190 refpAddress = pA;
191 return StatusCode::SUCCESS;
192}
193
194//--------------------------------------------------------------------------
195StatusCode RootHistCnv::RConverter::createAddress( const std::string& rzdir, const CLID& clid, long id, TObject* pTobj,
196 IOpaqueAddress*& refpAddress )
197//--------------------------------------------------------------------------
198{
199 auto obj = std::to_string( id );
200 StatusCode status = createAddress( rzdir, clid, obj, pTobj, refpAddress );
201 if ( status.isSuccess() ) {
202 unsigned long* ipar = (unsigned long*)refpAddress->ipar();
203 ipar[0] = id;
204 }
205 return status;
206}
207
208//-----------------------------------------------------------------------------
211//-----------------------------------------------------------------------------
212{
213 if ( pObject ) {
214 IRegistry* pReg = pObject->registry();
215 if ( pReg ) {
216 auto dataMgr = dataProvider().as<IDataManagerSvc>();
217 if ( dataMgr ) {
218 IRegistry* pParentReg = nullptr;
219 StatusCode status = dataMgr->objectParent( pReg, pParentReg );
220 if ( status.isSuccess() ) {
221 IOpaqueAddress* pParAddr = pParentReg->address();
222 if ( pParAddr ) {
223 TDirectory* pParentDir = (TDirectory*)pParAddr->ipar()[0];
224 if ( pParentDir ) {
225 gDirectory->cd( pParentDir->GetPath() );
226 return pParentDir;
227 }
228 }
229 }
230 }
231 }
232 }
233 return nullptr;
234}
235
236//-----------------------------------------------------------------------------
239//-----------------------------------------------------------------------------
240{
242 pAddr = nullptr;
243 try {
244 TDirectory* pParentDir = changeDirectory( pObject );
245 if ( pParentDir ) {
246 TObject* pTObj = createPersistent( pObject );
247 if ( pTObj ) {
248 pTObj->Write();
249 delete pTObj;
250 return createAddress( pObject, pParentDir, nullptr, pAddr );
251 }
252 }
253 } catch ( ... ) {}
254 MsgStream log( msgSvc(), "RConverter" );
255 log << MSG::ERROR << "Failed to create persistent Object!" << endmsg;
256 return StatusCode::FAILURE;
257}
258
259//-----------------------------------------------------------------------------
261 // MsgStream log(msgSvc(), "RConverter::readObject");
262 // log << MSG::WARNING << pAddr->par()[0] << " <> " << pAddr->par()[1]
263 // << " <> "
264 // << pAddr->ipar()[0] << " <> " << pAddr->ipar()[1] << " <> "
265 // << pAddr->registry()->identifier() << endmsg;
266
267 return StatusCode::SUCCESS;
268}
269
270//-----------------------------------------------------------------------------
271TObject* RootHistCnv::RConverter::createPersistent( DataObject* /* pObj */ ) { return nullptr; }
272
273//-----------------------------------------------------------------------------
274StatusCode RootHistCnv::RConverter::regTFile( const std::string& id, const TFile* tfile )
275//-----------------------------------------------------------------------------
276{
277 auto imap = s_fileMap.find( id );
278 if ( imap != s_fileMap.end() ) {
279 MsgStream log( msgSvc(), "RConverter" );
280 log << MSG::ERROR << "cannot register TTree " << id << ": already exists" << endmsg;
281 return StatusCode::FAILURE;
282 }
283 s_fileMap[id] = const_cast<TFile*>( tfile );
284
285 return StatusCode::SUCCESS;
286}
287
288//-----------------------------------------------------------------------------
289StatusCode RootHistCnv::RConverter::findTFile( const std::string& id, TFile*& tfile )
290//-----------------------------------------------------------------------------
291{
292 MsgStream log( msgSvc(), "RConverter" );
293 tfile = nullptr;
294
295 std::string idm;
296
297 // make sure we only get first two parts of id
298 int i1, i2, i3;
299 i1 = id.find( "/", 0 );
300 if ( i1 != 0 ) {
301 log << MSG::ERROR << "Directory name does not start with \"/\": " << id << endmsg;
302 return StatusCode::FAILURE;
303 }
304 i2 = id.find( "/", i1 + 1 );
305 if ( i2 == -1 ) {
306 log << MSG::ERROR << "Directory name has only one part: " << id << endmsg;
307 return StatusCode::FAILURE;
308 }
309 i3 = id.find( "/", i2 + 1 );
310 if ( i3 == -1 ) {
311 idm = id;
312 } else {
313 idm = id.substr( 0, i3 );
314 }
315
316 auto imap = s_fileMap.find( idm );
317 if ( imap == s_fileMap.end() ) return StatusCode::FAILURE;
318 tfile = imap->second;
319 return StatusCode::SUCCESS;
320}
321//-----------------------------------------------------------------------------
322std::string RootHistCnv::RConverter::convertId( const std::string& id ) const
323//-----------------------------------------------------------------------------
324{
325 bool forced = false;
326 if ( id.size() > 0 && isdigit( id[0] ) ) {
327 try {
329 tmp.assign( conversionSvc().as<IProperty>()->getProperty( "ForceAlphaIds" ) );
330 forced = tmp.value();
331 } catch ( ... ) {}
332 }
333 if ( forced )
334 return "h" + id;
335 else
336 return id;
337}
338//-----------------------------------------------------------------------------
340//-----------------------------------------------------------------------------
341{
342 MsgStream log( msgSvc(), "RootHistCnv" );
343 log << MSG::ERROR << msg << endmsg;
344 return StatusCode::FAILURE;
345}
const char *PyHelper getProperty(IInterface *p, char *name)
unsigned int CLID
Class ID definition.
Definition ClassID.h:16
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
SmartIF< IMessageSvc > & msgSvc() const
Retrieve pointer to message service.
SmartIF< IDataProviderSvc > & dataProvider() const override
Get Data provider service.
Definition Converter.cpp:77
SmartIF< IConversionSvc > & conversionSvc() const override
Get conversion service the converter is connected to.
Definition Converter.cpp:89
const CLID & objType() const override
Retrieve the class type of objects the converter produces.
Definition Converter.cpp:22
A DataObject is the base class of any identifiable object on any data store.
Definition DataObject.h:37
IRegistry * registry() const
Get pointer to Registry.
Definition DataObject.h:79
Implementation of property with value of concrete type.
Definition PropertyFwd.h:27
const ValueType & value() const
Definition Property.h:229
bool assign(const Details::PropertyBase &source) override
get the value from another property
Definition Property.h:361
Opaque address interface definition.
virtual const unsigned long * ipar() const =0
Access to generic link parameters.
The IRegistry represents the entry door to the environment any data object residing in a transient da...
Definition IRegistry.h:29
virtual const name_type & name() const =0
Name of the directory (or key)
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
Definition of the MsgStream class used to transmit messages.
Definition MsgStream.h:29
std::string directory(const std::string &loc)
StatusCode createRep(DataObject *pObj, IOpaqueAddress *&refpAddr) override
Convert the transient object to the requested representation.
std::string diskDirectory(const std::string &loc)
long repSvcType() const override
Definition RConverter.h:46
StatusCode findTFile(const std::string &, TFile *&)
std::string getDirectory()
void setDirectory(const std::string &loc)
void setDiskDirectory(const std::string &loc)
StatusCode createDirectory(const std::string &loc)
StatusCode regTFile(const std::string &, const TFile *)
virtual StatusCode readObject(IOpaqueAddress *pAddr, DataObject *&refpObj)
Create the transient representation of an object.
TDirectory * changeDirectory(DataObject *pObject)
Switch to object directory (=Parent directory)
virtual TObject * createPersistent(DataObject *pObj)
Create the persistent representation of an object.
StatusCode createAddress(DataObject *pObject, TDirectory *pDir, TObject *pTObject, IOpaqueAddress *&refpAddr)
Create address of the transient object according to the requested representation.
StatusCode error(const std::string &msg)
std::string convertId(const std::string &) const
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
bool isSuccess() const
Definition StatusCode.h:314
constexpr static const auto SUCCESS
Definition StatusCode.h:99
constexpr static const auto FAILURE
Definition StatusCode.h:100
@ ERROR
Definition IMessageSvc.h:22