7 #include "boost/algorithm/string/case_conv.hpp" 10 #include "TDirectory.h" 35 template <
typename InputIterator,
typename OutputIterator,
typename UnaryOperation,
typename UnaryPredicate>
36 OutputIterator transform_if( InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op,
37 UnaryPredicate pred ) {
38 while ( first != last ) {
39 if ( pred( *first ) ) *result++ = op( *first );
45 constexpr
struct select1st_t {
46 template <
typename T,
typename S>
61 error() <<
"initializing service" <<
endmsg;
70 error() <<
"Caught: " << err <<
endmsg;
77 error() <<
"Caught: " << err <<
endmsg;
83 static TROOT
root(
"root",
"ROOT I/O" );
89 if ( service(
"IncidentSvc", p_incSvc,
true ).isFailure() ) {
90 error() <<
"unable to get the IncidentSvc" <<
endmsg;
93 p_incSvc->addListener(
this,
"EndEvent", 100,
true );
96 if ( service(
"FileMgr", p_fileMgr,
true ).isFailure() ) {
97 error() <<
"unable to get the FileMgr" <<
endmsg;
100 debug() <<
"got the FileMgr" <<
endmsg;
105 auto boa = [
this](
const Io::FileAttr* fa,
const std::string& caller ) {
return this->rootOpenAction( fa, caller ); };
107 error() <<
"unable to register ROOT file open action with FileMgr" <<
endmsg;
110 return this->rootOpenErrAction( fa, caller );
113 error() <<
"unable to register ROOT file open Error action with FileMgr" <<
endmsg;
116 m_okToConnect =
true;
117 if ( m_delayConnect ) {
118 if ( !m_inputfile.value().empty() ) setupInputFile();
119 if ( !m_outputfile.value().empty() ) setupOutputFile();
120 m_delayConnect =
false;
122 m_alreadyConnectedOutFiles.
clear();
123 m_alreadyConnectedInFiles.clear();
126 if ( service(
"IoComponentMgr", iomgr,
true ).isFailure() ) {
127 error() <<
"unable to get the IoComponentMgr" <<
endmsg;
131 error() <<
"could not register with the I/O component manager !" <<
endmsg;
134 bool all_good =
true;
136 for (
const auto& reg : m_files ) {
137 const std::string& fname = reg.second.first->GetName();
141 warning() <<
"could not register file [" << fname <<
"] with the I/O component manager..." <<
endmsg;
144 info() <<
"registered file [" << fname <<
"]... [ok]" <<
endmsg;
148 error() <<
"problem while registering input/output files with " 149 <<
"the I/O component manager !" <<
endmsg;
155 if ( st.
isFailure() ) { fatal() <<
"Unable to initialize THistSvc" <<
endmsg; }
162 warning() <<
"reinitialize not implemented" <<
endmsg;
171 debug() <<
"THistSvc::finalize" <<
endmsg;
177 for (
const auto& itr : sorted_uids ) {
178 THistID& thid = itr.second->at( 0 );
179 TObject* tobj = thid.
obj;
182 if ( tobj && tobj->IsA()->InheritsFrom(
"TTree" ) ) {
183 TTree* tree =
dynamic_cast<TTree*
>( tobj );
184 if ( tree->GetDirectory() != 0 ) { dirname = tree->GetDirectory()->GetPath(); }
185 }
else if ( tobj && tobj->IsA()->InheritsFrom(
"TGraph" ) ) {
187 dirname = thid.
file->GetPath();
191 if ( id2.
find(
"/" ) == 0 ) { id2.
erase( 0, 1 ); }
196 }
else if ( tobj && tobj->IsA()->InheritsFrom(
"TH1" ) ) {
197 TH1* th =
dynamic_cast<TH1*
>( tobj );
198 if ( th ==
nullptr ) {
199 error() <<
"Couldn't dcast: " << itr.first <<
endmsg;
201 if ( th->GetDirectory() != 0 ) { dirname = th->GetDirectory()->GetPath(); }
203 }
else if ( !tobj ) {
204 warning() << itr.first <<
" has NULL TObject ptr" <<
endmsg;
206 debug() <<
"finalize: " << thid <<
endmsg;
211 if ( writeObjectsToFile().isFailure() ) { error() <<
"problems writing histograms" <<
endmsg; }
213 if ( m_print ) { info() <<
"Listing contents of ROOT files: " <<
endmsg; }
215 for (
auto& itr : m_files ) {
216 if (
std::find( deleted_files.
begin(), deleted_files.
end(), itr.second.first ) == deleted_files.
end() ) {
217 deleted_files.
push_back( itr.second.first );
221 debug() <<
"finalizing stream/file " << itr.first <<
":" << itr.second.first->GetName() <<
endmsg;
226 if ( msgLevel(
MSG::DEBUG ) ) { debug() <<
"already finalized stream " << itr.first <<
endmsg; }
231 if ( m_print && msgLevel(
MSG::INFO ) ) {
232 info() <<
"==> File: " << itr.second.first->GetName() <<
" stream: " << itr.first <<
endmsg;
234 itr.second.first->Print(
"base" );
239 p_fileMgr->close( itr.second.first,
name() );
242 if ( service(
"IncidentSvc", pIncidentSvc ).isFailure() ) {
243 error() <<
"Unable to get the IncidentSvc" <<
endmsg;
247 if ( itr.second.second == SHARE ) {
249 void* vfile =
nullptr;
254 error() <<
"unable to open Final Output File: \"" << m_sharedFiles[itr.first] <<
"\" for merging" <<
endmsg;
258 TFile* outputfile = (TFile*)vfile;
261 if ( msgLevel(
MSG::DEBUG ) ) { debug() <<
"THistSvc::writeObjectsToFile()::Merging Rootfile " <<
endmsg; }
267 error() <<
"unable to open temporary file: \"" << tmpfn <<
endmsg;
271 TFile* inputfile = (TFile*)vfile;
273 outputfile->SetCompressionLevel( inputfile->GetCompressionLevel() );
275 MergeRootFile( outputfile, inputfile );
278 p_fileMgr->close( outputfile,
name() );
279 p_fileMgr->close( inputfile,
name() );
281 if ( msgLevel(
MSG::DEBUG ) ) { debug() <<
"Trying to remove temporary file \"" << tmpfn <<
"\"" <<
endmsg; }
285 delete itr.second.first;
289 m_sharedFiles.clear();
290 m_fileStreams.clear();
295 for (
auto& obj : m_tobjs ) {
297 delete obj.second.first;
308 return regHist_i(
std::move( hist ),
id,
false );
312 return regHist_i(
std::move( hist ),
id,
false );
317 if ( hist_ptr !=
nullptr ) { hist_ptr = hist.
get(); }
318 return regHist_i(
std::move( hist ),
id,
false );
323 return regHist_i(
std::move( hist ),
id,
false );
327 hist = getHist_i<TH1>( id, ind );
328 if ( hist !=
nullptr ) {
336 hist = getHist_i<TH2>( id, ind );
337 if ( hist !=
nullptr ) {
345 hist = getHist_i<TH3>( id, ind );
346 if ( hist !=
nullptr ) {
355 return regHist_i(
std::move( tree ),
id,
false );
361 if ( getTree(
id, tr ).isSuccess() && sc.
isSuccess() ) {
362 if ( m_autoSave != 0 ) { tr->SetAutoSave( m_autoSave ); }
363 tr->SetAutoFlush( m_autoFlush );
372 if ( getTree(
id, tr ).isSuccess() && sc.
isSuccess() ) {
373 if ( m_autoSave != 0 ) { tr->SetAutoSave( m_autoSave ); }
374 tr->SetAutoFlush( m_autoFlush );
380 tree = getHist_i<TTree>( id );
381 if ( tree !=
nullptr ) {
390 return regHist_i(
std::move( graph ),
id,
false );
394 if ( strcmp( graph->GetName(),
"Graph" ) == 0 ) {
396 std::string::size_type i = id2.
rfind(
"/" );
397 if ( i != std::string::npos ) { id2.
erase( 0, i + 1 ); }
399 info() <<
"setting name of TGraph id: \"" <<
id <<
"\" to \"" << id2 <<
"\" since it is unset" <<
endmsg;
400 graph->SetName( id2.
c_str() );
403 return regHist_i(
std::move( graph ),
id,
false );
408 if ( strcmp( graph->GetName(),
"Graph" ) == 0 ) {
410 std::string::size_type i = id2.
rfind(
"/" );
411 if ( i != std::string::npos ) { id2.
erase( 0, i + 1 ); }
413 info() <<
"setting name of TGraph id: \"" <<
id <<
"\" to \"" << id2 <<
"\" since it is unset" <<
endmsg;
414 graph->SetName( id2.
c_str() );
417 return regHist_i(
std::move( graph ),
id,
false );
421 graph = getHist_i<TGraph>( id );
422 if ( graph !=
nullptr ) {
430 lh = regShared_i<TH1>( id,
std::move( hist ) );
439 lh = regShared_i<TH2>( id,
std::move( hist ) );
448 lh = regShared_i<TH3>( id,
std::move( hist ) );
457 lh = regShared_i<TGraph>( id,
std::move( graph ) );
466 lh = getShared_i<TH1>(
name );
475 lh = getShared_i<TH2>(
name );
484 lh = getShared_i<TH3>(
name );
493 lh = getShared_i<TGraph>(
name );
502 auto itr = m_uids.find(
id );
503 if ( itr == m_uids.end() ) {
504 error() <<
"Problem deregistering id \"" <<
id <<
"\": not found in registry" <<
endmsg;
509 debug() <<
"will deregister " << vh->
size() <<
" elements of id \"" <<
id <<
"\"" <<
endmsg;
512 size_t vh_size = vh->
size();
513 while ( vh_size-- ) {
514 if ( deReg( vh->
back().obj ).isFailure() ) {
516 error() <<
"Problems deRegistering " << vh->
size() <<
" element of id \"" <<
id <<
"\"" <<
endmsg;
525 objMap_t::iterator obj_itr = m_tobjs.find( obj );
526 if ( obj_itr != m_tobjs.end() ) {
527 vhid_t* vhid = obj_itr->second.first;
528 THistID hid = obj_itr->second.first->at( obj_itr->second.second );
530 auto uid_itr = m_uids.find( hid.
id );
531 if ( uid_itr == m_uids.end() ) {
532 error() <<
"Problems deregistering TObject \"" << obj->GetName() <<
"\" with id \"" << hid.
id 533 <<
"\": not in uidMap" <<
endmsg;
537 if ( vhid->
size() == 1 ) {
539 debug() <<
"vhid for " << hid.
id <<
" is empty. deleting" <<
endmsg;
542 parseString( hid.
id, root, rem );
544 auto mitr = m_ids.equal_range( rem );
546 [&]( idMap_t::const_reference i ) { return i.second->at( 0 ).obj == obj; } );
547 if ( id_itr == mitr.second ) {
548 error() <<
"Problems deregistering TObject \"" << obj->GetName() <<
"\" with id \"" << hid.
id 549 <<
"\": not in idMap" <<
endmsg;
553 auto hlist_itr =
std::find( m_hlist.begin(), m_hlist.end(), vhid );
554 if ( hlist_itr == m_hlist.end() ) {
555 error() <<
"Problems deregistering TObject \"" << obj->GetName() <<
"\" with id \"" << hid.
id 556 <<
"\": not in hlist" <<
endmsg;
560 vhid->
erase( vhid->
begin() + obj_itr->second.second );
561 m_tobjs.erase( obj_itr );
563 m_uids.erase( uid_itr );
564 m_ids.erase( id_itr );
565 m_hlist.erase( hlist_itr );
569 }
else if ( vhid->
size() > 1 ) {
570 m_tobjs.
erase( obj_itr );
571 vhid->
erase( vhid->
begin() + obj_itr->second.second );
575 error() <<
"Deregistration failed unexpectedly. (bug in THistSvc?)" <<
endmsg;
579 error() <<
"Cannot unregister TObject \"" << obj->GetName() <<
"\": not known to THistSvc" <<
endmsg;
585 uidMap_t::iterator itr = m_uids.find( name );
586 if ( itr == m_uids.end() ) {
587 error() <<
"merge: id \"" << name <<
"\" not found" <<
endmsg;
591 return merge( itr->second );
595 objMap_t::iterator itr = m_tobjs.find( obj );
596 if ( itr != m_tobjs.end() ) {
597 return merge( itr->second.first );
599 error() <<
"merge: unknown object " << obj <<
endmsg;
608 names.
reserve( m_uids.size() );
610 []( uidMap_t::const_reference i ) {
return i.second->at( 0 ).obj->IsA()->InheritsFrom(
"TH1" ); } );
616 names.
reserve( m_uids.size() );
618 []( uidMap_t::const_reference i ) {
return i.second->at( 0 ).obj->IsA()->InheritsFrom(
"TTree" ); } );
624 names.
reserve( m_uids.size() );
626 []( uidMap_t::const_reference i ) {
return i.second->at( 0 ).obj->IsA()->InheritsFrom(
"TGraph" ); } );
633 gErrorIgnoreLevel = kBreak;
636 error() <<
"getTHists: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
641 debug() <<
"getTHists: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys" <<
endmsg;
644 TIter nextkey( td->GetListOfKeys() );
645 while ( TKey* key = (TKey*)nextkey() ) {
647 if ( msgLevel(
MSG::DEBUG ) )
log <<
" key: " << key->GetName();
648 TObject* obj = key->ReadObj();
649 if ( obj != 0 && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
650 if ( msgLevel(
MSG::DEBUG ) )
log <<
" (" << obj->IsA()->GetName() <<
")";
651 }
else if ( obj != 0 && obj->IsA()->InheritsFrom(
"TH1" ) ) {
652 if ( msgLevel(
MSG::DEBUG ) )
log <<
" (" << obj->IsA()->GetName() <<
")";
654 }
else if ( obj != 0 ) {
655 if ( msgLevel(
MSG::DEBUG ) )
log <<
" [" << obj->IsA()->GetName() <<
"]";
662 nextkey = td->GetListOfKeys();
663 while ( TKey* key = (TKey*)nextkey() ) {
664 TObject* obj = key->ReadObj();
665 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
666 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
667 getTHists( tt, tl, rcs );
679 gErrorIgnoreLevel = kBreak;
684 parseString( dir, stream, rem );
686 auto itr = m_files.find( stream );
687 if ( itr != m_files.end() ) {
688 r2 = itr->second.first->GetName();
693 debug() <<
"getTHists: \"" << dir <<
"\" looks like a stream name." 694 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
697 if ( gDirectory->cd( r2.
c_str() ) ) {
698 m_curstream = stream;
699 sc = getTHists( gDirectory, tl, rcs );
703 if ( msgLevel(
MSG::DEBUG ) ) { debug() <<
"getTHists: no such TDirectory \"" << r2 <<
"\"" <<
endmsg; }
707 if ( msgLevel(
MSG::DEBUG ) ) { debug() <<
"getTHists: stream \"" << stream <<
"\" not found" <<
endmsg; }
710 if ( !gDirectory->cd( dir.
c_str() ) ) {
711 error() <<
"getTHists: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
714 sc = getTHists( gDirectory, tl, rcs );
723 gErrorIgnoreLevel = kBreak;
726 error() <<
"getTHists: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
731 debug() <<
"getTHists: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys" <<
endmsg;
734 TIter nextkey( td->GetListOfKeys() );
735 while ( TKey* key = (TKey*)nextkey() ) {
737 if ( msgLevel(
MSG::DEBUG ) )
log <<
" key: " << key->GetName();
738 TObject* obj = key->ReadObj();
739 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
740 if ( msgLevel(
MSG::DEBUG ) )
log <<
" (" << obj->IsA()->GetName() <<
")";
741 }
else if ( obj && obj->IsA()->InheritsFrom(
"TH1" ) ) {
742 if ( msgLevel(
MSG::DEBUG ) )
log <<
" (" << obj->IsA()->GetName() <<
")";
744 if ( reg && m_curstream !=
"" ) {
750 id =
id +
"/" + key->GetName();
752 id =
id + dir +
"/" + key->GetName();
754 if ( !exists(
id ) ) {
755 if ( msgLevel(
MSG::DEBUG ) )
log <<
" reg as \"" <<
id <<
"\"";
756 regHist(
id ).ignore();
762 if ( msgLevel(
MSG::DEBUG ) )
log <<
" [" << obj->IsA()->GetName() <<
"]";
769 nextkey = td->GetListOfKeys();
770 while ( TKey* key = (TKey*)nextkey() ) {
771 TObject* obj = key->ReadObj();
772 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
773 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
774 getTHists( tt, tl, rcs, reg );
785 gErrorIgnoreLevel = kBreak;
790 parseString( dir, stream, rem );
792 auto itr = m_files.find( stream );
793 if ( itr != m_files.end() ) {
794 r2 = itr->second.first->GetName();
799 debug() <<
"getTHists: \"" << dir <<
"\" looks like a stream name." 800 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
803 if ( gDirectory->cd( r2.
c_str() ) ) {
804 m_curstream = stream;
805 sc = getTHists( gDirectory, tl, rcs, reg );
809 if ( msgLevel(
MSG::DEBUG ) ) { debug() <<
"getTHists: no such TDirectory \"" << r2 <<
"\"" <<
endmsg; }
811 if ( msgLevel(
MSG::DEBUG ) ) { debug() <<
"getTHists: stream \"" << stream <<
"\" not found" <<
endmsg; }
814 if ( !gDirectory->cd( dir.
c_str() ) ) {
815 error() <<
"getTHists: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
819 warning() <<
"Unable to register histograms automatically " 820 <<
"without a valid stream name" <<
endmsg;
823 sc = getTHists( gDirectory, tl, rcs, reg );
832 gErrorIgnoreLevel = kBreak;
835 error() <<
"getTTrees: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
840 debug() <<
"getTHists: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys" <<
endmsg;
843 TIter nextkey( td->GetListOfKeys() );
844 while ( TKey* key = (TKey*)nextkey() ) {
846 if ( msgLevel(
MSG::DEBUG ) )
log <<
" key: " << key->GetName();
847 TObject* obj = key->ReadObj();
848 if ( obj != 0 && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
849 if ( msgLevel(
MSG::DEBUG ) )
log <<
" (" << obj->IsA()->GetName() <<
")";
850 }
else if ( obj != 0 && obj->IsA()->InheritsFrom(
"TTree" ) ) {
851 if ( msgLevel(
MSG::DEBUG ) )
log <<
" (" << obj->IsA()->GetName() <<
")";
853 }
else if ( obj != 0 ) {
854 if ( msgLevel(
MSG::DEBUG ) )
log <<
" [" << obj->IsA()->GetName() <<
"]";
861 nextkey = td->GetListOfKeys();
862 while ( TKey* key = (TKey*)nextkey() ) {
863 TObject* obj = key->ReadObj();
864 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
865 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
866 getTTrees( tt, tl, rcs );
877 gErrorIgnoreLevel = kBreak;
882 parseString( dir, stream, rem );
884 auto itr = m_files.find( stream );
885 if ( itr != m_files.end() ) {
886 r2 = itr->second.first->GetName();
891 debug() <<
"getTTrees: \"" << dir <<
"\" looks like a stream name." 892 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
895 if ( gDirectory->cd( r2.
c_str() ) ) {
return getTTrees( gDirectory, tl, rcs ); }
896 if ( msgLevel(
MSG::DEBUG ) ) { debug() <<
"getTTrees: no such TDirectory \"" << r2 <<
"\"" <<
endmsg; }
898 if ( msgLevel(
MSG::DEBUG ) ) { debug() <<
"getTTrees: stream \"" << stream <<
"\" not found" <<
endmsg; }
901 if ( !gDirectory->cd( dir.
c_str() ) ) {
902 error() <<
"getTTrees: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
905 sc = getTTrees( gDirectory, tl, rcs );
913 gErrorIgnoreLevel = kBreak;
916 error() <<
"getTTrees: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
921 debug() <<
"getTHists: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys" <<
endmsg;
924 TIter nextkey( td->GetListOfKeys() );
925 while ( TKey* key = (TKey*)nextkey() ) {
927 if ( msgLevel(
MSG::DEBUG ) )
log <<
" key: " << key->GetName();
928 TObject* obj = key->ReadObj();
929 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
930 if ( msgLevel(
MSG::DEBUG ) )
log <<
" (" << obj->IsA()->GetName() <<
")";
931 }
else if ( obj && obj->IsA()->InheritsFrom(
"TTree" ) ) {
932 if ( msgLevel(
MSG::DEBUG ) )
log <<
" (" << obj->IsA()->GetName() <<
")";
934 if ( reg && m_curstream !=
"" ) {
940 id =
id +
"/" + key->GetName();
942 id =
id + dir +
"/" + key->GetName();
944 if ( !exists(
id ) ) {
945 if ( msgLevel(
MSG::DEBUG ) )
log <<
" reg as \"" <<
id <<
"\"";
946 regHist(
id ).ignore();
951 }
else if ( obj != 0 ) {
952 if ( msgLevel(
MSG::DEBUG ) )
log <<
" [" << obj->IsA()->GetName() <<
"]";
959 nextkey = td->GetListOfKeys();
960 while ( TKey* key = (TKey*)nextkey() ) {
961 TObject* obj = key->ReadObj();
962 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
963 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
964 getTTrees( tt, tl, rcs, reg );
975 gErrorIgnoreLevel = kBreak;
980 parseString( dir, stream, rem );
982 auto itr = m_files.find( stream );
983 if ( itr != m_files.end() ) {
984 r2 = itr->second.first->GetName();
989 debug() <<
"getTTrees: \"" << dir <<
"\" looks like a stream name." 990 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
993 if ( gDirectory->cd( r2.
c_str() ) ) {
994 return getTTrees( gDirectory, tl, rcs, reg );
996 if ( msgLevel(
MSG::DEBUG ) ) { debug() <<
"getTTrees: no such TDirectory \"" << r2 <<
"\"" <<
endmsg; }
999 if ( msgLevel(
MSG::DEBUG ) ) { debug() <<
"getTTrees: stream \"" << stream <<
"\" not found" <<
endmsg; }
1002 if ( !gDirectory->cd( dir.
c_str() ) ) {
1003 error() <<
"getTTrees: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
1007 return getTTrees( gDirectory, tl, rcs, reg );
1013 if ( m_signaledStop )
return;
1015 if ( m_maxFileSize.value() == -1 )
return;
1018 Long64_t mfs = (Long64_t)m_maxFileSize.value() * (Long64_t)1048576;
1019 Long64_t mfs_warn = mfs * 95 / 100;
1023 for (
const auto& f : m_files ) {
1024 TFile* tf = f.second.first;
1028 debug() <<
"stream: " << f.first <<
" name: " << tf->GetName() <<
" size: " << tf->GetSize() <<
endmsg;
1033 if ( tf->GetSize() > mfs ) {
1035 m_signaledStop =
true;
1037 fatal() <<
"file \"" << tf->GetName() <<
"\" associated with stream \"" << f.first
1038 <<
"\" has exceeded the max file size of " << m_maxFileSize.value() <<
"MB. Terminating Job." <<
endmsg;
1041 if ( service(
"ApplicationMgr", evt,
true ).isSuccess() ) {
1047 }
else if ( tf->GetSize() > mfs_warn ) {
1048 warning() <<
"file \"" << tf->GetName() <<
"\" associated with stream \"" << f.first
1049 <<
"\" is at 95% of its maximum allowable file size of " << m_maxFileSize.value() <<
"MB" <<
endmsg;
1058 bool all_good =
true;
1059 if ( msgLevel(
MSG::DEBUG ) ) { debug() <<
"reinitializing I/O..." <<
endmsg; }
1065 if ( service(
"IoComponentMgr", iomgr,
true ).isFailure() ) {
1066 error() <<
"could not retrieve I/O component manager !" <<
endmsg;
1073 gErrorIgnoreLevel = kFatal;
1075 for (
auto& ifile : m_files ) {
1076 TFile* f = ifile.second.first;
1079 debug() <<
"file [" << fname <<
"] mode: [" << f->GetOption() <<
"] r:" << f->GetFileBytesRead()
1080 <<
" w:" << f->GetFileBytesWritten() <<
" cnt:" << f->GetFileCounter() <<
endmsg;
1083 if ( ifile.second.second ==
READ ) {
1084 if ( msgLevel(
MSG::DEBUG ) ) { debug() <<
" TFile opened in READ mode: not reassigning names" <<
endmsg; }
1088 if ( !iomgr->
io_retrieve(
this, fname ).isSuccess() ) {
1089 error() <<
"could not retrieve new name for [" << fname <<
"] !!" <<
endmsg;
1093 if ( msgLevel(
MSG::DEBUG ) ) { debug() <<
"got a new name [" << fname <<
"]..." <<
endmsg; }
1097 Option_t*
opts = f->GetOption();
1100 error() <<
"unable to open file \"" << fname <<
"\" for writing" <<
endmsg;
1103 TFile* newfile = (TFile*)vf;
1104 newfile->SetOption( opts );
1107 copyFileLayout( newfile, f );
1108 ifile.second.first = newfile;
1112 for (
auto& uid : m_uids ) {
1113 for (
auto& hid : *uid.second ) {
1114 if ( hid.file != f )
continue;
1115 TDirectory* olddir = this->changeDir( hid );
1118 TDirectory* newdir = this->changeDir( hid );
1119 TClass* cl = hid.obj->IsA();
1123 if ( cl->InheritsFrom(
"TTree" ) ) {
1124 dynamic_cast<TTree*
>( hid.obj )->SetDirectory( newdir );
1125 dynamic_cast<TTree*
>( hid.obj )->Reset();
1126 }
else if ( cl->InheritsFrom(
"TH1" ) ) {
1127 dynamic_cast<TH1*
>( hid.obj )->SetDirectory( newdir );
1128 dynamic_cast<TH1*
>( hid.obj )->Reset();
1129 }
else if ( cl->InheritsFrom(
"TGraph" ) ) {
1130 olddir->Remove( hid.obj );
1131 newdir->Append( hid.obj );
1133 error() <<
"id: \"" << hid.id <<
"\" is not a inheriting from a class " 1134 <<
"we know how to handle (received [" << cl->GetName() <<
"], " 1135 <<
"expected [TTree, TH1 or TGraph]) !" <<
endmsg <<
"attaching to current dir [" << newdir->GetPath()
1137 <<
"nonetheless..." <<
endmsg;
1138 olddir->Remove( hid.obj );
1139 newdir->Append( hid.obj );
1143 f->ReOpen(
"READ" );
1144 p_fileMgr->close( f,
name() );
1167 template <
typename T>
1169 return dynamic_cast<T*
>( readHist_i<T>( id ) );
1183 for (
auto& hid : *( uitr->second ) ) {
1186 verbose() <<
" update: " << uitr->first <<
" " << hid.id <<
" " << hid.mode <<
endmsg;
1188 TObject* to = hid.obj;
1189 TFile* oldFile = hid.file;
1192 }
else if ( hid.temp || hid.mode ==
READ ) {
1198 }
else if ( to->IsA()->InheritsFrom(
"TTree" ) ) {
1199 TTree* tr =
dynamic_cast<TTree*
>( to );
1200 TFile* newFile = tr->GetCurrentFile();
1202 if ( oldFile != newFile ) {
1205 TFile* dummy =
nullptr;
1206 findStream( hid.id, streamName, rem, dummy );
1209 if ( itr.second.first == oldFile ) { itr.second.first = newFile; }
1212 for (
auto uitr2 = uitr; uitr2 !=
m_uids.
end(); ++uitr2 ) {
1213 for (
auto& hid2 : *( uitr2->second ) ) {
1214 if ( hid2.file == oldFile ) { hid2.file = newFile; }
1219 [&]( streamMap::const_reference
s ) {
return s.second == streamName; } );
1224 debug() <<
"migrating uid: " << hid.id <<
" stream: " << streamName <<
" oldFile: " << oldFileName
1225 <<
" newFile: " << newFileName <<
endmsg;
1229 if ( !oldFileName.
empty() ) {
1234 debug() <<
"changing filename \"" << i->first <<
"\" to \"" << newFileName <<
"\" for stream \"" 1235 << i->second <<
"\"" <<
endmsg;
1243 error() <<
"Problems updating fileStreams with new file name" <<
endmsg;
1255 auto mode = i.second.second;
1256 auto file = i.second.first;
1258 file->Write(
"", TObject::kOverwrite );
1259 }
else if ( mode ==
APPEND ) {
1265 debug() <<
"THistSvc::writeObjectsToFile()::List of Files connected in ROOT " <<
endmsg;
1266 TSeqCollection* filelist = gROOT->GetListOfFiles();
1267 for (
int ii = 0; ii < filelist->GetEntries(); ii++ ) {
1268 debug() <<
"THistSvc::writeObjectsToFile()::List of Files connected in ROOT: \"" << filelist->At( ii )->GetName()
1277 auto loc = ident.
find(
" " );
1285 if ( loc != std::string::npos ) {
1287 for (
auto attrib : Parser( ident.
substr( loc + 1 ) ) ) {
1288 auto TAG = boost::algorithm::to_upper_copy( attrib.tag );
1289 auto VAL = boost::algorithm::to_upper_copy( attrib.value );
1291 if ( TAG ==
"FILE" || TAG ==
"DATAFILE" ) {
1292 filename = attrib.value;
1294 }
else if ( TAG ==
"OPT" ) {
1295 if ( VAL ==
"APPEND" || VAL ==
"UPDATE" ) {
1297 }
else if ( VAL ==
"CREATE" || VAL ==
"NEW" || VAL ==
"WRITE" ) {
1299 }
else if ( VAL ==
"RECREATE" ) {
1301 }
else if ( VAL ==
"SHARE" ) {
1303 }
else if ( VAL ==
"OLD" || VAL ==
"READ" ) {
1306 error() <<
"Unknown OPT: \"" << attrib.value <<
"\"" <<
endmsg;
1309 }
else if ( TAG ==
"TYP" ) {
1311 }
else if ( TAG ==
"CL" ) {
1319 if ( stream ==
"temp" ) {
1320 error() <<
"in JobOption \"" << ident <<
"\": stream name \"temp\" reserved." <<
endmsg;
1324 if ( db_typ !=
"ROOT" ) {
1325 error() <<
"in JobOption \"" << ident <<
"\": technology type \"" << db_typ <<
"\" not supported." <<
endmsg;
1330 error() <<
"in JobOption \"" << ident <<
"\":\n stream \"" << stream <<
"\" already connected to file: \"" 1337 error() <<
"No OPT= specified or unknown access mode in: " << ident <<
endmsg;
1345 const std::string& oldstream = fitr.first->second;
1347 const auto& f_info =
m_files[oldstream];
1349 if ( newMode != f_info.second ) {
1350 error() <<
"in JobOption \"" << ident <<
"\":\n file \"" << filename <<
"\" already opened by stream: \"" 1351 << oldstream <<
"\" with different access mode." <<
endmsg;
1354 TFile* f2 = f_info.first;
1357 debug() <<
"Connecting stream: \"" << stream <<
"\" to previously opened TFile: \"" << filename <<
"\"" 1364 if (
service(
"IncidentSvc", pi ).isFailure() ) {
1365 error() <<
"Unable to get the IncidentSvc" <<
endmsg;
1377 error() <<
"Unable to open ROOT file " << filename <<
" for reading" <<
endmsg;
1391 error() <<
"Unable to open ROOT file " << filename <<
" for writing" <<
endmsg;
1401 error() <<
"unable to open file \"" << filename <<
"\" for appending" <<
endmsg;
1412 static int ishared = 0;
1414 filename =
"tmp_THistSvc_" +
std::to_string( ishared++ ) +
".root";
1417 debug() <<
"Creating temp file \"" << filename <<
"\" and realfilename=" << realfilename <<
endmsg;
1424 error() <<
"Unable to open ROOT file " << filename <<
" for writing" <<
endmsg;
1435 error() <<
"Unable to open ROOT file " << filename <<
" for appending" <<
endmsg;
1446 debug() <<
"Opening TFile \"" << filename <<
"\" stream: \"" << stream <<
"\" mode: \"" << typ <<
"\"" 1447 <<
" comp level: " << cl <<
endmsg;
1455 TFile* file = hid.
file;
1468 if ( !gDirectory->GetKey( dir.
c_str() ) ) { gDirectory->mkdir( dir.
c_str() ); }
1469 gDirectory->cd( dir.
c_str() );
1476 std::string::size_type i = dir.
find(
"/" );
1478 if ( i == std::string::npos )
return {};
1492 while (
id.find(
"//" ) != std::string::npos ) {
id.replace(
id.find(
"//" ), 2,
"/" ); }
1497 TString
path( (
char*)strstr( target->GetPath(),
":" ) );
1498 path.Remove( 0, 2 );
1501 TDirectory* current_sourcedir = gDirectory;
1504 TList* lkeys = current_sourcedir->GetListOfKeys();
1505 int nkeys = lkeys->GetEntries();
1506 TKey* key =
nullptr;
1507 for (
int jj = 0; jj < nkeys; jj++ ) {
1508 key = (TKey*)lkeys->At( jj );
1511 TObject* obj = source->Get( pathnameinsource.
c_str() );
1514 if ( obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
1520 TDirectory* newtargetdir = target->mkdir( obj->GetName(), obj->GetTitle() );
1524 }
else if ( obj->IsA()->InheritsFrom(
"TTree" ) ) {
1526 TTree* mytree =
dynamic_cast<TTree*
>( obj );
1527 int nentries = (int)mytree->GetEntries();
1528 mytree->SetBranchStatus(
"*", 1 );
1532 mytree->CloneTree();
1536 obj->Write( key->GetName() );
1543 auto pos =
id.find(
"/" );
1545 if ( pos == std::string::npos ) {
1549 }
else if ( pos != 0 ) {
1556 auto pos2 =
id.
find(
"/", pos + 1 );
1558 if ( pos2 == std::string::npos ) {
1560 error() <<
"badly formed Hist/Tree id: \"" <<
id <<
"\"" <<
endmsg;
1566 if ( stream ==
"temp" ) {
1572 file = ( itr !=
m_files.
end() ? itr->second.first : nullptr );
1573 if ( !file ) {
warning() <<
"no stream \"" << stream <<
"\" associated with id: \"" <<
id <<
"\"" <<
endmsg; }
1579 auto pos =
id.find(
"/" );
1581 if ( pos == std::string::npos ) {
1584 }
else if ( pos == 0 ) {
1587 root =
id.
substr( 0, pos );
1588 rem =
id.
substr( pos + 1 );
1594 debug() <<
"Delaying connection of Input Files until Initialize" 1599 debug() <<
"Now connecting of Input Files" <<
endmsg;
1618 debug() <<
"Delaying connection of Input Files until Initialize" 1638 debug() <<
"copyFileLayout() to destination path: " << destination->GetPath() <<
endmsg;
1642 TString
path( (
char*)strstr( destination->GetPath(),
":" ) );
1643 path.Remove( 0, 2 );
1646 TDirectory* current_source_dir = gDirectory;
1649 TList* key_list = current_source_dir->GetListOfKeys();
1650 int n = key_list->GetEntries();
1651 for (
int j = 0; j <
n; ++j ) {
1652 TKey* k = (TKey*)key_list->At( j );
1654 TObject* o = source->Get( source_pathname.
c_str() );
1656 if ( o && o->IsA()->InheritsFrom(
"TDirectory" ) ) {
1659 TDirectory* destination_dir = destination->mkdir( o->GetName(), o->GetTitle() );
1674 if ( idr.
find(
"/" ) == 0 ) {
1682 if ( index >= itr->second->size() ) {
1683 error() <<
"no index " << index <<
" found for Hist " << idr <<
endmsg;
1686 hid = &( itr->second->at( index ) );
1692 if ( mitr.first == mitr.second ) {
1695 }
else if ( distance( mitr.first, mitr.second ) == 1 ) {
1697 if ( index >= mitr.first->second->size() ) {
1698 error() <<
"no index " << index <<
" found for Hist " << idr <<
endmsg;
1701 hid = &( mitr.first->second->at( 0 ) );
1705 hid = &( mitr.first->second->at( 0 ) );
1706 return distance( mitr.first, mitr.second );
1715 ost <<
"m_hlist: size: " <<
m_hlist.
size() <<
"\n";
1717 ost <<
" - " << vh->at( 0 ) <<
" :: [" << vh <<
"] " << vh->size() <<
" {";
1718 for (
auto& e : *vh ) {
1720 ost <<
"[" << o <<
"]";
1728 for (
auto& e :
m_uids ) { ost <<
" - " << e.first <<
" [" << e.second <<
"]" <<
std::endl; }
1733 for (
auto& e :
m_ids ) { ost <<
" - " << e.first <<
" [" << e.second <<
"]" <<
std::endl; }
1739 TObject* o = e.first;
1740 THistID& i = e.second.first->at( e.second.second );
1741 ost <<
" - " << o <<
" -> " << i <<
std::endl;
1751 if ( vh->
size() == 1 ) {
1752 debug() <<
"merge: id: \"" << name <<
"\" is size 1. nothing to do" <<
endmsg;
1756 if ( !vh->
at( 0 ).obj->IsA()->InheritsFrom(
"TH1" ) ) {
1757 error() <<
"merge: id \"" << name <<
"\" is not a THn. Cannot merge" <<
endmsg;
1761 TList*
l =
new TList();
1762 for (
size_t i = 1; i < vh->
size(); ++i ) {
1763 debug() <<
"merge: id: \"" << name <<
"\" (" << vh->
at( i ).obj <<
") adding index " << i <<
endmsg;
1764 l->Add( vh->
at( i ).obj );
1767 TH1* t0 =
dynamic_cast<TH1*
>( vh->
at( 0 ).obj );
1769 error() <<
"merge: could not dcast " << name <<
"(" << t0 <<
") index " << 0 <<
" to TH1" <<
endmsg;
1773 Long64_t
n = t0->Merge( l );
1775 debug() <<
"merge: id: \"" << name <<
"\" merged " << n <<
" entries" <<
endmsg;
1777 for (
size_t i = 1; i < vh->
size(); ++i ) {
1778 TH1* th =
dynamic_cast<TH1*
>( vh->
at( i ).obj );
1780 debug() <<
"clearing index " << i <<
"(" << th <<
")" <<
endmsg;
1781 th->SetDirectory(
nullptr );
1784 error() <<
"merge: could not dcast " << name <<
" index " << i <<
" to TH1" <<
endmsg;
Parse attribute strings allowing iteration over the various attributes.
GlobalDirectoryRestore(THistSvcMutex_t &mut)
Helper struct that bundles the histogram ID with a mutex, TFile and TObject*.
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()
constexpr static const auto SUCCESS
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
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
static Mode charToMode(const char typ)
Convert a char to a Mode enum.
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
StatusCode regHist(const std::string &name) override
Register a new ROOT histogram TH*X with a name.
virtual std::vector< std::string > io_retrieve(IIoComponent *iocomponent)=0
: retrieve all registered filenames for a given IIoComponent
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 &)
constexpr static const auto FAILURE
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)