11 #ifndef GAUDIROOTCNV_ROOTDATABASEMERGER_H
12 # define GAUDIROOTCNV_ROOTDATABASEMERGER_H
53 unsigned char buf[16];
93 #endif // GAUDIROOTCNV_ROOTDATABASEMERGER_H
95 #ifndef GAUDIROOTCNV_ROOTDATABASEMERGER_H
96 # include <RootDatabaseMerger.h>
97 #endif // GAUDIROOTCNV_ROOTDATABASEMERGER_H
100 #include <TInterpreter.h>
106 #include <TTreeCloner.h>
113 using namespace Gaudi;
117 static bool s_dbg =
true;
128 Bool_t result = gSystem->AccessPathName( fid.
c_str(), kFileExists );
130 return result == kFALSE;
135 const char* fid = file_id.
c_str();
137 ::printf(
"+++ Another output file %s is already open. Request denied.\n", m_output->GetName() );
139 }
else if ( !exists( file_id ) ) {
140 ::printf(
"+++ Cannot attach output file %s --- file does not exist.\n", fid );
143 m_output.reset( TFile::Open( fid,
"UPDATE" ) );
144 if ( m_output && !m_output->IsZombie() ) {
149 ::printf(
"+++ Failed to open new output file %s.\n", fid );
156 ::printf(
"+++ Another output file %s is already open. Request denied.\n", m_output->GetName() );
158 }
else if ( exists( fid ) ) {
159 ::printf(
"+++ Cannot create output file %s --- file already exists.\n", fid.
c_str() );
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" );
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() );
176 ::printf(
"+++ Failed to open new output file %s.\n", fid.
c_str() );
182 static const char*
fmt =
"FID=%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX";
184 TTree*
t = (TTree*)m_output->Get(
"Refs" );
189 TBranch* b =
t->GetBranch(
"Params" );
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],
194 b->SetAddress( text );
197 if ( s_dbg ) ::printf(
"+++ Added new GUID %s to merge file.\n", text );
202 ::printf(
"+++ Failed to add new GUID to merge file.\n" );
210 if ( s_dbg ) ::printf(
"+++ Closing merge file.\n" );
213 if ( s_dbg ) m_output->ls();
223 int nb, total = 0, nbytes = 0;
225 TTree*
t = (TTree*)m_output->Get(
"Sections" );
227 TBranch* b =
t->GetBranch(
"Sections" );
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 );
239 ::printf(
"+++ Failed to update Sections tree with new entries. [WRITE_ERROR]\n" );
242 ::sprintf( text,
"[END-OF-SECTION]" );
248 ::printf(
"+++ Failed to update Sections branch with new entries. [WRITE_ERROR]\n" );
250 if ( s_dbg ) ::printf(
"+++ Added %d Sections entries with %d bytes in total.\n", total, nbytes );
253 ::printf(
"+++ Failed to update Sections tree with new entries. [NO_OUTPUT_BRANCH]\n" );
256 ::printf(
"+++ Failed to update Sections tree with new entries. [NO_OUTPUT_TREE]\n" );
259 ::printf(
"+++ Failed to update Sections tree with new entries. [NO_OUTPUT_FILE]\n" );
265 for (
const auto& i : m_sections ) {
268 for (
const auto&
j : i.second ) {
270 ::sprintf( text,
"['%s'][%d]",
prefix.
c_str(), cnt++ );
272 ::printf(
"+++ section %-55s Start:%8d ... %8d [%d entries]\n", text,
j.start,
j.start +
j.length,
j.length );
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() );
293 ::printf(
"+++ Cannot open input file:%s\n", fid.
c_str() );
297 ::printf(
"+++ No valid output file present. Merge request refused for fid:%s.\n", fid.
c_str() );
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 );
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 );
322 ::printf(
"+++ Cannot merge incompatible branches:%s.\n", b_in->GetName() );
331 TBranch*
s = src_tree->GetBranch(
name.c_str() );
332 TBranch* o = out_tree->GetBranch(
name.c_str() );
334 s->SetAddress( text );
335 o->SetAddress( text );
336 for ( Long64_t i = 0,
n =
s->GetEntries(); i <
n; ++i ) {
347 TIter nextkey( source->GetListOfKeys() );
349 for ( TKey*
key = (TKey*)nextkey();
key;
key = (TKey*)nextkey() ) {
350 const char* classname =
key->GetClassName();
351 TClass* cl = gROOT->GetClass( classname );
353 if ( cl->InheritsFrom(
"TTree" ) ) {
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 ) );
359 m_treeSections =
false;
364 m_treeSections =
false;
370 TTree* src_tree = (TTree*)source->Get(
name.c_str() );
372 Long64_t src_entries = src_tree->GetEntries();
373 TTree* out_tree = (TTree*)m_output->Get(
name.c_str() );
375 if ( 0 == src_tree->GetEntries() ) { src_tree->SetEntries( 1 ); }
376 addSections( src_tree, out_tree );
378 out_tree = src_tree->CloneTree( -1,
"fast" );
379 if ( s_dbg ) ::printf(
"+++ Created new Tree %s.\n", out_tree->GetName() );
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 );
397 ::printf(
"+++ Got a tree where fast cloning is not possible -- operation failed.\n" );
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);
405 if ( s_dbg ) ::printf(
"+++ Merged tree: %s res=%lld\n",out_tree->GetName(),nb);
414 TTree* src_tree = (TTree*)source->Get(
name.c_str() );
416 TTree* out_tree = (TTree*)m_output->Get(
name.c_str() );
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" );
430 int merge(
const char*
target,
const char* source,
bool fixup =
false,
bool dbg =
true ) {
434 static bool first =
true;
437 gSystem->Load(
"libCintex");
438 gInterpreter->ProcessLine(
"Cintex::Enable()");
448 ret =
m.merge( source );
451 if ( fixup )
m.createFID();
456 ::printf(
"+++ Cannot open output file:%s\n",
target );