7 #include "boost/algorithm/string/case_conv.hpp" 10 #include "TDirectory.h" 36 template <
typename InputIterator,
typename OutputIterator,
typename UnaryOperation,
typename UnaryPredicate>
37 OutputIterator transform_if( InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op,
40 while ( first != last ) {
41 if ( pred( *first ) ) *result++ = op( *first );
47 constexpr
struct select1st_t {
48 template <
typename T,
typename S>
65 error() <<
"initializing service" <<
endmsg;
74 error() <<
"Caught: " << err <<
endmsg;
81 error() <<
"Caught: " << err <<
endmsg;
87 static TROOT
root(
"root",
"ROOT I/O" );
91 verbose() <<
"ROOT already initialized, debug = " << gDebug <<
endmsg;
95 if ( service(
"IncidentSvc", p_incSvc,
true ).isFailure() ) {
96 error() <<
"unable to get the IncidentSvc" <<
endmsg;
99 p_incSvc->addListener(
this,
"EndEvent", 100,
true );
102 if ( service(
"FileMgr", p_fileMgr,
true ).isFailure() ) {
103 error() <<
"unable to get the FileMgr" <<
endmsg;
106 debug() <<
"got the FileMgr" <<
endmsg;
111 auto boa = [
this](
const Io::FileAttr* fa,
const std::string& caller ) {
return this->rootOpenAction( fa, caller ); };
113 error() <<
"unable to register ROOT file open action with FileMgr" <<
endmsg;
116 return this->rootOpenErrAction( fa, caller );
119 error() <<
"unable to register ROOT file open Error action with FileMgr" <<
endmsg;
122 m_okToConnect =
true;
123 if ( m_delayConnect ) {
124 if ( !m_inputfile.value().empty() ) setupInputFile();
125 if ( !m_outputfile.value().empty() ) setupOutputFile();
126 m_delayConnect =
false;
128 m_alreadyConnectedOutFiles.
clear();
129 m_alreadyConnectedInFiles.clear();
132 if ( service(
"IoComponentMgr", iomgr,
true ).isFailure() ) {
133 error() <<
"unable to get the IoComponentMgr" <<
endmsg;
137 error() <<
"could not register with the I/O component manager !" <<
endmsg;
140 bool all_good =
true;
142 for (
const auto& reg : m_files ) {
143 const std::string& fname = reg.second.first->GetName();
147 warning() <<
"could not register file [" << fname <<
"] with the I/O component manager..." <<
endmsg;
150 info() <<
"registered file [" << fname <<
"]... [ok]" <<
endmsg;
154 error() <<
"problem while registering input/output files with " 155 <<
"the I/O component manager !" <<
endmsg;
162 fatal() <<
"Unable to initialize THistSvc" <<
endmsg;
171 warning() <<
"reinitialize not implemented" <<
endmsg;
181 debug() <<
"THistSvc::finalize" <<
endmsg;
187 for (
const auto& itr : sorted_uids ) {
188 THistID& thid = itr.second->at( 0 );
189 TObject* tobj = thid.
obj;
192 if ( tobj && tobj->IsA()->InheritsFrom(
"TTree" ) ) {
193 TTree* tree =
dynamic_cast<TTree*
>( tobj );
194 if ( tree->GetDirectory() != 0 ) {
195 dirname = tree->GetDirectory()->GetPath();
197 }
else if ( tobj && tobj->IsA()->InheritsFrom(
"TGraph" ) ) {
199 dirname = thid.
file->GetPath();
203 if ( id2.
find(
"/" ) == 0 ) {
210 }
else if ( tobj && tobj->IsA()->InheritsFrom(
"TH1" ) ) {
211 TH1* th =
dynamic_cast<TH1*
>( tobj );
212 if ( th ==
nullptr ) {
213 error() <<
"Couldn't dcast: " << itr.first <<
endmsg;
215 if ( th->GetDirectory() != 0 ) {
216 dirname = th->GetDirectory()->GetPath();
219 }
else if ( !tobj ) {
220 warning() << itr.first <<
" has NULL TObject ptr" <<
endmsg;
222 debug() <<
"finalize: " << thid <<
endmsg;
227 if ( writeObjectsToFile().isFailure() ) {
228 error() <<
"problems writing histograms" <<
endmsg;
232 info() <<
"Listing contents of ROOT files: " <<
endmsg;
235 for (
auto& itr : m_files ) {
236 if (
std::find( deleted_files.
begin(), deleted_files.
end(), itr.second.first ) == deleted_files.
end() ) {
237 deleted_files.
push_back( itr.second.first );
241 debug() <<
"finalizing stream/file " << itr.first <<
":" << itr.second.first->GetName() <<
endmsg;
247 debug() <<
"already finalized stream " << itr.first <<
endmsg;
253 if ( m_print && msgLevel(
MSG::INFO ) ) {
254 info() <<
"==> File: " << itr.second.first->GetName() <<
" stream: " << itr.first <<
endmsg;
256 itr.second.first->Print(
"base" );
261 p_fileMgr->close( itr.second.first,
name() );
264 if ( service(
"IncidentSvc", pIncidentSvc ).isFailure() ) {
265 error() <<
"Unable to get the IncidentSvc" <<
endmsg;
269 if ( itr.second.second == SHARE ) {
271 void* vfile =
nullptr;
276 error() <<
"unable to open Final Output File: \"" << m_sharedFiles[itr.first] <<
"\" for merging" <<
endmsg;
280 TFile* outputfile = (TFile*)vfile;
284 debug() <<
"THistSvc::writeObjectsToFile()::Merging Rootfile " <<
endmsg;
291 error() <<
"unable to open temporary file: \"" << tmpfn <<
endmsg;
295 TFile* inputfile = (TFile*)vfile;
297 outputfile->SetCompressionLevel( inputfile->GetCompressionLevel() );
299 MergeRootFile( outputfile, inputfile );
302 p_fileMgr->close( outputfile,
name() );
303 p_fileMgr->close( inputfile,
name() );
306 debug() <<
"Trying to remove temporary file \"" << tmpfn <<
"\"" <<
endmsg;
311 delete itr.second.first;
315 m_sharedFiles.clear();
316 m_fileStreams.clear();
321 for (
auto& obj : m_tobjs ) {
323 delete obj.second.first;
335 return regHist_i(
std::move( hist ),
id,
false );
340 return regHist_i(
std::move( hist ),
id,
false );
346 if ( hist_ptr !=
nullptr ) {
347 hist_ptr = hist.
get();
349 return regHist_i(
std::move( hist ),
id,
false );
355 return regHist_i(
std::move( hist ),
id,
false );
360 hist = getHist_i<TH1>( id, ind );
361 if ( hist !=
nullptr ) {
370 hist = getHist_i<TH2>( id, ind );
371 if ( hist !=
nullptr ) {
380 hist = getHist_i<TH3>( id, ind );
381 if ( hist !=
nullptr ) {
391 return regHist_i(
std::move( tree ),
id,
false );
398 if ( getTree(
id, tr ).isSuccess() && sc.
isSuccess() ) {
399 if ( m_autoSave != 0 ) {
400 tr->SetAutoSave( m_autoSave );
402 tr->SetAutoFlush( m_autoFlush );
412 if ( getTree(
id, tr ).isSuccess() && sc.
isSuccess() ) {
413 if ( m_autoSave != 0 ) {
414 tr->SetAutoSave( m_autoSave );
416 tr->SetAutoFlush( m_autoFlush );
423 tree = getHist_i<TTree>( id );
424 if ( tree !=
nullptr ) {
434 return regHist_i(
std::move( graph ),
id,
false );
439 if ( strcmp( graph->GetName(),
"Graph" ) == 0 ) {
441 std::string::size_type i = id2.
rfind(
"/" );
442 if ( i != std::string::npos ) {
443 id2.
erase( 0, i + 1 );
446 info() <<
"setting name of TGraph id: \"" <<
id <<
"\" to \"" << id2 <<
"\" since it is unset" <<
endmsg;
447 graph->SetName( id2.
c_str() );
450 return regHist_i(
std::move( graph ),
id,
false );
456 if ( strcmp( graph->GetName(),
"Graph" ) == 0 ) {
458 std::string::size_type i = id2.
rfind(
"/" );
459 if ( i != std::string::npos ) {
460 id2.
erase( 0, i + 1 );
463 info() <<
"setting name of TGraph id: \"" <<
id <<
"\" to \"" << id2 <<
"\" since it is unset" <<
endmsg;
464 graph->SetName( id2.
c_str() );
467 return regHist_i(
std::move( graph ),
id,
false );
472 graph = getHist_i<TGraph>( id );
473 if ( graph !=
nullptr ) {
482 lh = regShared_i<TH1>( id,
std::move( hist ) );
492 lh = regShared_i<TH2>( id,
std::move( hist ) );
502 lh = regShared_i<TH3>( id,
std::move( hist ) );
512 lh = regShared_i<TGraph>( id,
std::move( graph ) );
522 lh = getShared_i<TH1>(
name );
532 lh = getShared_i<TH2>(
name );
542 lh = getShared_i<TH3>(
name );
552 lh = getShared_i<TGraph>(
name );
562 auto itr = m_uids.find(
id );
563 if ( itr == m_uids.end() ) {
564 error() <<
"Problem deregistering id \"" <<
id <<
"\": not found in registry" <<
endmsg;
569 debug() <<
"will deregister " << vh->
size() <<
" elements of id \"" <<
id <<
"\"" <<
endmsg;
572 size_t vh_size = vh->
size();
573 while ( vh_size-- ) {
574 if ( deReg( vh->
back().obj ).isFailure() ) {
576 error() <<
"Problems deRegistering " << vh->
size() <<
" element of id \"" <<
id <<
"\"" <<
endmsg;
586 objMap_t::iterator obj_itr = m_tobjs.find( obj );
587 if ( obj_itr != m_tobjs.end() ) {
588 vhid_t* vhid = obj_itr->second.first;
589 THistID hid = obj_itr->second.first->at( obj_itr->second.second );
591 auto uid_itr = m_uids.find( hid.
id );
592 if ( uid_itr == m_uids.end() ) {
593 error() <<
"Problems deregistering TObject \"" << obj->GetName() <<
"\" with id \"" << hid.
id 594 <<
"\": not in uidMap" <<
endmsg;
598 if ( vhid->
size() == 1 ) {
600 debug() <<
"vhid for " << hid.
id <<
" is empty. deleting" <<
endmsg;
603 parseString( hid.
id, root, rem );
605 auto mitr = m_ids.equal_range( rem );
607 [&]( idMap_t::const_reference i ) { return i.second->at( 0 ).obj == obj; } );
608 if ( id_itr == mitr.second ) {
609 error() <<
"Problems deregistering TObject \"" << obj->GetName() <<
"\" with id \"" << hid.
id 610 <<
"\": not in idMap" <<
endmsg;
614 auto hlist_itr =
std::find( m_hlist.begin(), m_hlist.end(), vhid );
615 if ( hlist_itr == m_hlist.end() ) {
616 error() <<
"Problems deregistering TObject \"" << obj->GetName() <<
"\" with id \"" << hid.
id 617 <<
"\": not in hlist" <<
endmsg;
621 vhid->
erase( vhid->
begin() + obj_itr->second.second );
622 m_tobjs.erase( obj_itr );
624 m_uids.erase( uid_itr );
625 m_ids.erase( id_itr );
626 m_hlist.erase( hlist_itr );
630 }
else if ( vhid->
size() > 1 ) {
631 m_tobjs.
erase( obj_itr );
632 vhid->
erase( vhid->
begin() + obj_itr->second.second );
636 error() <<
"Deregistration failed unexpectedly. (bug in THistSvc?)" <<
endmsg;
640 error() <<
"Cannot unregister TObject \"" << obj->GetName() <<
"\": not known to THistSvc" <<
endmsg;
647 uidMap_t::iterator itr = m_uids.find( name );
648 if ( itr == m_uids.end() ) {
649 error() <<
"merge: id \"" << name <<
"\" not found" <<
endmsg;
653 return merge( itr->second );
658 objMap_t::iterator itr = m_tobjs.find( obj );
659 if ( itr != m_tobjs.end() ) {
660 return merge( itr->second.first );
662 error() <<
"merge: unknown object " << obj <<
endmsg;
672 names.
reserve( m_uids.size() );
674 []( uidMap_t::const_reference i ) {
return i.second->at( 0 ).obj->IsA()->InheritsFrom(
"TH1" ); } );
681 names.
reserve( m_uids.size() );
683 []( uidMap_t::const_reference i ) {
return i.second->at( 0 ).obj->IsA()->InheritsFrom(
"TTree" ); } );
690 names.
reserve( m_uids.size() );
692 []( uidMap_t::const_reference i ) {
return i.second->at( 0 ).obj->IsA()->InheritsFrom(
"TGraph" ); } );
700 gErrorIgnoreLevel = kBreak;
703 error() <<
"getTHists: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
708 debug() <<
"getTHists: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys" <<
endmsg;
711 TIter nextkey( td->GetListOfKeys() );
712 while ( TKey* key = (TKey*)nextkey() ) {
714 if ( msgLevel(
MSG::DEBUG ) )
log <<
" key: " << key->GetName();
715 TObject* obj = key->ReadObj();
716 if ( obj != 0 && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
717 if ( msgLevel(
MSG::DEBUG ) )
log <<
" (" << obj->IsA()->GetName() <<
")";
718 }
else if ( obj != 0 && obj->IsA()->InheritsFrom(
"TH1" ) ) {
719 if ( msgLevel(
MSG::DEBUG ) )
log <<
" (" << obj->IsA()->GetName() <<
")";
721 }
else if ( obj != 0 ) {
722 if ( msgLevel(
MSG::DEBUG ) )
log <<
" [" << obj->IsA()->GetName() <<
"]";
729 nextkey = td->GetListOfKeys();
730 while ( TKey* key = (TKey*)nextkey() ) {
731 TObject* obj = key->ReadObj();
732 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
733 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
734 getTHists( tt, tl, rcs );
747 gErrorIgnoreLevel = kBreak;
752 parseString( dir, stream, rem );
754 auto itr = m_files.find( stream );
755 if ( itr != m_files.end() ) {
756 r2 = itr->second.first->GetName();
761 debug() <<
"getTHists: \"" << dir <<
"\" looks like a stream name." 762 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
765 if ( gDirectory->cd( r2.
c_str() ) ) {
766 m_curstream = stream;
767 sc = getTHists( gDirectory, tl, rcs );
772 debug() <<
"getTHists: no such TDirectory \"" << r2 <<
"\"" <<
endmsg;
778 debug() <<
"getTHists: stream \"" << stream <<
"\" not found" <<
endmsg;
782 if ( !gDirectory->cd( dir.
c_str() ) ) {
783 error() <<
"getTHists: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
786 sc = getTHists( gDirectory, tl, rcs );
796 gErrorIgnoreLevel = kBreak;
799 error() <<
"getTHists: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
804 debug() <<
"getTHists: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys" <<
endmsg;
807 TIter nextkey( td->GetListOfKeys() );
808 while ( TKey* key = (TKey*)nextkey() ) {
810 if ( msgLevel(
MSG::DEBUG ) )
log <<
" key: " << key->GetName();
811 TObject* obj = key->ReadObj();
812 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
813 if ( msgLevel(
MSG::DEBUG ) )
log <<
" (" << obj->IsA()->GetName() <<
")";
814 }
else if ( obj && obj->IsA()->InheritsFrom(
"TH1" ) ) {
815 if ( msgLevel(
MSG::DEBUG ) )
log <<
" (" << obj->IsA()->GetName() <<
")";
817 if ( reg && m_curstream !=
"" ) {
823 id =
id +
"/" + key->GetName();
825 id =
id + dir +
"/" + key->GetName();
827 if ( !exists(
id ) ) {
828 if ( msgLevel(
MSG::DEBUG ) )
log <<
" reg as \"" <<
id <<
"\"";
829 regHist(
id ).ignore();
835 if ( msgLevel(
MSG::DEBUG ) )
log <<
" [" << obj->IsA()->GetName() <<
"]";
842 nextkey = td->GetListOfKeys();
843 while ( TKey* key = (TKey*)nextkey() ) {
844 TObject* obj = key->ReadObj();
845 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
846 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
847 getTHists( tt, tl, rcs, reg );
859 gErrorIgnoreLevel = kBreak;
864 parseString( dir, stream, rem );
866 auto itr = m_files.find( stream );
867 if ( itr != m_files.end() ) {
868 r2 = itr->second.first->GetName();
873 debug() <<
"getTHists: \"" << dir <<
"\" looks like a stream name." 874 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
877 if ( gDirectory->cd( r2.
c_str() ) ) {
878 m_curstream = stream;
879 sc = getTHists( gDirectory, tl, rcs, reg );
884 debug() <<
"getTHists: no such TDirectory \"" << r2 <<
"\"" <<
endmsg;
888 debug() <<
"getTHists: stream \"" << stream <<
"\" not found" <<
endmsg;
892 if ( !gDirectory->cd( dir.
c_str() ) ) {
893 error() <<
"getTHists: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
897 warning() <<
"Unable to register histograms automatically " 898 <<
"without a valid stream name" <<
endmsg;
901 sc = getTHists( gDirectory, tl, rcs, reg );
911 gErrorIgnoreLevel = kBreak;
914 error() <<
"getTTrees: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
919 debug() <<
"getTHists: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys" <<
endmsg;
922 TIter nextkey( td->GetListOfKeys() );
923 while ( TKey* key = (TKey*)nextkey() ) {
925 if ( msgLevel(
MSG::DEBUG ) )
log <<
" key: " << key->GetName();
926 TObject* obj = key->ReadObj();
927 if ( obj != 0 && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
928 if ( msgLevel(
MSG::DEBUG ) )
log <<
" (" << obj->IsA()->GetName() <<
")";
929 }
else if ( obj != 0 && obj->IsA()->InheritsFrom(
"TTree" ) ) {
930 if ( msgLevel(
MSG::DEBUG ) )
log <<
" (" << obj->IsA()->GetName() <<
")";
932 }
else if ( obj != 0 ) {
933 if ( msgLevel(
MSG::DEBUG ) )
log <<
" [" << obj->IsA()->GetName() <<
"]";
940 nextkey = td->GetListOfKeys();
941 while ( TKey* key = (TKey*)nextkey() ) {
942 TObject* obj = key->ReadObj();
943 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
944 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
945 getTTrees( tt, tl, rcs );
957 gErrorIgnoreLevel = kBreak;
962 parseString( dir, stream, rem );
964 auto itr = m_files.find( stream );
965 if ( itr != m_files.end() ) {
966 r2 = itr->second.first->GetName();
971 debug() <<
"getTTrees: \"" << dir <<
"\" looks like a stream name." 972 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
975 if ( gDirectory->cd( r2.
c_str() ) ) {
976 return getTTrees( gDirectory, tl, rcs );
979 debug() <<
"getTTrees: no such TDirectory \"" << r2 <<
"\"" <<
endmsg;
983 debug() <<
"getTTrees: stream \"" << stream <<
"\" not found" <<
endmsg;
987 if ( !gDirectory->cd( dir.
c_str() ) ) {
988 error() <<
"getTTrees: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
991 sc = getTTrees( gDirectory, tl, rcs );
1000 gErrorIgnoreLevel = kBreak;
1003 error() <<
"getTTrees: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
1008 debug() <<
"getTHists: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys" <<
endmsg;
1011 TIter nextkey( td->GetListOfKeys() );
1012 while ( TKey* key = (TKey*)nextkey() ) {
1013 auto&
log = debug();
1014 if ( msgLevel(
MSG::DEBUG ) )
log <<
" key: " << key->GetName();
1015 TObject* obj = key->ReadObj();
1016 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
1017 if ( msgLevel(
MSG::DEBUG ) )
log <<
" (" << obj->IsA()->GetName() <<
")";
1018 }
else if ( obj && obj->IsA()->InheritsFrom(
"TTree" ) ) {
1019 if ( msgLevel(
MSG::DEBUG ) )
log <<
" (" << obj->IsA()->GetName() <<
")";
1021 if ( reg && m_curstream !=
"" ) {
1027 id =
id +
"/" + key->GetName();
1029 id =
id + dir +
"/" + key->GetName();
1031 if ( !exists(
id ) ) {
1032 if ( msgLevel(
MSG::DEBUG ) )
log <<
" reg as \"" <<
id <<
"\"";
1033 regHist(
id ).ignore();
1038 }
else if ( obj != 0 ) {
1039 if ( msgLevel(
MSG::DEBUG ) )
log <<
" [" << obj->IsA()->GetName() <<
"]";
1046 nextkey = td->GetListOfKeys();
1047 while ( TKey* key = (TKey*)nextkey() ) {
1048 TObject* obj = key->ReadObj();
1049 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
1050 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
1051 getTTrees( tt, tl, rcs, reg );
1063 gErrorIgnoreLevel = kBreak;
1068 parseString( dir, stream, rem );
1070 auto itr = m_files.find( stream );
1071 if ( itr != m_files.end() ) {
1072 r2 = itr->second.first->GetName();
1077 debug() <<
"getTTrees: \"" << dir <<
"\" looks like a stream name." 1078 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
1081 if ( gDirectory->cd( r2.
c_str() ) ) {
1082 return getTTrees( gDirectory, tl, rcs, reg );
1085 debug() <<
"getTTrees: no such TDirectory \"" << r2 <<
"\"" <<
endmsg;
1090 debug() <<
"getTTrees: stream \"" << stream <<
"\" not found" <<
endmsg;
1094 if ( !gDirectory->cd( dir.
c_str() ) ) {
1095 error() <<
"getTTrees: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
1099 return getTTrees( gDirectory, tl, rcs, reg );
1106 if ( m_signaledStop )
return;
1108 if ( m_maxFileSize.value() == -1 )
return;
1111 Long64_t mfs = (Long64_t)m_maxFileSize.value() * (Long64_t)1048576;
1112 Long64_t mfs_warn = mfs * 95 / 100;
1116 for (
const auto& f : m_files ) {
1117 TFile* tf = f.second.first;
1121 debug() <<
"stream: " << f.first <<
" name: " << tf->GetName() <<
" size: " << tf->GetSize() <<
endmsg;
1126 if ( tf->GetSize() > mfs ) {
1128 m_signaledStop =
true;
1130 fatal() <<
"file \"" << tf->GetName() <<
"\" associated with stream \"" << f.first
1131 <<
"\" has exceeded the max file size of " << m_maxFileSize.value() <<
"MB. Terminating Job." <<
endmsg;
1134 if ( service(
"ApplicationMgr", evt,
true ).isSuccess() ) {
1140 }
else if ( tf->GetSize() > mfs_warn ) {
1141 warning() <<
"file \"" << tf->GetName() <<
"\" associated with stream \"" << f.first
1142 <<
"\" is at 95% of its maximum allowable file size of " << m_maxFileSize.value() <<
"MB" <<
endmsg;
1152 bool all_good =
true;
1154 debug() <<
"reinitializing I/O..." <<
endmsg;
1161 if ( service(
"IoComponentMgr", iomgr,
true ).isFailure() ) {
1162 error() <<
"could not retrieve I/O component manager !" <<
endmsg;
1169 gErrorIgnoreLevel = kFatal;
1171 for (
auto& ifile : m_files ) {
1172 TFile* f = ifile.second.first;
1175 debug() <<
"file [" << fname <<
"] mode: [" << f->GetOption() <<
"] r:" << f->GetFileBytesRead()
1176 <<
" w:" << f->GetFileBytesWritten() <<
" cnt:" << f->GetFileCounter() <<
endmsg;
1179 if ( ifile.second.second ==
READ ) {
1181 debug() <<
" TFile opened in READ mode: not reassigning names" <<
endmsg;
1187 error() <<
"could not retrieve new name for [" << fname <<
"] !!" <<
endmsg;
1192 debug() <<
"got a new name [" << fname <<
"]..." <<
endmsg;
1197 Option_t*
opts = f->GetOption();
1200 error() <<
"unable to open file \"" << fname <<
"\" for writing" <<
endmsg;
1203 TFile* newfile = (TFile*)vf;
1204 newfile->SetOption( opts );
1207 copyFileLayout( newfile, f );
1208 ifile.second.first = newfile;
1212 for (
auto& uid : m_uids ) {
1213 for (
auto& hid : *uid.second ) {
1214 if ( hid.file != f )
continue;
1215 TDirectory* olddir = this->changeDir( hid );
1218 TDirectory* newdir = this->changeDir( hid );
1219 TClass* cl = hid.obj->IsA();
1223 if ( cl->InheritsFrom(
"TTree" ) ) {
1224 dynamic_cast<TTree*
>( hid.obj )->SetDirectory( newdir );
1225 dynamic_cast<TTree*
>( hid.obj )->Reset();
1226 }
else if ( cl->InheritsFrom(
"TH1" ) ) {
1227 dynamic_cast<TH1*
>( hid.obj )->SetDirectory( newdir );
1228 dynamic_cast<TH1*
>( hid.obj )->Reset();
1229 }
else if ( cl->InheritsFrom(
"TGraph" ) ) {
1230 olddir->Remove( hid.obj );
1231 newdir->Append( hid.obj );
1233 error() <<
"id: \"" << hid.id <<
"\" is not a inheriting from a class " 1234 <<
"we know how to handle (received [" << cl->GetName() <<
"], " 1235 <<
"expected [TTree, TH1 or TGraph]) !" <<
endmsg <<
"attaching to current dir [" << newdir->GetPath()
1237 <<
"nonetheless..." <<
endmsg;
1238 olddir->Remove( hid.obj );
1239 newdir->Append( hid.obj );
1243 f->ReOpen(
"READ" );
1244 p_fileMgr->close( f,
name() );
1269 template <
typename T>
1272 return dynamic_cast<T*
>( readHist_i<T>( id ) );
1287 for (
auto& hid : *( uitr->second ) ) {
1290 verbose() <<
" update: " << uitr->first <<
" " << hid.id <<
" " << hid.mode <<
endmsg;
1292 TObject* to = hid.obj;
1293 TFile* oldFile = hid.file;
1296 }
else if ( hid.temp || hid.mode ==
READ ) {
1302 }
else if ( to->IsA()->InheritsFrom(
"TTree" ) ) {
1303 TTree* tr =
dynamic_cast<TTree*
>( to );
1304 TFile* newFile = tr->GetCurrentFile();
1306 if ( oldFile != newFile ) {
1309 TFile* dummy =
nullptr;
1310 findStream( hid.id, streamName, rem, dummy );
1313 if ( itr.second.first == oldFile ) {
1314 itr.second.first = newFile;
1318 for (
auto uitr2 = uitr; uitr2 !=
m_uids.
end(); ++uitr2 ) {
1319 for (
auto& hid2 : *( uitr2->second ) ) {
1320 if ( hid2.file == oldFile ) {
1321 hid2.file = newFile;
1327 [&]( streamMap::const_reference
s ) {
return s.second == streamName; } );
1332 debug() <<
"migrating uid: " << hid.id <<
" stream: " << streamName <<
" oldFile: " << oldFileName
1333 <<
" newFile: " << newFileName <<
endmsg;
1337 if ( !oldFileName.
empty() ) {
1342 debug() <<
"changing filename \"" << i->first <<
"\" to \"" << newFileName <<
"\" for stream \"" 1343 << i->second <<
"\"" <<
endmsg;
1351 error() <<
"Problems updating fileStreams with new file name" <<
endmsg;
1364 auto mode = i.second.second;
1365 auto file = i.second.first;
1367 file->Write(
"", TObject::kOverwrite );
1368 }
else if ( mode ==
APPEND ) {
1374 debug() <<
"THistSvc::writeObjectsToFile()::List of Files connected in ROOT " <<
endmsg;
1375 TSeqCollection* filelist = gROOT->GetListOfFiles();
1376 for (
int ii = 0; ii < filelist->GetEntries(); ii++ ) {
1377 debug() <<
"THistSvc::writeObjectsToFile()::List of Files connected in ROOT: \"" << filelist->At( ii )->GetName()
1387 auto loc = ident.
find(
" " );
1395 if ( loc != std::string::npos ) {
1397 for (
auto attrib : Parser( ident.
substr( loc + 1 ) ) ) {
1398 auto TAG = boost::algorithm::to_upper_copy( attrib.tag );
1399 auto VAL = boost::algorithm::to_upper_copy( attrib.value );
1401 if ( TAG ==
"FILE" || TAG ==
"DATAFILE" ) {
1402 filename = attrib.value;
1404 }
else if ( TAG ==
"OPT" ) {
1405 if ( VAL ==
"APPEND" || VAL ==
"UPDATE" ) {
1407 }
else if ( VAL ==
"CREATE" || VAL ==
"NEW" || VAL ==
"WRITE" ) {
1409 }
else if ( VAL ==
"RECREATE" ) {
1411 }
else if ( VAL ==
"SHARE" ) {
1413 }
else if ( VAL ==
"OLD" || VAL ==
"READ" ) {
1416 error() <<
"Unknown OPT: \"" << attrib.value <<
"\"" <<
endmsg;
1419 }
else if ( TAG ==
"TYP" ) {
1421 }
else if ( TAG ==
"CL" ) {
1429 if ( stream ==
"temp" ) {
1430 error() <<
"in JobOption \"" << ident <<
"\": stream name \"temp\" reserved." <<
endmsg;
1434 if ( db_typ !=
"ROOT" ) {
1435 error() <<
"in JobOption \"" << ident <<
"\": technology type \"" << db_typ <<
"\" not supported." <<
endmsg;
1440 error() <<
"in JobOption \"" << ident <<
"\":\n stream \"" << stream <<
"\" already connected to file: \"" 1447 error() <<
"No OPT= specified or unknown access mode in: " << ident <<
endmsg;
1455 const std::string& oldstream = fitr.first->second;
1457 const auto& f_info =
m_files[oldstream];
1459 if ( newMode != f_info.second ) {
1460 error() <<
"in JobOption \"" << ident <<
"\":\n file \"" << filename <<
"\" already opened by stream: \"" 1461 << oldstream <<
"\" with different access mode." <<
endmsg;
1464 TFile* f2 = f_info.first;
1467 debug() <<
"Connecting stream: \"" << stream <<
"\" to previously opened TFile: \"" << filename <<
"\"" 1474 if (
service(
"IncidentSvc", pi ).isFailure() ) {
1475 error() <<
"Unable to get the IncidentSvc" <<
endmsg;
1487 error() <<
"Unable to open ROOT file " << filename <<
" for reading" <<
endmsg;
1501 error() <<
"Unable to open ROOT file " << filename <<
" for writing" <<
endmsg;
1511 error() <<
"unable to open file \"" << filename <<
"\" for appending" <<
endmsg;
1522 static int ishared = 0;
1524 filename =
"tmp_THistSvc_" +
std::to_string( ishared++ ) +
".root";
1527 debug() <<
"Creating temp file \"" << filename <<
"\" and realfilename=" << realfilename <<
endmsg;
1534 error() <<
"Unable to open ROOT file " << filename <<
" for writing" <<
endmsg;
1545 error() <<
"Unable to open ROOT file " << filename <<
" for appending" <<
endmsg;
1556 debug() <<
"Opening TFile \"" << filename <<
"\" stream: \"" << stream <<
"\" mode: \"" << typ <<
"\"" 1557 <<
" comp level: " << cl <<
endmsg;
1566 TFile* file = hid.
file;
1579 if ( !gDirectory->GetKey( dir.
c_str() ) ) {
1580 gDirectory->mkdir( dir.
c_str() );
1582 gDirectory->cd( dir.
c_str() );
1590 std::string::size_type i = dir.
find(
"/" );
1592 if ( i == std::string::npos )
return {};
1607 while (
id.find(
"//" ) != std::string::npos ) {
1608 id.replace(
id.find(
"//" ), 2,
"/" );
1615 debug() <<
"Target path: " << target->GetPath() <<
endmsg;
1617 TString
path( (
char*)strstr( target->GetPath(),
":" ) );
1618 path.Remove( 0, 2 );
1621 TDirectory* current_sourcedir = gDirectory;
1624 TList* lkeys = current_sourcedir->GetListOfKeys();
1625 int nkeys = lkeys->GetEntries();
1626 TKey* key =
nullptr;
1627 for (
int jj = 0; jj < nkeys; jj++ ) {
1628 key = (TKey*)lkeys->At( jj );
1631 debug() <<
"Reading Key:" << pathnameinsource <<
endmsg;
1633 TObject* obj = source->Get( pathnameinsource.
c_str() );
1636 if ( obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
1639 debug() <<
"Found subdirectory " << obj->GetName() <<
endmsg;
1644 TDirectory* newtargetdir = target->mkdir( obj->GetName(), obj->GetTitle() );
1648 }
else if ( obj->IsA()->InheritsFrom(
"TTree" ) ) {
1650 debug() <<
"Found TTree " << obj->GetName() <<
endmsg;
1652 TTree* mytree =
dynamic_cast<TTree*
>( obj );
1653 int nentries = (int)mytree->GetEntries();
1654 mytree->SetBranchStatus(
"*", 1 );
1657 debug() <<
"Dumping TTree " << nentries <<
" entries" <<
endmsg;
1660 mytree->CloneTree();
1664 obj->Write( key->GetName() );
1672 auto pos =
id.find(
"/" );
1674 if ( pos == std::string::npos ) {
1678 }
else if ( pos != 0 ) {
1685 auto pos2 =
id.
find(
"/", pos + 1 );
1687 if ( pos2 == std::string::npos ) {
1689 error() <<
"badly formed Hist/Tree id: \"" <<
id <<
"\"" <<
endmsg;
1695 if ( stream ==
"temp" ) {
1701 file = ( itr !=
m_files.
end() ? itr->second.first : nullptr );
1703 warning() <<
"no stream \"" << stream <<
"\" associated with id: \"" <<
id <<
"\"" <<
endmsg;
1711 auto pos =
id.find(
"/" );
1713 if ( pos == std::string::npos ) {
1716 }
else if ( pos == 0 ) {
1719 root =
id.
substr( 0, pos );
1720 rem =
id.
substr( pos + 1 );
1727 debug() <<
"Delaying connection of Input Files until Initialize" 1732 debug() <<
"Now connecting of Input Files" <<
endmsg;
1756 debug() <<
"Delaying connection of Input Files until Initialize" 1781 debug() <<
"copyFileLayout() to destination path: " << destination->GetPath() <<
endmsg;
1785 TString
path( (
char*)strstr( destination->GetPath(),
":" ) );
1786 path.Remove( 0, 2 );
1789 TDirectory* current_source_dir = gDirectory;
1792 TList* key_list = current_source_dir->GetListOfKeys();
1793 int n = key_list->GetEntries();
1794 for (
int j = 0; j <
n; ++j ) {
1795 TKey* k = (TKey*)key_list->At( j );
1797 TObject* o = source->Get( source_pathname.
c_str() );
1799 if ( o && o->IsA()->InheritsFrom(
"TDirectory" ) ) {
1801 verbose() <<
" subdir [" << o->GetName() <<
"]..." <<
endmsg;
1804 TDirectory* destination_dir = destination->mkdir( o->GetName(), o->GetTitle() );
1820 if ( idr.
find(
"/" ) == 0 ) {
1828 if ( index >= itr->second->size() ) {
1829 error() <<
"no index " << index <<
" found for Hist " << idr <<
endmsg;
1832 hid = &( itr->second->at( index ) );
1838 if ( mitr.first == mitr.second ) {
1841 }
else if ( distance( mitr.first, mitr.second ) == 1 ) {
1843 if ( index >= mitr.first->second->size() ) {
1844 error() <<
"no index " << index <<
" found for Hist " << idr <<
endmsg;
1847 hid = &( mitr.first->second->at( 0 ) );
1851 hid = &( mitr.first->second->at( 0 ) );
1852 return distance( mitr.first, mitr.second );
1862 ost <<
"m_hlist: size: " <<
m_hlist.
size() <<
"\n";
1864 ost <<
" - " << vh->at( 0 ) <<
" :: [" << vh <<
"] " << vh->size() <<
" {";
1865 for (
auto& e : *vh ) {
1867 ost <<
"[" << o <<
"]";
1875 for (
auto& e :
m_uids ) {
1876 ost <<
" - " << e.first <<
" [" << e.second <<
"]" <<
std::endl;
1882 for (
auto& e :
m_ids ) {
1883 ost <<
" - " << e.first <<
" [" << e.second <<
"]" <<
std::endl;
1890 TObject* o = e.first;
1891 THistID& i = e.second.first->at( e.second.second );
1892 ost <<
" - " << o <<
" -> " << i <<
std::endl;
1903 if ( vh->
size() == 1 ) {
1904 debug() <<
"merge: id: \"" << name <<
"\" is size 1. nothing to do" <<
endmsg;
1908 if ( !vh->
at( 0 ).obj->IsA()->InheritsFrom(
"TH1" ) ) {
1909 error() <<
"merge: id \"" << name <<
"\" is not a THn. Cannot merge" <<
endmsg;
1913 TList*
l =
new TList();
1914 for (
size_t i = 1; i < vh->
size(); ++i ) {
1915 debug() <<
"merge: id: \"" << name <<
"\" (" << vh->
at( i ).obj <<
") adding index " << i <<
endmsg;
1916 l->Add( vh->
at( i ).obj );
1919 TH1* t0 =
dynamic_cast<TH1*
>( vh->
at( 0 ).obj );
1921 error() <<
"merge: could not dcast " << name <<
"(" << t0 <<
") index " << 0 <<
" to TH1" <<
endmsg;
1925 Long64_t
n = t0->Merge( l );
1927 debug() <<
"merge: id: \"" << name <<
"\" merged " << n <<
" entries" <<
endmsg;
1929 for (
size_t i = 1; i < vh->
size(); ++i ) {
1930 TH1* th =
dynamic_cast<TH1*
>( vh->
at( i ).obj );
1932 debug() <<
"clearing index " << i <<
"(" << th <<
")" <<
endmsg;
1933 th->SetDirectory(
nullptr );
1936 error() <<
"merge: could not dcast " << name <<
" index " << i <<
" to TH1" <<
endmsg;
1950 if ( fa->
desc() !=
"HIST" ) {
1975 if ( fa->
desc() !=
"HIST" ) {
Parse attribute strings allowing iteration over the various attributes.
virtual StatusCode io_retrieve(IIoComponent *iocomponent, std::string &fname)=0
: retrieve the new filename for a given IIoComponent and
GlobalDirectoryRestore(THistSvcMutex_t &mut)
Helper struct that bundles the histogram ID with a mutex, TFile and TObject*.
constexpr static const auto FAILURE
StatusCode initialize() override
void MergeRootFile(TDirectory *, TDirectory *)
virtual StatusCode stopRun()=0
Schedule a stop of the current event processing.
StatusCode getGraph(const std::string &name, TGraph *&) const override
Return TGraph with given name.
This class is the FileIncident.
StatusCode initialize() override
StatusCode deReg(const std::string &name) override
Deregister object with given name and give up ownership (without deletion!)
Define general base for Gaudi exception.
virtual Io::open_t open(const Io::IoTech &, const std::string &caller, const std::string &fname, const Io::IoFlags &, Io::Fd &, void *&, const std::string &desc, const bool shared=false)=0
const std::string & name() const override
Retrieve name of the service.
TTree * readTree(const std::string &name) const
StatusCode finalize() override
StatusCode regShared(const std::string &name, std::unique_ptr< TH1 >, LockedHandle< TH1 > &) override
Register shared object of type TH1 and return LockedHandle for that object.
std::vector< std::string > getGraphs() const override
This file contains the class definition for the FileIncident class.
bool exists(const std::string &name) const override
Check if object with given name is managed by THistSvcMT.
bool findStream(const std::string &name, std::string &root, std::string &rem, TFile *&file) const
StatusCode getTHists(TDirectory *td, TList &, bool recurse=false) const override
MsgStream & verbose() const
shortcut for the method msgStream(MSG::VERBOSE)
StatusCode writeObjectsToFile()
StatusCode merge(const std::string &id) override
Merge all clones for object with a given id.
StatusCode rootOpenAction(FILEMGR_CALLBACK_ARGS)
void copyFileLayout(TDirectory *, TDirectory *)
helper function to recursively copy the layout of a TFile into a new TFile
TDirectory * changeDir(const THistSvc::THistID &hid) const
StatusCode getHist(const std::string &name, TH1 *&, size_t index=0) const override
Return histogram with given name as TH1*, THistSvcMT still owns object.
Gaudi::Property< std::vector< std::string > > m_outputfile
std::vector< std::string > getHists() const override
#define DECLARE_COMPONENT(type)
void setupOutputFile()
call-back method to handle output stream property
const std::string & name() const
void setupInputFile()
call-back method to handle input stream property
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
virtual void fireIncident(const Incident &incident)=0
Fire an Incident.
std::string stripDirectoryName(std::string &dir) const
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
const std::string & desc() const
Gaudi::Property< std::vector< std::string > > m_inputfile
Mode charToMode(const char typ)
Convert a char to a Mode enum.
This class is used for returning status codes from appropriate routines.
void clear(STATE_TYPE _i=std::ios_base::failbit)
Provides automatic lock/unlock access to a class upon deref of ptr.
void handle(const Incident &) override
StatusCode getTree(const std::string &name, TTree *&) const override
Return TTree with given name.
~GlobalDirectoryRestore()
StatusCode rootOpenErrAction(FILEMGR_CALLBACK_ARGS)
void parseString(const std::string &id, std::string &root, std::string &rem) const
StatusCode finalize() override
constexpr static const auto SUCCESS
StatusCode regHist(const std::string &name) override
Register a new ROOT histogram TH*X with a name.
StatusCode getTTrees(TDirectory *td, TList &, bool recurse=false) const override
virtual unsigned long release()=0
Release Interface instance.
StatusCode reinitialize() override
virtual Out operator()(const vector_of_const_< In > &inputs) const =0
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
T back_inserter(T...args)
Base class for all Incidents (computing events).
std::map< std::string, std::pair< TFile *, Mode > > m_files
Gaudi::StateMachine::State FSMState() const override
StatusCode connect(const std::string &)
The IEventProcessor is the interface to process events.
virtual StatusCode io_register(IIoComponent *iocomponent)=0
: allow a IIoComponent to register itself with this manager so appropriate actions can be taken when ...
std::set< std::string > m_alreadyConnectedOutFiles
list of already connected files.
StatusCode regTree(const std::string &name) override
Register a new TTree with a given name.
std::map< std::string, std::string > m_sharedFiles
size_t findHistID(const std::string &id, const THistID *&hid, const size_t &index=0) const
StatusCode service(const std::string &name, const T *&psvc, bool createIf=true) const
Access a service by name, creating it if it doesn't already exist.
std::vector< std::string > getTrees() const override
StatusCode getShared(const std::string &name, LockedHandle< TH1 > &) const override
Retrieve shared object with given name as TH1 through LockedHandle.
AttribStringParser::Iterator begin(const AttribStringParser &parser)
std::set< std::string > m_alreadyConnectedInFiles
list of already connected files.
StatusCode regGraph(const std::string &name) override
Register a new TGraph with a given name.
StatusCode io_reinit() override
callback method to reinitialize the internal state of the component for I/O purposes (e...
Helper class that manages ROOts global directory and file.
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
TDirectory * m_gDirectory
The interface implemented by the IncidentSvc service.
T * readHist(const std::string &name) const
void removeDoubleSlash(std::string &) const
void updateFiles()
Handle case where TTree grows beyond TTree::fgMaxTreeSize.
MSG::Level msgLevel() const
get the cached level (originally extracted from the embedded MsgStream)