The Gaudi Framework  v32r2 (46d42edc)
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 33 of file merge.C.

Member Typedef Documentation

◆ ContainerSections

typedef std::vector<ContainerSection> Gaudi::RootDatabaseMerger::ContainerSections
private

Definition at line 35 of file merge.C.

◆ DatabaseSections

typedef std::map<std::string, ContainerSections> Gaudi::RootDatabaseMerger::DatabaseSections
private

Definition at line 36 of file merge.C.

Constructor & Destructor Documentation

◆ RootDatabaseMerger()

RootDatabaseMerger::RootDatabaseMerger ( )
default

Standard constructor.

◆ ~RootDatabaseMerger()

RootDatabaseMerger::~RootDatabaseMerger ( )
virtual

Default destructor.

Definition at line 114 of file merge.C.

114 { close(); }
MergeStatus close()
Close output file.
Definition: merge.C:197

Member Function Documentation

◆ addSections()

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

Add section information for the next merge step.

Definition at line 292 of file merge.C.

292  {
293  if ( m_treeSections ) {
295  s.start = (int)( out ? out->GetEntries() : 0 );
296  s.length = (int)in->GetEntries();
297  m_sections[in->GetName()].push_back( s );
298  return MERGE_SUCCESS;
299  }
300 
301  TObjArray* a_in = in->GetListOfBranches();
302  for ( int i = 0, n = a_in->GetLast(); i < n; ++i ) {
303  TBranch* b_in = (TBranch*)a_in->At( i );
304  TBranch* b_out = out ? out->GetBranch( b_in->GetName() ) : 0;
305  if ( !out || b_out ) {
307  s.start = (int)( b_out ? b_out->GetEntries() : 0 );
308  s.length = (int)b_in->GetEntries();
309  m_sections[b_in->GetName()].push_back( s );
310  continue;
311  }
312  ::printf( "+++ Cannot merge incompatible branches:%s.\n", b_in->GetName() );
313  return MERGE_ERROR;
314  }
315  return MERGE_SUCCESS;
316 }
T length(T... args)
string s
Definition: gaudirun.py:318
DatabaseSections m_sections
Definition: merge.C:38

◆ attach()

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

Attach to existing output file for further merging.

Definition at line 124 of file merge.C.

124  {
125  const char* fid = file_id.c_str();
126  if ( m_output ) {
127  ::printf( "+++ Another output file %s is already open. Request denied.\n", m_output->GetName() );
128  return MERGE_ERROR;
129  } else if ( !exists( file_id ) ) {
130  ::printf( "+++ Cannot attach output file %s --- file does not exist.\n", fid );
131  return MERGE_ERROR;
132  }
133  m_output.reset( TFile::Open( fid, "UPDATE" ) );
134  if ( m_output && !m_output->IsZombie() ) {
135  // if ( s_dbg ) ::printf("+++ Update output file %s.\n",fid);
136  // if ( s_dbg ) ::printf("+++ Update output file.\n");
137  return MERGE_SUCCESS;
138  }
139  ::printf( "+++ Failed to open new output file %s.\n", fid );
140  return MERGE_ERROR;
141 }
bool exists(const std::string &fid) const
Check if a database exists.
Definition: merge.C:117
std::unique_ptr< TFile > m_output
Definition: merge.C:39
T reset(T... args)
T c_str(T... args)

◆ close()

MergeStatus RootDatabaseMerger::close ( )

Close output file.

Definition at line 197 of file merge.C.

197  {
198  if ( m_output ) {
199  // if ( s_dbg ) ::printf("+++ Closing merge file: %s.\n",m_output->GetName());
200  if ( s_dbg ) ::printf( "+++ Closing merge file.\n" );
201  m_output->Write();
202  m_output->Purge();
203  if ( s_dbg ) m_output->ls();
204  m_output->Close();
205  m_output.reset();
206  }
207  return MERGE_SUCCESS;
208 }
std::unique_ptr< TFile > m_output
Definition: merge.C:39
T reset(T... args)

◆ copyAllTrees()

MergeStatus RootDatabaseMerger::copyAllTrees ( TFile *  source)

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

Definition at line 336 of file merge.C.

336  {
337  TIter nextkey( source->GetListOfKeys() );
338  // m_treeSections = true;
339  for ( TKey* key = (TKey*)nextkey(); key; key = (TKey*)nextkey() ) {
340  const char* classname = key->GetClassName();
341  TClass* cl = gROOT->GetClass( classname );
342  if ( !cl ) continue;
343  if ( cl->InheritsFrom( "TTree" ) ) {
344  string name = key->GetName();
345  if ( name == "Refs" ) continue;
346  m_treeSections = 0 == ::strncmp( key->GetName(), "<local>_", 7 );
347  printf( "+++ Copy Tree:%s %d\n", name.c_str(), int( m_treeSections ) );
348  if ( copyTree( source, name ) != MERGE_SUCCESS ) {
349  m_treeSections = false;
350  return MERGE_ERROR;
351  }
352  }
353  }
354  m_treeSections = false;
355  return MERGE_SUCCESS;
356 }
MergeStatus copyTree(TFile *source, const std::string &name)
Copy one single tree from the input file to the output file.
Definition: merge.C:359
T printf(T... args)

◆ copyBranch()

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

Copy single reference branch.

Definition at line 319 of file merge.C.

319  {
320  char text[4096];
321  TBranch* s = src_tree->GetBranch( name.c_str() );
322  TBranch* o = out_tree->GetBranch( name.c_str() );
323  if ( s && o ) {
324  s->SetAddress( text );
325  o->SetAddress( text );
326  for ( Long64_t i = 0, n = s->GetEntries(); i < n; ++i ) {
327  s->GetEntry( i );
328  o->Fill();
329  }
330  return MERGE_SUCCESS;
331  }
332  return MERGE_ERROR;
333 }
string s
Definition: gaudirun.py:318

◆ 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 403 of file merge.C.

403  {
404  TTree* src_tree = (TTree*)source->Get( name.c_str() );
405  if ( src_tree ) {
406  TTree* out_tree = (TTree*)m_output->Get( name.c_str() );
407  if ( out_tree ) {
408  addSections( src_tree, out_tree );
409  copyBranch( src_tree, out_tree, "Links" );
410  copyBranch( src_tree, out_tree, "Params" );
411  copyBranch( src_tree, out_tree, "Containers" );
412  copyBranch( src_tree, out_tree, "Databases" );
413  out_tree->Write();
414  return MERGE_SUCCESS;
415  }
416  }
417  return MERGE_ERROR;
418 }
MergeStatus addSections(TTree *in, TTree *out)
Add section information for the next merge step.
Definition: merge.C:292
std::unique_ptr< TFile > m_output
Definition: merge.C:39
MergeStatus copyBranch(TTree *src_tree, TTree *out_tree, const std::string &name)
Copy single reference branch.
Definition: merge.C:319

◆ 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 359 of file merge.C.

359  {
360  TTree* src_tree = (TTree*)source->Get( name.c_str() );
361  if ( src_tree ) {
362  Long64_t src_entries = src_tree->GetEntries();
363  TTree* out_tree = (TTree*)m_output->Get( name.c_str() );
364  m_output->cd();
365  if ( 0 == src_tree->GetEntries() ) { src_tree->SetEntries( 1 ); }
366  addSections( src_tree, out_tree );
367  if ( !out_tree ) {
368  out_tree = src_tree->CloneTree( -1, "fast" );
369  if ( s_dbg ) ::printf( "+++ Created new Tree %s.\n", out_tree->GetName() );
370  out_tree->Write();
371  delete out_tree;
372  return MERGE_SUCCESS;
373  }
374  m_output->GetObject( name.c_str(), out_tree );
375  TTreeCloner cloner( src_tree, out_tree, "fast" );
376  if ( cloner.IsValid() ) {
377  Long64_t out_entries = out_tree->GetEntries();
378  out_tree->SetEntries( out_entries + src_entries );
379  Bool_t res = cloner.Exec();
380  if ( s_dbg ) ::printf( "+++ Merged tree: %s res=%d\n", out_tree->GetName(), res );
381  out_tree->Write();
382  delete out_tree;
383  return MERGE_SUCCESS;
384  } else {
385  // Fast cloning is not possible for this input TTree.
386  // ... see TTree::CloneTree for example of recovery code ...
387  ::printf( "+++ Got a tree where fast cloning is not possible -- operation failed.\n" );
388  return MERGE_ERROR;
389  }
390 #if 0
391  Long64_t nb = out_tree->CopyEntries(src_tree,-1,"fast");
392  Long64_t out_entries = out_tree->GetEntries();
393  out_tree->SetEntries(out_entries+src_entries);
394  out_tree->Write();
395  if ( s_dbg ) ::printf("+++ Merged tree: %s res=%lld\n",out_tree->GetName(),nb);
396  return MERGE_SUCCESS;
397 #endif
398  }
399  return MERGE_ERROR;
400 }
MergeStatus addSections(TTree *in, TTree *out)
Add section information for the next merge step.
Definition: merge.C:292
std::unique_ptr< TFile > m_output
Definition: merge.C:39

◆ create()

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

Create new output file.

Definition at line 144 of file merge.C.

144  {
145  if ( m_output ) {
146  ::printf( "+++ Another output file %s is already open. Request denied.\n", m_output->GetName() );
147  return MERGE_ERROR;
148  } else if ( exists( fid ) ) {
149  ::printf( "+++ Cannot create output file %s --- file already exists.\n", fid.c_str() );
150  return MERGE_ERROR;
151  }
152  m_output.reset( TFile::Open( fid.c_str(), "RECREATE" ) );
153  if ( m_output && !m_output->IsZombie() ) {
154  TTree* t1 = new TTree( "Sections", "Root Section data" );
155  TTree* t2 = new TTree( "Refs", "Root Section data" );
156  if ( t1 && t2 ) {
157  t1->Branch( "Sections", 0, "Sections/C" );
158  t2->Branch( "Links", 0, "Links/C" );
159  t2->Branch( "Params", 0, "Params/C" );
160  t2->Branch( "Databases", 0, "Databases/C" );
161  t2->Branch( "Containers", 0, "Containers/C" );
162  if ( s_dbg ) ::printf( "+++ Opened new output file %s.\n", fid.c_str() );
163  return MERGE_SUCCESS;
164  }
165  }
166  ::printf( "+++ Failed to open new output file %s.\n", fid.c_str() );
167  return MERGE_ERROR;
168 }
bool exists(const std::string &fid) const
Check if a database exists.
Definition: merge.C:117
std::unique_ptr< TFile > m_output
Definition: merge.C:39
T reset(T... args)
T c_str(T... args)

◆ createFID()

MergeStatus RootDatabaseMerger::createFID ( )

Create and add new FID to the newly merged file.

Close output file.

Definition at line 171 of file merge.C.

171  {
172  static const char* fmt = "FID=%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX";
173  if ( m_output ) {
174  TTree* t = (TTree*)m_output->Get( "Refs" );
175  if ( t ) {
176  uuid_data d;
177  char text[256];
178  TUUID uuid;
179  TBranch* b = t->GetBranch( "Params" );
180  if ( b ) {
181  uuid.GetUUID( d.buf );
182  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],
183  d.buf[13], d.buf[14], d.buf[15] );
184  b->SetAddress( text );
185  b->Fill();
186  t->Write();
187  if ( s_dbg ) ::printf( "+++ Added new GUID %s to merge file.\n", text );
188  return MERGE_SUCCESS;
189  }
190  }
191  }
192  ::printf( "+++ Failed to add new GUID to merge file.\n" );
193  return MERGE_ERROR;
194 }
std::unique_ptr< TFile > m_output
Definition: merge.C:39
T sprintf(T... args)

◆ dumpSections()

void RootDatabaseMerger::dumpSections ( )

Dump collected database sections.

Definition at line 254 of file merge.C.

254  {
255  for ( const auto& i : m_sections ) {
256  int cnt = 0;
257  string prefix = i.first;
258  for ( const auto& j : i.second ) {
259  char text[1024];
260  ::sprintf( text, "['%s'][%d]", prefix.c_str(), cnt++ );
261  if ( s_dbg ) {
262  ::printf( "+++ section %-55s Start:%8d ... %8d [%d entries]\n", text, j.start, j.start + j.length, j.length );
263  }
264  }
265  }
266 }
string prefix
Definition: gaudirun.py:333
T c_str(T... args)
DatabaseSections m_sections
Definition: merge.C:38

◆ exists()

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

Check if a database exists.

Definition at line 117 of file merge.C.

117  {
118  Bool_t result = gSystem->AccessPathName( fid.c_str(), kFileExists );
119  // if ( s_dbg ) ::printf("File %s %s!\n",fid.c_str(),result == kFALSE ? "EXISTS" : "DOES NOT EXIST");
120  return result == kFALSE;
121 }
T c_str(T... args)

◆ merge()

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

Merge new input to existing output.

Definition at line 269 of file merge.C.

269  {
270  if ( m_output ) {
271  std::unique_ptr<TFile> source{TFile::Open( fid.c_str() )};
272  if ( source && !source->IsZombie() ) {
273  size_t idx = fid.rfind( '/' );
274  ::printf( "+++ Start merging input file:%s\n",
275  idx != string::npos ? fid.substr( idx + 1 ).c_str() : fid.c_str() );
276  if ( copyAllTrees( source.get() ) == MERGE_SUCCESS ) {
277  if ( copyRefs( source.get(), "Refs" ) == MERGE_SUCCESS ) {
278  source->Close();
279  return MERGE_SUCCESS;
280  }
281  }
282  }
283  ::printf( "+++ Cannot open input file:%s\n", source->GetName() );
284  m_output->cd();
285  return MERGE_ERROR;
286  }
287  ::printf( "+++ No valid output file present. Merge request refused for fid:%s.\n", fid.c_str() );
288  return MERGE_ERROR;
289 }
MergeStatus copyAllTrees(TFile *source)
Copy all data trees from the input file to the output file.
Definition: merge.C:336
T rfind(T... args)
std::unique_ptr< TFile > m_output
Definition: merge.C:39
T c_str(T... args)
T substr(T... args)
MergeStatus copyRefs(TFile *source, const std::string &name)
Copy one single tree from the input file to the output file.
Definition: merge.C:403

◆ saveSections()

MergeStatus RootDatabaseMerger::saveSections ( )

Save new sections to the output file.

Definition at line 211 of file merge.C.

211  {
212  if ( m_output ) {
213  int nb, total = 0, nbytes = 0;
214  char text[1024];
215  TTree* t = (TTree*)m_output->Get( "Sections" );
216  if ( t ) {
217  TBranch* b = t->GetBranch( "Sections" );
218  if ( b ) {
219  b->SetAddress( text );
220  for ( const auto& i : m_sections ) {
221  string cont = i.first;
222  for ( const auto& j : i.second ) {
223  ::sprintf( text, "[CNT=%s][START=%d][LEN=%d]", cont.c_str(), j.start, j.length );
224  nb = t->Fill();
225  ++total;
226  if ( nb > 0 )
227  nbytes += nb;
228  else
229  ::printf( "+++ Failed to update Sections tree with new entries. [WRITE_ERROR]\n" );
230  }
231  }
232  ::sprintf( text, "[END-OF-SECTION]" );
233  nb = t->Fill();
234  ++total;
235  if ( nb > 0 )
236  nbytes += nb;
237  else
238  ::printf( "+++ Failed to update Sections branch with new entries. [WRITE_ERROR]\n" );
239  t->Write();
240  if ( s_dbg ) ::printf( "+++ Added %d Sections entries with %d bytes in total.\n", total, nbytes );
241  return MERGE_SUCCESS;
242  }
243  ::printf( "+++ Failed to update Sections tree with new entries. [NO_OUTPUT_BRANCH]\n" );
244  return MERGE_ERROR;
245  }
246  ::printf( "+++ Failed to update Sections tree with new entries. [NO_OUTPUT_TREE]\n" );
247  return MERGE_ERROR;
248  }
249  ::printf( "+++ Failed to update Sections tree with new entries. [NO_OUTPUT_FILE]\n" );
250  return MERGE_ERROR;
251 }
std::unique_ptr< TFile > m_output
Definition: merge.C:39
T c_str(T... args)
DatabaseSections m_sections
Definition: merge.C:38

Member Data Documentation

◆ m_output

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

Definition at line 39 of file merge.C.

◆ m_sections

DatabaseSections Gaudi::RootDatabaseMerger::m_sections
private

Definition at line 38 of file merge.C.

◆ m_treeSections

bool Gaudi::RootDatabaseMerger::m_treeSections = false
private

Definition at line 40 of file merge.C.


The documentation for this class was generated from the following file: