The Gaudi Framework  master (37c0b60a)
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"
16 #include <GaudiKernel/DataObject.h>
19 #include <GaudiKernel/IRegistry.h>
20 #include <GaudiKernel/MsgStream.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 
29 namespace {
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 
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 
76  return StatusCode::SUCCESS;
77 }
78 //-----------------------------------------------------------------------------
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 //-----------------------------------------------------------------------------
112 //-----------------------------------------------------------------------------
113 {
114  return diskDirectory( loc );
115 }
116 
117 //-----------------------------------------------------------------------------
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 //-----------------------------------------------------------------------------
152 //-----------------------------------------------------------------------------
153 {
154  setDirectory( loc );
155 }
156 
157 //-----------------------------------------------------------------------------
159 //-----------------------------------------------------------------------------
160 {
161  return gDirectory->GetPath();
162 }
163 
164 //-----------------------------------------------------------------------------
165 StatusCode 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 //--------------------------------------------------------------------------
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 //--------------------------------------------------------------------------
195 StatusCode 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 {
241  GlobalDirectoryRestore restore;
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 //-----------------------------------------------------------------------------
271 TObject* RootHistCnv::RConverter::createPersistent( DataObject* /* pObj */ ) { return nullptr; }
272 
273 //-----------------------------------------------------------------------------
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 //-----------------------------------------------------------------------------
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 //-----------------------------------------------------------------------------
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 }
RConverter.h
RootHistCnv::RConverter::convertId
std::string convertId(const std::string &) const
Definition: RConverter.cpp:322
RootHistCnv::RConverter::createPersistent
virtual TObject * createPersistent(DataObject *pObj)
Create the persistent representation of an object.
Definition: RConverter.cpp:271
std::string
STL class.
details::size
constexpr auto size(const T &, Args &&...) noexcept
Definition: AnyDataWrapper.h:23
Gaudi.Configuration.log
log
Definition: Configuration.py:28
IDataManagerSvc
Definition: IDataManagerSvc.h:55
StatusCode::isSuccess
bool isSuccess() const
Definition: StatusCode.h:314
gaudirun.s
string s
Definition: gaudirun.py:346
IOpaqueAddress
Definition: IOpaqueAddress.h:33
std::vector< std::string >
std::string::find
T find(T... args)
GaudiMP.FdsRegistry.msg
msg
Definition: FdsRegistry.py:19
RootHistCnv::RConverter::findTFile
StatusCode findTFile(const std::string &, TFile *&)
Definition: RConverter.cpp:289
IRegistry
Definition: IRegistry.h:32
Gaudi::Property::assign
bool assign(const Details::PropertyBase &source) override
get the value from another property
Definition: Property.h:370
GaudiPartProp.tests.id
id
Definition: tests.py:111
RootHistCnv::RootObjAddress
Definition: RootObjAddress.h:21
IDataProviderSvc.h
AvalancheSchedulerErrorTest.msgSvc
msgSvc
Definition: AvalancheSchedulerErrorTest.py:80
RootHistCnv::RConverter::setDirectory
void setDirectory(const std::string &loc)
Definition: RConverter.cpp:118
std::vector::push_back
T push_back(T... args)
RootHistCnv::RConverter::createRep
StatusCode createRep(DataObject *pObj, IOpaqueAddress *&refpAddr) override
Convert the transient object to the requested representation.
Definition: RConverter.cpp:238
SmartIF.h
RootHistCnv::RConverter::directory
std::string directory(const std::string &loc)
Definition: RConverter.cpp:111
IRegistry::name
virtual const name_type & name() const =0
Name of the directory (or key)
RootHistCnv::RConverter::regTFile
StatusCode regTFile(const std::string &, const TFile *)
Definition: RConverter.cpp:274
StatusCode
Definition: StatusCode.h:65
RootHistCnv::RConverter::diskDirectory
std::string diskDirectory(const std::string &loc)
Definition: RConverter.cpp:79
std::string::c_str
T c_str(T... args)
RootHistCnv::RConverter::getDirectory
std::string getDirectory()
Definition: RConverter.cpp:158
Gaudi::Property::value
const ValueType & value() const
Definition: Property.h:237
std::to_string
T to_string(T... args)
RootHistCnv::RConverter::createAddress
StatusCode createAddress(DataObject *pObject, TDirectory *pDir, TObject *pTObject, IOpaqueAddress *&refpAddr)
Create address of the transient object according to the requested representation.
Definition: RConverter.cpp:165
CLID
unsigned int CLID
Class ID definition.
Definition: ClassID.h:18
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202
std::map
STL class.
RootObjAddress.h
IRegistry.h
MsgStream
Definition: MsgStream.h:33
GlobalDirectoryRestore
Definition: RConverter.h:26
RootHistCnv::RConverter::error
StatusCode error(const std::string &msg)
Definition: RConverter.cpp:339
std::string::substr
T substr(T... args)
IRegistry::address
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
RootHistCnv::RConverter::setDiskDirectory
void setDiskDirectory(const std::string &loc)
Definition: RConverter.cpp:151
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
DataObject.h
MSG::ERROR
@ ERROR
Definition: IMessageSvc.h:25
RootHistCnv::RConverter::createDirectory
StatusCode createDirectory(const std::string &loc)
Definition: RConverter.cpp:34
DataObject
Definition: DataObject.h:36
RootHistCnv::RConverter::readObject
virtual StatusCode readObject(IOpaqueAddress *pAddr, DataObject *&refpObj)
Create the transient representation of an object.
Definition: RConverter.cpp:260
RootHistCnv::RConverter::changeDirectory
TDirectory * changeDirectory(DataObject *pObject)
Switch to object directory (=Parent directory)
Definition: RConverter.cpp:210
Converter::msgSvc
SmartIF< IMessageSvc > & msgSvc() const
Retrieve pointer to message service.
Definition: Converter.cpp:105
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
getProperty
const char *PyHelper() getProperty(IInterface *p, char *name)
Definition: Bootstrap.cpp:251
DataObject::registry
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:78
Gaudi::Property< bool >
IDataManagerSvc.h
MsgStream.h
IOpaqueAddress::ipar
virtual const unsigned long * ipar() const =0
Access to generic link parameters.