19 #include <boost/algorithm/string/case_conv.hpp>
23 #include <TDirectory.h>
59 template <
typename InputIterator,
typename OutputIterator,
typename UnaryOperation,
typename UnaryPredicate>
60 OutputIterator transform_if( InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op,
61 UnaryPredicate pred ) {
62 while ( first != last ) {
63 if ( pred( *first ) ) *result++ = op( *first );
69 constexpr
struct select1st_t {
70 template <
typename T,
typename S>
88 error() <<
"initializing service" <<
endmsg;
97 error() <<
"Caught: " << err <<
endmsg;
104 error() <<
"Caught: " << err <<
endmsg;
110 static TROOT
root(
"root",
"ROOT I/O" );
117 error() <<
"unable to get the IncidentSvc" <<
endmsg;
124 error() <<
"unable to get the FileMgr" <<
endmsg;
134 error() <<
"unable to register ROOT file open action with FileMgr" <<
endmsg;
140 error() <<
"unable to register ROOT file open Error action with FileMgr" <<
endmsg;
152 auto iomgr = service<IIoComponentMgr>(
"IoComponentMgr" );
154 error() <<
"unable to get the IoComponentMgr" <<
endmsg;
157 if ( !iomgr->io_register(
this ).isSuccess() ) {
158 error() <<
"could not register with the I/O component manager !" <<
endmsg;
161 bool all_good =
true;
163 for (
const auto& reg :
m_files ) {
164 const std::string& fname = reg.second.first->GetName();
167 if ( !iomgr->io_register(
this, iomode, fname ).isSuccess() ) {
168 warning() <<
"could not register file [" << fname <<
"] with the I/O component manager..." <<
endmsg;
171 info() <<
"registered file [" << fname <<
"]... [ok]" <<
endmsg;
175 error() <<
"problem while registering input/output files with "
176 <<
"the I/O component manager !" <<
endmsg;
182 if ( st.
isFailure() ) { fatal() <<
"Unable to initialize THistSvc" <<
endmsg; }
189 warning() <<
"reinitialize not implemented" <<
endmsg;
198 debug() <<
"THistSvc::finalize" <<
endmsg;
204 for (
const auto& itr : sorted_uids ) {
205 THistID& thid = itr.second->at( 0 );
206 TObject* tobj = thid.
obj;
210 TTree* tree =
dynamic_cast<TTree*
>( tobj );
211 if ( tree->GetDirectory() != 0 ) { dirname = tree->GetDirectory()->GetPath(); }
214 dirname = thid.
file->GetPath();
218 if ( id2.starts_with(
"/" ) ) { id2.
erase( 0, 1 ); }
224 TH1* th =
dynamic_cast<TH1*
>( tobj );
225 if ( th ==
nullptr ) {
226 error() <<
"Couldn't dcast: " << itr.first <<
endmsg;
228 if ( th->GetDirectory() != 0 ) { dirname = th->GetDirectory()->GetPath(); }
230 }
else if ( !tobj ) {
231 warning() << itr.first <<
" has NULL TObject ptr" <<
endmsg;
233 debug() <<
"finalize: " << thid <<
endmsg;
240 if (
m_print ) { info() <<
"Listing contents of ROOT files: " <<
endmsg; }
243 if (
std::find( deleted_files.
begin(), deleted_files.
end(), itr.second.first ) == deleted_files.
end() ) {
244 deleted_files.
push_back( itr.second.first );
248 debug() <<
"finalizing stream/file " << itr.first <<
":" << itr.second.first->GetName() <<
endmsg;
259 info() <<
"==> File: " << itr.second.first->GetName() <<
" stream: " << itr.first <<
endmsg;
261 itr.second.first->Print(
"base" );
268 if ( itr.second.second ==
SHARE ) {
270 void* vfile =
nullptr;
275 error() <<
"unable to open Final Output File: \"" <<
m_sharedFiles[itr.first] <<
"\" for merging" <<
endmsg;
279 TFile* outputfile = (TFile*)vfile;
288 error() <<
"unable to open temporary file: \"" << tmpfn <<
endmsg;
292 TFile* inputfile = (TFile*)vfile;
294 outputfile->SetCompressionLevel( inputfile->GetCompressionLevel() );
306 delete itr.second.first;
319 if ( obj.second.second == 0 ) {
320 delete obj.second.first;
345 hist = getHist_i<TH1>(
id, ind );
346 if ( hist !=
nullptr ) {
354 hist = getHist_i<TH2>(
id, ind );
355 if ( hist !=
nullptr ) {
363 hist = getHist_i<TH3>(
id, ind );
364 if ( hist !=
nullptr ) {
398 tree = getHist_i<TTree>(
id );
399 if ( tree !=
nullptr ) {
412 if ( strcmp(
graph->GetName(),
"Graph" ) == 0 ) {
414 std::string::size_type i = id2.
rfind(
"/" );
415 if ( i != std::string::npos ) { id2.
erase( 0, i + 1 ); }
417 info() <<
"setting name of TGraph id: \"" <<
id <<
"\" to \"" << id2 <<
"\" since it is unset" <<
endmsg;
426 if ( strcmp(
graph->GetName(),
"Graph" ) == 0 ) {
428 std::string::size_type i = id2.
rfind(
"/" );
429 if ( i != std::string::npos ) { id2.
erase( 0, i + 1 ); }
431 info() <<
"setting name of TGraph id: \"" <<
id <<
"\" to \"" << id2 <<
"\" since it is unset" <<
endmsg;
439 graph = getHist_i<TGraph>(
id );
440 if (
graph !=
nullptr ) {
462 eff = getHist_i<TEfficiency>(
id );
463 if ( eff !=
nullptr ) {
471 lh = regShared_i<TH1>(
id,
std::move( hist ) );
480 lh = regShared_i<TH2>(
id,
std::move( hist ) );
489 lh = regShared_i<TH3>(
id,
std::move( hist ) );
508 lh = regShared_i<TEfficiency>(
id,
std::move( eff ) );
517 lh = getShared_i<TH1>(
name );
526 lh = getShared_i<TH2>(
name );
535 lh = getShared_i<TH3>(
name );
544 lh = getShared_i<TGraph>(
name );
553 lh = getShared_i<TEfficiency>(
name );
564 error() <<
"Problem deregistering id \"" <<
id <<
"\": not found in registry" <<
endmsg;
571 debug() <<
"will deregister " << vh->
size() <<
" elements of id \"" <<
id <<
"\"" <<
endmsg;
575 size_t vh_size = vh->
size();
576 while ( vh_size-- ) {
579 error() <<
"Problems deRegistering " << vh->
size() <<
" element of id \"" <<
id <<
"\"" <<
endmsg;
590 vhid_t* vhid = obj_itr->second.first;
591 THistID hid = obj_itr->second.first->at( obj_itr->second.second );
595 error() <<
"Problems deregistering TObject \"" << obj->GetName() <<
"\" with id \"" << hid.
id
596 <<
"\": not in uidMap" <<
endmsg;
600 if ( vhid->
size() == 1 ) {
609 [&]( idMap_t::const_reference i ) { return i.second->at( 0 ).obj == obj; } );
610 if ( id_itr == mitr.second ) {
611 error() <<
"Problems deregistering TObject \"" << obj->GetName() <<
"\" with id \"" << hid.
id
612 <<
"\": not in idMap" <<
endmsg;
618 error() <<
"Problems deregistering TObject \"" << obj->GetName() <<
"\" with id \"" << hid.
id
619 <<
"\": not in hlist" <<
endmsg;
623 vhid->
erase( vhid->
begin() + obj_itr->second.second );
632 }
else if ( vhid->
size() > 1 ) {
633 vhid->
erase( vhid->
begin() + obj_itr->second.second );
638 error() <<
"Deregistration failed unexpectedly. (bug in THistSvc?)" <<
endmsg;
642 error() <<
"Cannot unregister TObject \"" << obj->GetName() <<
"\": not known to THistSvc" <<
endmsg;
650 error() <<
"merge: id \"" <<
name <<
"\" not found" <<
endmsg;
654 return merge( itr->second );
660 return merge( itr->second.first );
662 error() <<
"merge: unknown object " << obj <<
endmsg;
672 return ( getHist_i<TEfficiency>(
name, 0,
true ) !=
nullptr );
676 return ( getHist_i<TGraph>(
name, 0,
true ) !=
nullptr );
716 gErrorIgnoreLevel = kBreak;
719 error() <<
"getTHists: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
724 debug() <<
"getTHists: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys" <<
endmsg;
727 TIter nextkey( td->GetListOfKeys() );
728 while ( TKey*
key = (TKey*)nextkey() ) {
731 TObject* obj =
key->ReadObj();
732 if ( obj != 0 && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
734 }
else if ( obj != 0 && obj->IsA()->InheritsFrom(
"TH1" ) ) {
737 }
else if ( obj != 0 ) {
745 nextkey = td->GetListOfKeys();
746 while ( TKey*
key = (TKey*)nextkey() ) {
747 TObject* obj =
key->ReadObj();
748 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
749 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
762 gErrorIgnoreLevel = kBreak;
771 r2 = itr->second.first->GetName();
776 debug() <<
"getTHists: \"" << dir <<
"\" looks like a stream name."
777 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
780 if ( gDirectory->cd( r2.
c_str() ) ) {
793 if ( !gDirectory->cd( dir.
c_str() ) ) {
794 error() <<
"getTHists: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
806 gErrorIgnoreLevel = kBreak;
809 error() <<
"getTHists: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
814 debug() <<
"getTHists: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys" <<
endmsg;
817 TIter nextkey( td->GetListOfKeys() );
818 while ( TKey*
key = (TKey*)nextkey() ) {
821 TObject* obj =
key->ReadObj();
822 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
824 }
else if ( obj && obj->IsA()->InheritsFrom(
"TH1" ) ) {
833 id =
id +
"/" +
key->GetName();
835 id =
id + dir +
"/" +
key->GetName();
852 nextkey = td->GetListOfKeys();
853 while ( TKey*
key = (TKey*)nextkey() ) {
854 TObject* obj =
key->ReadObj();
855 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
856 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
868 gErrorIgnoreLevel = kBreak;
877 r2 = itr->second.first->GetName();
882 debug() <<
"getTHists: \"" << dir <<
"\" looks like a stream name."
883 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
886 if ( gDirectory->cd( r2.
c_str() ) ) {
888 sc =
getTHists( gDirectory, tl, rcs, reg );
897 if ( !gDirectory->cd( dir.
c_str() ) ) {
898 error() <<
"getTHists: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
902 warning() <<
"Unable to register histograms automatically "
903 <<
"without a valid stream name" <<
endmsg;
906 sc =
getTHists( gDirectory, tl, rcs, reg );
915 gErrorIgnoreLevel = kBreak;
918 error() <<
"getTTrees: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
923 debug() <<
"getTHists: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys" <<
endmsg;
926 TIter nextkey( td->GetListOfKeys() );
927 while ( TKey*
key = (TKey*)nextkey() ) {
930 TObject* obj =
key->ReadObj();
931 if ( obj != 0 && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
933 }
else if ( obj != 0 && obj->IsA()->InheritsFrom(
"TTree" ) ) {
936 }
else if ( obj != 0 ) {
944 nextkey = td->GetListOfKeys();
945 while ( TKey*
key = (TKey*)nextkey() ) {
946 TObject* obj =
key->ReadObj();
947 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
948 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
960 gErrorIgnoreLevel = kBreak;
969 r2 = itr->second.first->GetName();
974 debug() <<
"getTTrees: \"" << dir <<
"\" looks like a stream name."
975 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
978 if ( gDirectory->cd( r2.
c_str() ) ) {
return getTTrees( gDirectory, tl, rcs ); }
984 if ( !gDirectory->cd( dir.
c_str() ) ) {
985 error() <<
"getTTrees: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
996 gErrorIgnoreLevel = kBreak;
999 error() <<
"getTTrees: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
1004 debug() <<
"getTHists: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys" <<
endmsg;
1007 TIter nextkey( td->GetListOfKeys() );
1008 while ( TKey*
key = (TKey*)nextkey() ) {
1009 auto&
log = debug();
1011 TObject* obj =
key->ReadObj();
1012 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
1014 }
else if ( obj && obj->IsA()->InheritsFrom(
"TTree" ) ) {
1023 id =
id +
"/" +
key->GetName();
1025 id =
id + dir +
"/" +
key->GetName();
1034 }
else if ( obj != 0 ) {
1042 nextkey = td->GetListOfKeys();
1043 while ( TKey*
key = (TKey*)nextkey() ) {
1044 TObject* obj =
key->ReadObj();
1045 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
1046 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
1058 gErrorIgnoreLevel = kBreak;
1067 r2 = itr->second.first->GetName();
1072 debug() <<
"getTTrees: \"" << dir <<
"\" looks like a stream name."
1073 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
1076 if ( gDirectory->cd( r2.
c_str() ) ) {
1077 return getTTrees( gDirectory, tl, rcs, reg );
1085 if ( !gDirectory->cd( dir.
c_str() ) ) {
1086 error() <<
"getTTrees: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
1090 return getTTrees( gDirectory, tl, rcs, reg );
1096 gErrorIgnoreLevel = kBreak;
1099 error() <<
"getTEfficiencies: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
1104 debug() <<
"getTEfficiencies: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys"
1108 TIter nextkey( td->GetListOfKeys() );
1109 while ( TKey*
key = (TKey*)nextkey() ) {
1110 auto&
log = debug();
1112 TObject* obj =
key->ReadObj();
1113 if ( obj != 0 && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
1115 }
else if ( obj != 0 && obj->IsA()->InheritsFrom(
"TEfficiency" ) ) {
1118 }
else if ( obj != 0 ) {
1126 nextkey = td->GetListOfKeys();
1127 while ( TKey*
key = (TKey*)nextkey() ) {
1128 TObject* obj =
key->ReadObj();
1129 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
1130 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
1143 gErrorIgnoreLevel = kBreak;
1152 r2 = itr->second.first->GetName();
1157 debug() <<
"getTEfficiencies: \"" << dir <<
"\" looks like a stream name."
1158 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
1161 if ( gDirectory->cd( r2.
c_str() ) ) {
1174 if ( !gDirectory->cd( dir.
c_str() ) ) {
1175 error() <<
"getTEfficiencies: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
1187 gErrorIgnoreLevel = kBreak;
1190 error() <<
"getTEfficiencies: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
1195 debug() <<
"getTEfficiencies: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys"
1199 TIter nextkey( td->GetListOfKeys() );
1200 while ( TKey*
key = (TKey*)nextkey() ) {
1201 auto&
log = debug();
1203 TObject* obj =
key->ReadObj();
1204 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
1206 }
else if ( obj && obj->IsA()->InheritsFrom(
"TEfficiency" ) ) {
1215 id =
id +
"/" +
key->GetName();
1217 id =
id + dir +
"/" +
key->GetName();
1234 nextkey = td->GetListOfKeys();
1235 while ( TKey*
key = (TKey*)nextkey() ) {
1236 TObject* obj =
key->ReadObj();
1237 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
1238 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
1250 gErrorIgnoreLevel = kBreak;
1259 r2 = itr->second.first->GetName();
1264 debug() <<
"getTEfficiencies: \"" << dir <<
"\" looks like a stream name."
1265 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
1268 if ( gDirectory->cd( r2.
c_str() ) ) {
1279 if ( !gDirectory->cd( dir.
c_str() ) ) {
1280 error() <<
"getTEfficiencies: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
1284 warning() <<
"Unable to register histograms automatically "
1285 <<
"without a valid stream name" <<
endmsg;
1302 Long64_t mfs_warn = mfs * 95 / 100;
1306 for (
const auto& f :
m_files ) {
1307 TFile* tf = f.second.first;
1311 debug() <<
"stream: " << f.first <<
" name: " << tf->GetName() <<
" size: " << tf->GetSize() <<
endmsg;
1316 if ( tf->GetSize() > mfs ) {
1320 "file size of {} MB. Terminating Job.",
1324 }
else if ( tf->GetSize() > mfs_warn ) {
1325 warning() <<
"file \"" << tf->GetName() <<
"\" associated with stream \"" << f.first
1335 bool all_good =
true;
1340 auto iomgr = service<IIoComponentMgr>(
"IoComponentMgr",
true );
1342 error() <<
"could not retrieve I/O component manager !" <<
endmsg;
1349 gErrorIgnoreLevel = kFatal;
1351 for (
auto& ifile :
m_files ) {
1352 TFile* f = ifile.second.first;
1355 debug() <<
"file [" << fname <<
"] mode: [" << f->GetOption() <<
"] r:" << f->GetFileBytesRead()
1356 <<
" w:" << f->GetFileBytesWritten() <<
" cnt:" << f->GetFileCounter() <<
endmsg;
1359 if ( ifile.second.second ==
READ ) {
1364 if ( !iomgr->io_retrieve(
this, fname ).isSuccess() ) {
1365 error() <<
"could not retrieve new name for [" << fname <<
"] !!" <<
endmsg;
1368 }
else if ( fname.
empty() ) {
1376 Option_t*
opts = f->GetOption();
1379 error() <<
"unable to open file \"" << fname <<
"\" for writing" <<
endmsg;
1382 TFile* newfile = (TFile*)vf;
1383 newfile->SetOption(
opts );
1387 ifile.second.first = newfile;
1391 for (
auto& uid :
m_uids ) {
1392 for (
auto& hid : *uid.second ) {
1393 if ( hid.file != f )
continue;
1394 TDirectory* olddir = this->
changeDir( hid );
1397 TDirectory* newdir = this->
changeDir( hid );
1398 TClass* cl = hid.obj->IsA();
1403 TTree& tree =
dynamic_cast<TTree&
>( *hid.obj );
1404 tree.SetDirectory( newdir );
1407 TH1& hist =
dynamic_cast<TH1&
>( *hid.obj );
1408 hist.SetDirectory( newdir );
1411 dynamic_cast<TEfficiency&
>( *hid.obj ).SetDirectory( newdir );
1413 olddir->Remove( hid.obj );
1414 newdir->Append( hid.obj );
1416 error() <<
"id: \"" << hid.id <<
"\" is not a inheriting from a class "
1417 <<
"we know how to handle (received [" << cl->GetName() <<
"], "
1418 <<
"expected [TTree, TH1, TGraph or TEfficiency]) !" <<
endmsg <<
"attaching to current dir ["
1419 << newdir->GetPath() <<
"] "
1420 <<
"nonetheless..." <<
endmsg;
1421 olddir->Remove( hid.obj );
1422 newdir->Append( hid.obj );
1426 f->ReOpen(
"READ" );
1443 gDirectory = m_gDirectory;
1445 gErrorIgnoreLevel = m_gErrorIgnoreLevel;
1450 template <
typename T>
1452 return dynamic_cast<T*
>( readHist_i<T>(
id ) );
1467 for (
auto& hid : *( uitr->second ) ) {
1470 if ( hid.type !=
ObjectType::TTREE || hid.temp || hid.mode ==
READ || hid.obj ==
nullptr )
continue;
1473 verbose() <<
" update: " << uitr->first <<
" " << hid.id <<
" " << hid.mode <<
endmsg;
1475 TTree* tr =
dynamic_cast<TTree*
>( hid.obj );
1476 TFile* oldFile = hid.file;
1477 TFile* newFile = tr->GetCurrentFile();
1479 if ( oldFile != newFile ) {
1482 TFile* dummy =
nullptr;
1483 findStream( hid.id, streamName, rem, dummy );
1486 if ( itr.second.first == oldFile ) { itr.second.first = newFile; }
1489 for (
auto uitr2 = uitr; uitr2 !=
m_uids.
end(); ++uitr2 ) {
1490 for (
auto& hid2 : *( uitr2->second ) ) {
1491 if ( hid2.file == oldFile ) { hid2.file = newFile; }
1496 [&]( streamMap::const_reference
s ) {
return s.second == streamName; } );
1501 debug() <<
"migrating uid: " << hid.id <<
" stream: " << streamName <<
" oldFile: " << oldFileName
1502 <<
" newFile: " << newFileName <<
endmsg;
1506 if ( !oldFileName.
empty() ) {
1511 debug() <<
"changing filename \"" << i->first <<
"\" to \"" << newFileName <<
"\" for stream \""
1512 << i->second <<
"\"" <<
endmsg;
1520 error() <<
"Problems updating fileStreams with new file name" <<
endmsg;
1531 auto mode = i.second.second;
1532 auto file = i.second.first;
1533 if ( mode == WRITE || mode == UPDATE || mode == SHARE ) {
1534 file->Write(
"", TObject::kOverwrite );
1535 }
else if ( mode ==
APPEND ) {
1541 debug() <<
"THistSvc::writeObjectsToFile()::List of Files connected in ROOT " <<
endmsg;
1542 TSeqCollection* filelist = gROOT->GetListOfFiles();
1543 for (
int ii = 0; ii < filelist->GetEntries(); ii++ ) {
1544 debug() <<
"THistSvc::writeObjectsToFile()::List of Files connected in ROOT: \"" << filelist->At( ii )->GetName()
1553 auto loc =
ident.find(
" " );
1561 if ( loc != std::string::npos ) {
1563 for (
auto attrib : Parser(
ident.substr( loc + 1 ) ) ) {
1567 auto TAG = attrib.tag;
1568 auto VAL = attrib.value;
1569 boost::algorithm::to_upper( TAG );
1570 boost::algorithm::to_upper( VAL );
1572 if ( TAG ==
"FILE" || TAG ==
"DATAFILE" ) {
1575 }
else if ( TAG ==
"OPT" ) {
1576 if ( VAL ==
"APPEND" || VAL ==
"UPDATE" ) {
1578 }
else if ( VAL ==
"CREATE" || VAL ==
"NEW" || VAL ==
"WRITE" ) {
1580 }
else if ( VAL ==
"RECREATE" ) {
1582 }
else if ( VAL ==
"SHARE" ) {
1584 }
else if ( VAL ==
"OLD" || VAL ==
"READ" ) {
1587 error() <<
"Unknown OPT: \"" << attrib.value <<
"\"" <<
endmsg;
1590 }
else if ( TAG ==
"TYP" ) {
1592 }
else if ( TAG ==
"CL" ) {
1595 props.emplace_back( attrib.tag, attrib.value );
1600 if (
stream ==
"temp" ) {
1601 error() <<
"in JobOption \"" <<
ident <<
"\": stream name \"temp\" reserved." <<
endmsg;
1605 if ( db_typ !=
"ROOT" ) {
1606 error() <<
"in JobOption \"" <<
ident <<
"\": technology type \"" << db_typ <<
"\" not supported." <<
endmsg;
1611 error() <<
"in JobOption \"" <<
ident <<
"\":\n stream \"" <<
stream <<
"\" already connected to file: \""
1618 error() <<
"No OPT= specified or unknown access mode in: " <<
ident <<
endmsg;
1626 const std::string& oldstream = fitr.first->second;
1628 const auto& f_info =
m_files[oldstream];
1630 if ( newMode != f_info.second ) {
1631 error() <<
"in JobOption \"" <<
ident <<
"\":\n file \"" <<
filename <<
"\" already opened by stream: \""
1632 << oldstream <<
"\" with different access mode." <<
endmsg;
1635 TFile* f2 = f_info.first;
1638 debug() <<
"Connecting stream: \"" <<
stream <<
"\" to previously opened TFile: \"" <<
filename <<
"\""
1652 error() <<
"Unable to open ROOT file " <<
filename <<
" for reading" <<
endmsg;
1666 error() <<
"Unable to open ROOT file " <<
filename <<
" for writing" <<
endmsg;
1676 error() <<
"unable to open file \"" <<
filename <<
"\" for appending" <<
endmsg;
1687 static int ishared = 0;
1692 debug() <<
"Creating temp file \"" <<
filename <<
"\" and realfilename=" << realfilename <<
endmsg;
1699 error() <<
"Unable to open ROOT file " <<
filename <<
" for writing" <<
endmsg;
1710 error() <<
"Unable to open ROOT file " <<
filename <<
" for appending" <<
endmsg;
1721 debug() <<
"Opening TFile \"" <<
filename <<
"\" stream: \"" <<
stream <<
"\" mode: \"" << typ <<
"\""
1722 <<
" comp level: " << cl <<
endmsg;
1730 TFile* file = hid.
file;
1743 if ( !gDirectory->GetKey( dir.
c_str() ) ) { gDirectory->mkdir( dir.
c_str() ); }
1744 gDirectory->cd( dir.
c_str() );
1751 std::string::size_type i = dir.
find(
"/" );
1753 if ( i == std::string::npos )
return {};
1767 while (
id.find(
"//" ) != std::string::npos ) {
id.replace(
id.find(
"//" ), 2,
"/" ); }
1772 TString
path( (
char*)strstr(
target->GetPath(),
":" ) );
1773 path.Remove( 0, 2 );
1776 TDirectory* current_sourcedir = gDirectory;
1779 TList* lkeys = current_sourcedir->GetListOfKeys();
1780 int nkeys = lkeys->GetEntries();
1781 TKey*
key =
nullptr;
1782 for (
int jj = 0; jj < nkeys; jj++ ) {
1783 key = (TKey*)lkeys->At( jj );
1786 TObject* obj = source->Get( pathnameinsource.
c_str() );
1789 if ( obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
1795 TDirectory* newtargetdir =
target->mkdir( obj->GetName(), obj->GetTitle() );
1799 }
else if ( obj->IsA()->InheritsFrom(
"TTree" ) ) {
1801 TTree* mytree =
dynamic_cast<TTree*
>( obj );
1802 int nentries = (int)mytree->GetEntries();
1803 mytree->SetBranchStatus(
"*", 1 );
1807 mytree->CloneTree();
1811 obj->Write(
key->GetName() );
1818 auto pos =
id.find(
"/" );
1820 if ( pos == std::string::npos ) {
1824 }
else if ( pos != 0 ) {
1831 auto pos2 =
id.find(
"/", pos + 1 );
1833 if ( pos2 == std::string::npos ) {
1835 error() <<
"badly formed Hist/Tree id: \"" <<
id <<
"\"" <<
endmsg;
1841 if (
stream ==
"temp" ) {
1848 if ( !file ) { warning() <<
"no stream \"" <<
stream <<
"\" associated with id: \"" <<
id <<
"\"" <<
endmsg; }
1854 auto pos =
id.find(
"/" );
1856 if ( pos == std::string::npos ) {
1859 }
else if ( pos == 0 ) {
1862 root =
id.substr( 0, pos );
1863 rem =
id.
substr( pos + 1 );
1869 debug() <<
"Delaying connection of Input Files until Initialize"
1874 debug() <<
"Now connecting of Input Files" <<
endmsg;
1880 if (
connect( itr ).isFailure() ) {
1893 debug() <<
"Delaying connection of Output Files until Initialize"
1900 if (
connect( itr ).isFailure() ) {
1913 debug() <<
"copyFileLayout() to destination path: " << destination->GetPath() <<
endmsg;
1917 TString
path( (
char*)strstr( destination->GetPath(),
":" ) );
1918 path.Remove( 0, 2 );
1921 TDirectory* current_source_dir = gDirectory;
1924 TList* key_list = current_source_dir->GetListOfKeys();
1925 int n = key_list->GetEntries();
1926 for (
int j = 0;
j <
n; ++
j ) {
1927 TKey* k = (TKey*)key_list->At(
j );
1929 TObject* o = source->Get( source_pathname.
c_str() );
1931 if ( o && o->IsA()->InheritsFrom(
"TDirectory" ) ) {
1935 TDirectory* destination_dir = destination->mkdir( o->GetName(), o->GetTitle() );
1936 if ( destination_dir ==
nullptr ) destination_dir = destination->GetDirectory( o->GetName() );
1951 if ( idr.starts_with(
"/" ) ) {
1959 if (
index >= itr->second->size() ) {
1960 error() <<
"no index " <<
index <<
" found for Hist " << idr <<
endmsg;
1963 hid = &( itr->second->at(
index ) );
1969 if ( mitr.first == mitr.second ) {
1972 }
else if ( distance( mitr.first, mitr.second ) == 1 ) {
1974 if (
index >= mitr.first->second->size() ) {
1975 error() <<
"no index " <<
index <<
" found for Hist " << idr <<
endmsg;
1978 hid = &( mitr.first->second->at( 0 ) );
1982 hid = &( mitr.first->second->at( 0 ) );
1983 return distance( mitr.first, mitr.second );
1992 ost <<
"m_hlist: size: " <<
m_hlist.
size() <<
"\n";
1994 ost <<
" - " << vh->at( 0 ) <<
" :: [" << vh <<
"] " << vh->size() <<
" {";
1995 for (
auto& e : *vh ) {
1997 ost <<
"[" << o <<
"]";
2005 for (
auto& e :
m_uids ) { ost <<
" - " << e.first <<
" [" << e.second <<
"]" <<
std::endl; }
2010 for (
auto& e :
m_ids ) { ost <<
" - " << e.first <<
" [" << e.second <<
"]" <<
std::endl; }
2016 TObject* o = e.first;
2017 THistID& i = e.second.first->at( e.second.second );
2018 ost <<
" - " << o <<
" -> " << i <<
std::endl;
2021 debug() <<
"dumping THistSvc contents\n" << ost.
str() <<
endmsg;
2028 if ( vh->
size() == 1 ) {
2029 debug() <<
"merge: id: \"" <<
name <<
"\" is size 1. nothing to do" <<
endmsg;
2034 error() <<
"merge: id \"" <<
name <<
"\" is not a THn. Cannot merge" <<
endmsg;
2038 TList*
l =
new TList();
2039 for (
size_t i = 1; i < vh->
size(); ++i ) {
2040 debug() <<
"merge: id: \"" <<
name <<
"\" (" << vh->
at( i ).obj <<
") adding index " << i <<
endmsg;
2041 l->Add( vh->
at( i ).obj );
2044 TH1* t0 =
dynamic_cast<TH1*
>( vh->
at( 0 ).obj );
2046 error() <<
"merge: could not dcast " <<
name <<
"(" << t0 <<
") index " << 0 <<
" to TH1" <<
endmsg;
2050 Long64_t
n = t0->Merge(
l );
2052 debug() <<
"merge: id: \"" <<
name <<
"\" merged " <<
n <<
" entries" <<
endmsg;
2054 for (
size_t i = 1; i < vh->
size(); ++i ) {
2055 TH1* th =
dynamic_cast<TH1*
>( vh->
at( i ).obj );
2057 debug() <<
"clearing index " << i <<
"(" << th <<
")" <<
endmsg;
2058 th->SetDirectory(
nullptr );
2061 error() <<
"merge: could not dcast " <<
name <<
" index " << i <<
" to TH1" <<
endmsg;