The Gaudi Framework  master (37c0b60a)
Gaudi::RootDatabaseMerger Class Reference
Collaboration diagram for Gaudi::RootDatabaseMerger:

Classes

union  uuid_data
 

Public Member Functions

 RootDatabaseMerger ()
 Standard constructor. More...
 
virtual ~RootDatabaseMerger ()
 Default destructor. More...
 
bool exists (const std::string &fid) const
 Check if a database exists. More...
 
MergeStatus create (const std::string &fid)
 Create new output file. More...
 
MergeStatus attach (const std::string &fid)
 Attach to existing output file for further merging. More...
 
MergeStatus close ()
 Close output file. More...
 
MergeStatus merge (const std::string &fid)
 Merge new input to existing output. More...
 
void dumpSections ()
 Dump collected database sections. More...
 
MergeStatus saveSections ()
 Save new sections to the output file. More...
 
MergeStatus createFID ()
 Create and add new FID to the newly merged file. More...
 
MergeStatus copyAllTrees (TFile *source)
 Copy all data trees from the input file to the output file. More...
 
MergeStatus copyTree (TFile *source, const std::string &name)
 Copy one single tree from the input file to the output file. More...
 
MergeStatus copyBranch (TTree *src_tree, TTree *out_tree, const std::string &name)
 Copy single reference branch. More...
 
MergeStatus copyRefs (TFile *source, const std::string &name)
 Copy one single tree from the input file to the output file. More...
 
MergeStatus addSections (TTree *in, TTree *out)
 Add section information for the next merge step. More...
 

Private Types

typedef std::vector< ContainerSectionContainerSections
 
typedef std::map< std::string, ContainerSectionsDatabaseSections
 

Private Attributes

DatabaseSections m_sections
 
std::unique_ptr< TFile > m_output
 
bool m_treeSections = false
 

Detailed Description

Author
M.Frank
Version
1.0

Definition at line 43 of file merge.C.

Member Typedef Documentation

◆ ContainerSections

◆ DatabaseSections

Constructor & Destructor Documentation

◆ RootDatabaseMerger()

RootDatabaseMerger::RootDatabaseMerger ( )
default

Standard constructor.

◆ ~RootDatabaseMerger()

RootDatabaseMerger::~RootDatabaseMerger ( )
virtual

Default destructor.

Definition at line 124 of file merge.C.

124 { close(); }

Member Function Documentation

◆ addSections()

MergeStatus RootDatabaseMerger::addSections ( TTree *  in,
TTree *  out 
)

Add section information for the next merge step.

Definition at line 302 of file merge.C.

302  {
303  if ( m_treeSections ) {
305  s.start = (int)( out ? out->GetEntries() : 0 );
306  s.length = (int)in->GetEntries();
307  m_sections[in->GetName()].push_back( s );
308  return MERGE_SUCCESS;
309  }
310 
311  TObjArray* a_in = in->GetListOfBranches();
312  for ( int i = 0, n = a_in->GetLast(); i < n; ++i ) {
313  TBranch* b_in = (TBranch*)a_in->At( i );
314  TBranch* b_out = out ? out->GetBranch( b_in->GetName() ) : 0;
315  if ( !out || b_out ) {
317  s.start = (int)( b_out ? b_out->GetEntries() : 0 );
318  s.length = (int)b_in->GetEntries();
319  m_sections[b_in->GetName()].push_back( s );
320  continue;
321  }
322  ::printf( "+++ Cannot merge incompatible branches:%s.\n", b_in->GetName() );
323  return MERGE_ERROR;
324  }
325  return MERGE_SUCCESS;
326 }

◆ attach()

MergeStatus RootDatabaseMerger::attach ( const std::string fid)

Attach to existing output file for further merging.

Definition at line 134 of file merge.C.

134  {
135  const char* fid = file_id.c_str();
136  if ( m_output ) {
137  ::printf( "+++ Another output file %s is already open. Request denied.\n", m_output->GetName() );
138  return MERGE_ERROR;
139  } else if ( !exists( file_id ) ) {
140  ::printf( "+++ Cannot attach output file %s --- file does not exist.\n", fid );
141  return MERGE_ERROR;
142  }
143  m_output.reset( TFile::Open( fid, "UPDATE" ) );
144  if ( m_output && !m_output->IsZombie() ) {
145  // if ( s_dbg ) ::printf("+++ Update output file %s.\n",fid);
146  // if ( s_dbg ) ::printf("+++ Update output file.\n");
147  return MERGE_SUCCESS;
148  }
149  ::printf( "+++ Failed to open new output file %s.\n", fid );
150  return MERGE_ERROR;
151 }

◆ close()

MergeStatus RootDatabaseMerger::close ( )

Close output file.

Definition at line 207 of file merge.C.

207  {
208  if ( m_output ) {
209  // if ( s_dbg ) ::printf("+++ Closing merge file: %s.\n",m_output->GetName());
210  if ( s_dbg ) ::printf( "+++ Closing merge file.\n" );
211  m_output->Write();
212  m_output->Purge();
213  if ( s_dbg ) m_output->ls();
214  m_output->Close();
215  m_output.reset();
216  }
217  return MERGE_SUCCESS;
218 }

◆ copyAllTrees()

MergeStatus RootDatabaseMerger::copyAllTrees ( TFile *  source)

Copy all data trees from the input file to the output file.

Definition at line 346 of file merge.C.

346  {
347  TIter nextkey( source->GetListOfKeys() );
348  // m_treeSections = true;
349  for ( TKey* key = (TKey*)nextkey(); key; key = (TKey*)nextkey() ) {
350  const char* classname = key->GetClassName();
351  TClass* cl = gROOT->GetClass( classname );
352  if ( !cl ) continue;
353  if ( cl->InheritsFrom( "TTree" ) ) {
354  string name = key->GetName();
355  if ( name == "Refs" ) continue;
356  m_treeSections = 0 == ::strncmp( key->GetName(), "<local>_", 7 );
357  printf( "+++ Copy Tree:%s %d\n", name.c_str(), int( m_treeSections ) );
358  if ( copyTree( source, name ) != MERGE_SUCCESS ) {
359  m_treeSections = false;
360  return MERGE_ERROR;
361  }
362  }
363  }
364  m_treeSections = false;
365  return MERGE_SUCCESS;
366 }

◆ copyBranch()

MergeStatus RootDatabaseMerger::copyBranch ( TTree *  src_tree,
TTree *  out_tree,
const std::string name 
)

Copy single reference branch.

Definition at line 329 of file merge.C.

329  {
330  char text[4096];
331  TBranch* s = src_tree->GetBranch( name.c_str() );
332  TBranch* o = out_tree->GetBranch( name.c_str() );
333  if ( s && o ) {
334  s->SetAddress( text );
335  o->SetAddress( text );
336  for ( Long64_t i = 0, n = s->GetEntries(); i < n; ++i ) {
337  s->GetEntry( i );
338  o->Fill();
339  }
340  return MERGE_SUCCESS;
341  }
342  return MERGE_ERROR;
343 }

◆ copyRefs()

MergeStatus RootDatabaseMerger::copyRefs ( TFile *  source,
const std::string name 
)

Copy one single tree from the input file to the output file.

Copy refs of one single tree from the input file to the output file.

Definition at line 413 of file merge.C.

413  {
414  TTree* src_tree = (TTree*)source->Get( name.c_str() );
415  if ( src_tree ) {
416  TTree* out_tree = (TTree*)m_output->Get( name.c_str() );
417  if ( out_tree ) {
418  addSections( src_tree, out_tree );
419  copyBranch( src_tree, out_tree, "Links" );
420  copyBranch( src_tree, out_tree, "Params" );
421  copyBranch( src_tree, out_tree, "Containers" );
422  copyBranch( src_tree, out_tree, "Databases" );
423  out_tree->Write();
424  return MERGE_SUCCESS;
425  }
426  }
427  return MERGE_ERROR;
428 }

◆ copyTree()

MergeStatus RootDatabaseMerger::copyTree ( TFile *  source,
const std::string name 
)

Copy one single tree from the input file to the output file.

Definition at line 369 of file merge.C.

369  {
370  TTree* src_tree = (TTree*)source->Get( name.c_str() );
371  if ( src_tree ) {
372  Long64_t src_entries = src_tree->GetEntries();
373  TTree* out_tree = (TTree*)m_output->Get( name.c_str() );
374  m_output->cd();
375  if ( 0 == src_tree->GetEntries() ) { src_tree->SetEntries( 1 ); }
376  addSections( src_tree, out_tree );
377  if ( !out_tree ) {
378  out_tree = src_tree->CloneTree( -1, "fast" );
379  if ( s_dbg ) ::printf( "+++ Created new Tree %s.\n", out_tree->GetName() );
380  out_tree->Write();
381  delete out_tree;
382  return MERGE_SUCCESS;
383  }
384  m_output->GetObject( name.c_str(), out_tree );
385  TTreeCloner cloner( src_tree, out_tree, "fast" );
386  if ( cloner.IsValid() ) {
387  Long64_t out_entries = out_tree->GetEntries();
388  out_tree->SetEntries( out_entries + src_entries );
389  Bool_t res = cloner.Exec();
390  if ( s_dbg ) ::printf( "+++ Merged tree: %s res=%d\n", out_tree->GetName(), res );
391  out_tree->Write();
392  delete out_tree;
393  return MERGE_SUCCESS;
394  } else {
395  // Fast cloning is not possible for this input TTree.
396  // ... see TTree::CloneTree for example of recovery code ...
397  ::printf( "+++ Got a tree where fast cloning is not possible -- operation failed.\n" );
398  return MERGE_ERROR;
399  }
400 #if 0
401  Long64_t nb = out_tree->CopyEntries(src_tree,-1,"fast");
402  Long64_t out_entries = out_tree->GetEntries();
403  out_tree->SetEntries(out_entries+src_entries);
404  out_tree->Write();
405  if ( s_dbg ) ::printf("+++ Merged tree: %s res=%lld\n",out_tree->GetName(),nb);
406  return MERGE_SUCCESS;
407 #endif
408  }
409  return MERGE_ERROR;
410 }

◆ create()

MergeStatus RootDatabaseMerger::create ( const std::string fid)

Create new output file.

Definition at line 154 of file merge.C.

154  {
155  if ( m_output ) {
156  ::printf( "+++ Another output file %s is already open. Request denied.\n", m_output->GetName() );
157  return MERGE_ERROR;
158  } else if ( exists( fid ) ) {
159  ::printf( "+++ Cannot create output file %s --- file already exists.\n", fid.c_str() );
160  return MERGE_ERROR;
161  }
162  m_output.reset( TFile::Open( fid.c_str(), "RECREATE" ) );
163  if ( m_output && !m_output->IsZombie() ) {
164  TTree* t1 = new TTree( "Sections", "Root Section data" );
165  TTree* t2 = new TTree( "Refs", "Root Section data" );
166  if ( t1 && t2 ) {
167  t1->Branch( "Sections", 0, "Sections/C" );
168  t2->Branch( "Links", 0, "Links/C" );
169  t2->Branch( "Params", 0, "Params/C" );
170  t2->Branch( "Databases", 0, "Databases/C" );
171  t2->Branch( "Containers", 0, "Containers/C" );
172  if ( s_dbg ) ::printf( "+++ Opened new output file %s.\n", fid.c_str() );
173  return MERGE_SUCCESS;
174  }
175  }
176  ::printf( "+++ Failed to open new output file %s.\n", fid.c_str() );
177  return MERGE_ERROR;
178 }

◆ createFID()

MergeStatus RootDatabaseMerger::createFID ( )

Create and add new FID to the newly merged file.

Close output file.

Definition at line 181 of file merge.C.

181  {
182  static const char* fmt = "FID=%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX";
183  if ( m_output ) {
184  TTree* t = (TTree*)m_output->Get( "Refs" );
185  if ( t ) {
186  uuid_data d;
187  char text[256];
188  TUUID uuid;
189  TBranch* b = t->GetBranch( "Params" );
190  if ( b ) {
191  uuid.GetUUID( d.buf );
192  sprintf( text, fmt, d.ibuf[0], d.sbuf[2], d.sbuf[3], d.buf[8], d.buf[9], d.buf[10], d.buf[11], d.buf[12],
193  d.buf[13], d.buf[14], d.buf[15] );
194  b->SetAddress( text );
195  b->Fill();
196  t->Write();
197  if ( s_dbg ) ::printf( "+++ Added new GUID %s to merge file.\n", text );
198  return MERGE_SUCCESS;
199  }
200  }
201  }
202  ::printf( "+++ Failed to add new GUID to merge file.\n" );
203  return MERGE_ERROR;
204 }

◆ dumpSections()

void RootDatabaseMerger::dumpSections ( )

Dump collected database sections.

Definition at line 264 of file merge.C.

264  {
265  for ( const auto& i : m_sections ) {
266  int cnt = 0;
267  string prefix = i.first;
268  for ( const auto& j : i.second ) {
269  char text[1024];
270  ::sprintf( text, "['%s'][%d]", prefix.c_str(), cnt++ );
271  if ( s_dbg ) {
272  ::printf( "+++ section %-55s Start:%8d ... %8d [%d entries]\n", text, j.start, j.start + j.length, j.length );
273  }
274  }
275  }
276 }

◆ exists()

bool RootDatabaseMerger::exists ( const std::string fid) const

Check if a database exists.

Definition at line 127 of file merge.C.

127  {
128  Bool_t result = gSystem->AccessPathName( fid.c_str(), kFileExists );
129  // if ( s_dbg ) ::printf("File %s %s!\n",fid.c_str(),result == kFALSE ? "EXISTS" : "DOES NOT EXIST");
130  return result == kFALSE;
131 }

◆ merge()

MergeStatus RootDatabaseMerger::merge ( const std::string fid)

Merge new input to existing output.

Definition at line 279 of file merge.C.

279  {
280  if ( m_output ) {
281  std::unique_ptr<TFile> source{ TFile::Open( fid.c_str() ) };
282  if ( source && !source->IsZombie() ) {
283  size_t idx = fid.rfind( '/' );
284  ::printf( "+++ Start merging input file:%s\n",
285  idx != string::npos ? fid.substr( idx + 1 ).c_str() : fid.c_str() );
286  if ( copyAllTrees( source.get() ) == MERGE_SUCCESS ) {
287  if ( copyRefs( source.get(), "Refs" ) == MERGE_SUCCESS ) {
288  source->Close();
289  return MERGE_SUCCESS;
290  }
291  }
292  }
293  ::printf( "+++ Cannot open input file:%s\n", fid.c_str() );
294  m_output->cd();
295  return MERGE_ERROR;
296  }
297  ::printf( "+++ No valid output file present. Merge request refused for fid:%s.\n", fid.c_str() );
298  return MERGE_ERROR;
299 }

◆ saveSections()

MergeStatus RootDatabaseMerger::saveSections ( )

Save new sections to the output file.

Definition at line 221 of file merge.C.

221  {
222  if ( m_output ) {
223  int nb, total = 0, nbytes = 0;
224  char text[1024];
225  TTree* t = (TTree*)m_output->Get( "Sections" );
226  if ( t ) {
227  TBranch* b = t->GetBranch( "Sections" );
228  if ( b ) {
229  b->SetAddress( text );
230  for ( const auto& i : m_sections ) {
231  string cont = i.first;
232  for ( const auto& j : i.second ) {
233  ::sprintf( text, "[CNT=%s][START=%d][LEN=%d]", cont.c_str(), j.start, j.length );
234  nb = t->Fill();
235  ++total;
236  if ( nb > 0 )
237  nbytes += nb;
238  else
239  ::printf( "+++ Failed to update Sections tree with new entries. [WRITE_ERROR]\n" );
240  }
241  }
242  ::sprintf( text, "[END-OF-SECTION]" );
243  nb = t->Fill();
244  ++total;
245  if ( nb > 0 )
246  nbytes += nb;
247  else
248  ::printf( "+++ Failed to update Sections branch with new entries. [WRITE_ERROR]\n" );
249  t->Write();
250  if ( s_dbg ) ::printf( "+++ Added %d Sections entries with %d bytes in total.\n", total, nbytes );
251  return MERGE_SUCCESS;
252  }
253  ::printf( "+++ Failed to update Sections tree with new entries. [NO_OUTPUT_BRANCH]\n" );
254  return MERGE_ERROR;
255  }
256  ::printf( "+++ Failed to update Sections tree with new entries. [NO_OUTPUT_TREE]\n" );
257  return MERGE_ERROR;
258  }
259  ::printf( "+++ Failed to update Sections tree with new entries. [NO_OUTPUT_FILE]\n" );
260  return MERGE_ERROR;
261 }

Member Data Documentation

◆ m_output

std::unique_ptr<TFile> Gaudi::RootDatabaseMerger::m_output
private

Definition at line 49 of file merge.C.

◆ m_sections

DatabaseSections Gaudi::RootDatabaseMerger::m_sections
private

Definition at line 48 of file merge.C.

◆ m_treeSections

bool Gaudi::RootDatabaseMerger::m_treeSections = false
private

Definition at line 50 of file merge.C.


The documentation for this class was generated from the following file:
Gaudi::ContainerSection
Definition: merge.C:33
Gaudi::MERGE_ERROR
@ MERGE_ERROR
Definition: merge.C:31
Gaudi::RootDatabaseMerger::copyRefs
MergeStatus copyRefs(TFile *source, const std::string &name)
Copy one single tree from the input file to the output file.
Definition: merge.C:413
gaudirun.s
string s
Definition: gaudirun.py:346
Gaudi::RootDatabaseMerger::m_treeSections
bool m_treeSections
Definition: merge.C:50
std::string::length
T length(T... args)
gaudirun.prefix
string prefix
Definition: gaudirun.py:361
std::unique_ptr::reset
T reset(T... args)
Gaudi::MERGE_SUCCESS
@ MERGE_SUCCESS
Definition: merge.C:31
Gaudi::RootDatabaseMerger::copyBranch
MergeStatus copyBranch(TTree *src_tree, TTree *out_tree, const std::string &name)
Copy single reference branch.
Definition: merge.C:329
bug_34121.t
t
Definition: bug_34121.py:31
std::printf
T printf(T... args)
ProduceConsume.j
j
Definition: ProduceConsume.py:104
Gaudi::RootDatabaseMerger::addSections
MergeStatus addSections(TTree *in, TTree *out)
Add section information for the next merge step.
Definition: merge.C:302
TemplatedAlg
Definition: TemplatedAlg.cpp:22
std::string::c_str
T c_str(T... args)
cpluginsvc.n
n
Definition: cpluginsvc.py:234
Gaudi::RootDatabaseMerger::exists
bool exists(const std::string &fid) const
Check if a database exists.
Definition: merge.C:127
std::string::substr
T substr(T... args)
ConditionsStallTest.name
name
Definition: ConditionsStallTest.py:77
Gaudi::RootDatabaseMerger::m_sections
DatabaseSections m_sections
Definition: merge.C:48
fmt
Gaudi::RootDatabaseMerger::copyTree
MergeStatus copyTree(TFile *source, const std::string &name)
Copy one single tree from the input file to the output file.
Definition: merge.C:369
Gaudi::RootDatabaseMerger::m_output
std::unique_ptr< TFile > m_output
Definition: merge.C:49
Gaudi::RootDatabaseMerger::copyAllTrees
MergeStatus copyAllTrees(TFile *source)
Copy all data trees from the input file to the output file.
Definition: merge.C:346
Gaudi::RootDatabaseMerger::close
MergeStatus close()
Close output file.
Definition: merge.C:207
std::unique_ptr< TFile >
ProduceConsume.key
key
Definition: ProduceConsume.py:84
std::string::rfind
T rfind(T... args)
PrepareBase.out
out
Definition: PrepareBase.py:20