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>
94 static TROOT
root(
"root",
"ROOT I/O" );
98 verbose() <<
"ROOT already initialized, debug = " << gDebug <<
endmsg;
103 error() <<
"unable to get the IncidentSvc" <<
endmsg;
120 error() <<
"unable to register ROOT file open action with FileMgr" <<
endmsg;
126 error() <<
"unable to register ROOT file open Error action with FileMgr" <<
endmsg;
144 if (
service(
"IoComponentMgr", iomgr,
true ).isFailure() ) {
145 error() <<
"unable to get the IoComponentMgr" <<
endmsg;
149 error() <<
"could not register with the I/O component manager !" <<
endmsg;
152 bool all_good =
true;
154 for (
const auto& reg :
m_files ) {
155 const std::string& fname = reg.second.first->GetName();
159 warning() <<
"could not register file [" << fname <<
"] with the I/O component manager..." <<
endmsg;
162 info() <<
"registered file [" << fname <<
"]... [ok]" <<
endmsg;
166 error() <<
"problem while registering input/output files with " 167 <<
"the I/O component manager !" <<
endmsg;
174 fatal() <<
"Unable to initialize THistSvc" <<
endmsg;
198 for (
const auto& itr :
m_uids ) {
199 THistID& thid = itr.second->at( 0 );
200 TObject* tobj = thid.
obj;
203 if ( tobj && tobj->IsA()->InheritsFrom(
"TTree" ) ) {
204 TTree* tree =
dynamic_cast<TTree*
>( tobj );
205 if ( tree->GetDirectory() != 0 ) {
206 dirname = tree->GetDirectory()->GetPath();
208 }
else if ( tobj && tobj->IsA()->InheritsFrom(
"TGraph" ) ) {
210 dirname = thid.
file->GetPath();
214 if ( id2.
find(
"/" ) == 0 ) {
221 }
else if ( tobj && tobj->IsA()->InheritsFrom(
"TH1" ) ) {
222 TH1* th =
dynamic_cast<TH1*
>( tobj );
223 if ( th ==
nullptr ) {
224 error() <<
"Couldn't dcast: " << itr.first <<
endmsg;
226 if ( th->GetDirectory() != 0 ) {
227 dirname = th->GetDirectory()->GetPath();
230 }
else if ( !tobj ) {
239 error() <<
"problems writing histograms" <<
endmsg;
243 info() <<
"Listing contents of ROOT files: " <<
endmsg;
247 if (
std::find( deleted_files.
begin(), deleted_files.
end(), itr.second.first ) == deleted_files.
end() ) {
248 deleted_files.
push_back( itr.second.first );
252 debug() <<
"finalizing stream/file " << itr.first <<
":" << itr.second.first->GetName() <<
endmsg;
258 debug() <<
"already finalized stream " << itr.first <<
endmsg;
265 info() <<
"==> File: " << itr.second.first->GetName() <<
" stream: " << itr.first <<
endmsg;
267 itr.second.first->Print(
"base" );
275 if (
service(
"IncidentSvc", pIncidentSvc ).isFailure() ) {
276 error() <<
"Unable to get the IncidentSvc" <<
endmsg;
280 if ( itr.second.second ==
SHARE ) {
282 void* vfile =
nullptr;
291 TFile* outputfile = (TFile*)vfile;
295 debug() <<
"THistSvc::writeObjectsToFile()::Merging Rootfile " <<
endmsg;
302 error() <<
"unable to open temporary file: \"" << tmpfn <<
endmsg;
306 TFile* inputfile = (TFile*)vfile;
308 outputfile->SetCompressionLevel( inputfile->GetCompressionLevel() );
317 debug() <<
"Trying to remove temporary file \"" << tmpfn <<
"\"" <<
endmsg;
322 delete itr.second.first;
334 delete obj.second.first;
357 if ( hist_ptr !=
nullptr ) {
358 hist_ptr = hist.
get();
371 hist = getHist_i<TH1>( id, ind );
372 if ( hist !=
nullptr ) {
381 hist = getHist_i<TH2>( id, ind );
382 if ( hist !=
nullptr ) {
391 hist = getHist_i<TH3>( id, ind );
392 if ( hist !=
nullptr ) {
434 tree = getHist_i<TTree>( id );
435 if ( tree !=
nullptr ) {
450 if ( strcmp( graph->GetName(),
"Graph" ) == 0 ) {
452 std::string::size_type i = id2.
rfind(
"/" );
453 if ( i != std::string::npos ) {
454 id2.
erase( 0, i + 1 );
457 info() <<
"setting name of TGraph id: \"" <<
id <<
"\" to \"" << id2 <<
"\" since it is unset" <<
endmsg;
458 graph->SetName( id2.
c_str() );
467 if ( strcmp( graph->GetName(),
"Graph" ) == 0 ) {
469 std::string::size_type i = id2.
rfind(
"/" );
470 if ( i != std::string::npos ) {
471 id2.
erase( 0, i + 1 );
474 info() <<
"setting name of TGraph id: \"" <<
id <<
"\" to \"" << id2 <<
"\" since it is unset" <<
endmsg;
475 graph->SetName( id2.
c_str() );
483 graph = getHist_i<TGraph>( id );
484 if ( graph !=
nullptr ) {
493 lh = regShared_i<TH1>( id,
std::move( hist ) );
503 lh = regShared_i<TH2>( id,
std::move( hist ) );
513 lh = regShared_i<TH3>( id,
std::move( hist ) );
523 lh = regShared_i<TGraph>( id,
std::move( graph ) );
533 lh = getShared_i<TH1>(
name );
543 lh = getShared_i<TH2>(
name );
553 lh = getShared_i<TH3>(
name );
563 lh = getShared_i<TGraph>(
name );
575 error() <<
"Problem deregistering id \"" <<
id <<
"\": not found in registry" <<
endmsg;
580 debug() <<
"will deregister " << vh->
size() <<
" elements of id \"" <<
id <<
"\"" <<
endmsg;
582 while ( vh->
size() > 0 ) {
583 if (
deReg( vh->
back().obj ).isFailure() ) {
585 error() <<
"Problems deRegistering " << vh->
size() <<
" element of id \"" <<
id <<
"\"" <<
endmsg;
597 vhid_t* vhid = obj_itr->second.first;
598 THistID hid = obj_itr->second.first->at( obj_itr->second.second );
602 error() <<
"Problems deregistering TObject \"" << obj->GetName() <<
"\" with id \"" << hid.
id 603 <<
"\": not in uidMap" <<
endmsg;
607 if ( vhid->
size() == 1 ) {
609 debug() <<
"vhid for " << hid.
id <<
" is empty. deleting" <<
endmsg;
616 [&]( idMap_t::const_reference i ) { return i.second->at( 0 ).obj == obj; } );
617 if ( id_itr == mitr.second ) {
618 error() <<
"Problems deregistering TObject \"" << obj->GetName() <<
"\" with id \"" << hid.
id 619 <<
"\": not in idMap" <<
endmsg;
625 error() <<
"Problems deregistering TObject \"" << obj->GetName() <<
"\" with id \"" << hid.
id 626 <<
"\": not in hlist" <<
endmsg;
631 vhid->
erase( vhid->
begin() + obj_itr->second.second );
639 }
else if ( vhid->
size() > 1 ) {
641 vhid->
erase( vhid->
begin() + obj_itr->second.second );
645 error() <<
"Deregistration failed unexpectedly. (bug in THistSvc?)" <<
endmsg;
649 error() <<
"Cannot unregister TObject \"" << obj->GetName() <<
"\": not known to THistSvc" <<
endmsg;
658 error() <<
"merge: id \"" << name <<
"\" not found" <<
endmsg;
662 return merge( itr->second );
669 return merge( itr->second.first );
671 error() <<
"merge: unknown object " << obj <<
endmsg;
683 []( uidMap_t::const_reference i ) {
return i.second->at( 0 ).obj->IsA()->InheritsFrom(
"TH1" ); } );
692 []( uidMap_t::const_reference i ) {
return i.second->at( 0 ).obj->IsA()->InheritsFrom(
"TTree" ); } );
701 []( uidMap_t::const_reference i ) {
return i.second->at( 0 ).obj->IsA()->InheritsFrom(
"TGraph" ); } );
709 gErrorIgnoreLevel = kBreak;
712 error() <<
"getTHists: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
717 debug() <<
"getTHists: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys" <<
endmsg;
720 TIter nextkey( td->GetListOfKeys() );
721 while ( TKey* key = (TKey*)nextkey() ) {
724 TObject* obj = key->ReadObj();
725 if ( obj != 0 && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
727 }
else if ( obj != 0 && obj->IsA()->InheritsFrom(
"TH1" ) ) {
730 }
else if ( obj != 0 ) {
738 nextkey = td->GetListOfKeys();
739 while ( TKey* key = (TKey*)nextkey() ) {
740 TObject* obj = key->ReadObj();
741 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
742 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
756 gErrorIgnoreLevel = kBreak;
765 r2 = itr->second.first->GetName();
770 debug() <<
"getTHists: \"" << dir <<
"\" looks like a stream name." 771 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
774 if ( gDirectory->cd( r2.
c_str() ) ) {
781 debug() <<
"getTHists: no such TDirectory \"" << r2 <<
"\"" <<
endmsg;
787 debug() <<
"getTHists: stream \"" << stream <<
"\" not found" <<
endmsg;
791 if ( !gDirectory->cd( dir.
c_str() ) ) {
792 error() <<
"getTHists: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
805 gErrorIgnoreLevel = kBreak;
808 error() <<
"getTHists: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
813 debug() <<
"getTHists: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys" <<
endmsg;
816 TIter nextkey( td->GetListOfKeys() );
817 while ( TKey* key = (TKey*)nextkey() ) {
820 TObject* obj = key->ReadObj();
821 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
823 }
else if ( obj && obj->IsA()->InheritsFrom(
"TH1" ) ) {
832 id =
id +
"/" + key->GetName();
834 id =
id + dir +
"/" + key->GetName();
851 nextkey = td->GetListOfKeys();
852 while ( TKey* key = (TKey*)nextkey() ) {
853 TObject* obj = key->ReadObj();
854 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
855 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 );
893 debug() <<
"getTHists: no such TDirectory \"" << r2 <<
"\"" <<
endmsg;
897 debug() <<
"getTHists: stream \"" << stream <<
"\" not found" <<
endmsg;
901 if ( !gDirectory->cd( dir.
c_str() ) ) {
902 error() <<
"getTHists: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
906 warning() <<
"Unable to register histograms automatically " 907 <<
"without a valid stream name" <<
endmsg;
910 sc =
getTHists( gDirectory, tl, rcs, reg );
920 gErrorIgnoreLevel = kBreak;
923 error() <<
"getTTrees: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
928 debug() <<
"getTHists: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys" <<
endmsg;
931 TIter nextkey( td->GetListOfKeys() );
932 while ( TKey* key = (TKey*)nextkey() ) {
935 TObject* obj = key->ReadObj();
936 if ( obj != 0 && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
938 }
else if ( obj != 0 && obj->IsA()->InheritsFrom(
"TTree" ) ) {
941 }
else if ( obj != 0 ) {
949 nextkey = td->GetListOfKeys();
950 while ( TKey* key = (TKey*)nextkey() ) {
951 TObject* obj = key->ReadObj();
952 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
953 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
966 gErrorIgnoreLevel = kBreak;
975 r2 = itr->second.first->GetName();
980 debug() <<
"getTTrees: \"" << dir <<
"\" looks like a stream name." 981 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
984 if ( gDirectory->cd( r2.
c_str() ) ) {
988 debug() <<
"getTTrees: no such TDirectory \"" << r2 <<
"\"" <<
endmsg;
992 debug() <<
"getTTrees: stream \"" << stream <<
"\" not found" <<
endmsg;
996 if ( !gDirectory->cd( dir.
c_str() ) ) {
997 error() <<
"getTTrees: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
1009 gErrorIgnoreLevel = kBreak;
1012 error() <<
"getTTrees: No such TDirectory \"" << td->GetPath() <<
"\"" <<
endmsg;
1017 debug() <<
"getTHists: \"" << td->GetPath() <<
"\": found " << td->GetListOfKeys()->GetSize() <<
" keys" <<
endmsg;
1020 TIter nextkey( td->GetListOfKeys() );
1021 while ( TKey* key = (TKey*)nextkey() ) {
1024 TObject* obj = key->ReadObj();
1025 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
1027 }
else if ( obj && obj->IsA()->InheritsFrom(
"TTree" ) ) {
1036 id =
id +
"/" + key->GetName();
1038 id =
id + dir +
"/" + key->GetName();
1047 }
else if ( obj != 0 ) {
1055 nextkey = td->GetListOfKeys();
1056 while ( TKey* key = (TKey*)nextkey() ) {
1057 TObject* obj = key->ReadObj();
1058 if ( obj && obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
1059 TDirectory* tt =
dynamic_cast<TDirectory*
>( obj );
1072 gErrorIgnoreLevel = kBreak;
1081 r2 = itr->second.first->GetName();
1086 debug() <<
"getTTrees: \"" << dir <<
"\" looks like a stream name." 1087 <<
" associated TFile: \"" << itr->second.first->GetName() <<
"\"" <<
endmsg;
1090 if ( gDirectory->cd( r2.
c_str() ) ) {
1091 return getTTrees( gDirectory, tl, rcs, reg );
1094 debug() <<
"getTTrees: no such TDirectory \"" << r2 <<
"\"" <<
endmsg;
1099 debug() <<
"getTTrees: stream \"" << stream <<
"\" not found" <<
endmsg;
1103 if ( !gDirectory->cd( dir.
c_str() ) ) {
1104 error() <<
"getTTrees: No such TDirectory/stream \"" << dir <<
"\"" <<
endmsg;
1108 return getTTrees( gDirectory, tl, rcs, reg );
1120 Long64_t mfs = (Long64_t)
m_maxFileSize.value() * (Long64_t)1048576;
1121 Long64_t mfs_warn = mfs * 95 / 100;
1126 for (
const auto& f :
m_files ) {
1127 TFile* tf = f.second.first;
1131 debug() <<
"stream: " << f.first <<
" name: " << tf->GetName() <<
" size: " << tf->GetSize() <<
endmsg;
1136 if ( tf->GetSize() > mfs ) {
1140 fatal() <<
"file \"" << tf->GetName() <<
"\" associated with stream \"" << f.first
1141 <<
"\" has exceeded the max file size of " <<
m_maxFileSize.value() <<
"MB. Terminating Job." <<
endmsg;
1144 if (
service(
"ApplicationMgr", evt,
true ).isSuccess() ) {
1150 }
else if ( tf->GetSize() > mfs_warn ) {
1151 warning() <<
"file \"" << tf->GetName() <<
"\" associated with stream \"" << f.first
1152 <<
"\" is at 95% of its maximum allowable file size of " <<
m_maxFileSize.value() <<
"MB" <<
endmsg;
1162 bool all_good =
true;
1171 if (
service(
"IoComponentMgr", iomgr,
true ).isFailure() ) {
1172 error() <<
"could not retrieve I/O component manager !" <<
endmsg;
1179 gErrorIgnoreLevel = kFatal;
1181 for (
auto& ifile :
m_files ) {
1182 TFile* f = ifile.second.first;
1185 debug() <<
"file [" << fname <<
"] mode: [" << f->GetOption() <<
"] r:" << f->GetFileBytesRead()
1186 <<
" w:" << f->GetFileBytesWritten() <<
" cnt:" << f->GetFileCounter() <<
endmsg;
1189 if ( ifile.second.second ==
READ ) {
1191 debug() <<
" TFile opened in READ mode: not reassigning names" <<
endmsg;
1197 error() <<
"could not retrieve new name for [" << fname <<
"] !!" <<
endmsg;
1202 debug() <<
"got a new name [" << fname <<
"]..." <<
endmsg;
1207 Option_t*
opts = f->GetOption();
1210 error() <<
"unable to open file \"" << fname <<
"\" for writing" <<
endmsg;
1213 TFile* newfile = (TFile*)vf;
1214 newfile->SetOption( opts );
1218 ifile.second.first = newfile;
1225 if ( hid.
file != f )
continue;
1226 TDirectory* olddir = this->
changeDir( hid );
1229 TDirectory* newdir = this->
changeDir( hid );
1230 TClass* cl = hid.
obj->IsA();
1234 if ( cl->InheritsFrom(
"TTree" ) ) {
1235 dynamic_cast<TTree*
>( hid.
obj )->SetDirectory( newdir );
1236 dynamic_cast<TTree*
>( hid.
obj )->Reset();
1237 }
else if ( cl->InheritsFrom(
"TH1" ) ) {
1238 dynamic_cast<TH1*
>( hid.
obj )->SetDirectory( newdir );
1239 dynamic_cast<TH1*
>( hid.
obj )->Reset();
1240 }
else if ( cl->InheritsFrom(
"TGraph" ) ) {
1241 olddir->Remove( hid.
obj );
1242 newdir->Append( hid.
obj );
1244 error() <<
"id: \"" << hid.
id <<
"\" is not a inheriting from a class " 1245 <<
"we know how to handle (received [" << cl->GetName() <<
"], " 1246 <<
"expected [TTree, TH1 or TGraph]) !" <<
endmsg <<
"attaching to current dir [" << newdir->GetPath()
1248 <<
"nonetheless..." <<
endmsg;
1249 olddir->Remove( hid.
obj );
1250 newdir->Append( hid.
obj );
1253 f->ReOpen(
"READ" );
1279 template <
typename T>
1282 return dynamic_cast<T*
>( readHist_i<T>( id ) );
1299 verbose() <<
" update: " << uitr->first <<
" " << uitr->second.id <<
" " << uitr->second.mode <<
endmsg;
1301 TObject* to = uitr->second.obj;
1302 TFile* oldFile = uitr->second.file;
1305 }
else if ( uitr->second.temp || uitr->second.mode ==
READ ) {
1311 }
else if ( to->IsA()->InheritsFrom(
"TTree" ) ) {
1312 TTree* tr =
dynamic_cast<TTree*
>( to );
1313 TFile* newFile = tr->GetCurrentFile();
1315 if ( oldFile != newFile ) {
1318 TFile* dummy =
nullptr;
1319 findStream( uitr->second.id, streamName, rem, dummy );
1322 if ( itr.second.first == oldFile ) {
1323 itr.second.first = newFile;
1327 for (
auto uitr2 = uitr; uitr2 !=
m_uidsX.
end(); ++uitr2 ) {
1328 if ( uitr2->second.file == oldFile ) {
1329 uitr2->second.file = newFile;
1334 [&]( streamMap::const_reference
s ) {
return s.second == streamName; } );
1339 debug() <<
"migrating uid: " << uitr->second.id <<
" stream: " << streamName
1340 <<
" oldFile: " << oldFileName <<
" newFile: " << newFileName <<
endmsg;
1344 if ( !oldFileName.
empty() ) {
1349 debug() <<
"changing filename \"" << i->first <<
"\" to \"" << newFileName <<
"\" for stream \"" 1350 << i->second <<
"\"" <<
endmsg;
1358 error() <<
"Problems updating fileStreams with new file name" <<
endmsg;
1370 auto mode = i.second.second;
1371 auto file = i.second.first;
1373 file->Write(
"", TObject::kOverwrite );
1374 }
else if ( mode ==
APPEND ) {
1380 debug() <<
"THistSvc::writeObjectsToFile()::List of Files connected in ROOT " <<
endmsg;
1381 TSeqCollection* filelist = gROOT->GetListOfFiles();
1382 for (
int ii = 0; ii < filelist->GetEntries(); ii++ ) {
1383 debug() <<
"THistSvc::writeObjectsToFile()::List of Files connected in ROOT: \"" << filelist->At( ii )->GetName()
1393 auto loc = ident.
find(
" " );
1401 if ( loc != std::string::npos ) {
1403 for (
auto attrib : Parser( ident.
substr( loc + 1 ) ) ) {
1404 auto TAG = boost::algorithm::to_upper_copy( attrib.tag );
1405 auto VAL = boost::algorithm::to_upper_copy( attrib.value );
1407 if ( TAG ==
"FILE" || TAG ==
"DATAFILE" ) {
1408 filename = attrib.value;
1410 }
else if ( TAG ==
"OPT" ) {
1411 if ( VAL ==
"APPEND" || VAL ==
"UPDATE" ) {
1413 }
else if ( VAL ==
"CREATE" || VAL ==
"NEW" || VAL ==
"WRITE" ) {
1415 }
else if ( VAL ==
"RECREATE" ) {
1417 }
else if ( VAL ==
"SHARE" ) {
1419 }
else if ( VAL ==
"OLD" || VAL ==
"READ" ) {
1422 error() <<
"Unknown OPT: \"" << attrib.value <<
"\"" <<
endmsg;
1425 }
else if ( TAG ==
"TYP" ) {
1427 }
else if ( TAG ==
"CL" ) {
1435 if ( stream ==
"temp" ) {
1436 error() <<
"in JobOption \"" << ident <<
"\": stream name \"temp\" reserved." <<
endmsg;
1440 if ( db_typ !=
"ROOT" ) {
1441 error() <<
"in JobOption \"" << ident <<
"\": technology type \"" << db_typ <<
"\" not supported." <<
endmsg;
1446 error() <<
"in JobOption \"" << ident <<
"\":\n stream \"" << stream <<
"\" already connected to file: \"" 1454 }
else if ( typ ==
'N' ) {
1456 }
else if ( typ ==
'A' ) {
1458 }
else if ( typ ==
'R' ) {
1460 }
else if ( typ ==
'S' ) {
1464 error() <<
"No OPT= specified or unknown access mode in: " << ident <<
endmsg;
1472 const std::string& oldstream = fitr.first->second;
1474 const auto& f_info =
m_files[oldstream];
1476 if ( newMode != f_info.second ) {
1477 error() <<
"in JobOption \"" << ident <<
"\":\n file \"" << filename <<
"\" already opened by stream: \"" 1478 << oldstream <<
"\" with different access mode." <<
endmsg;
1481 TFile* f2 = f_info.first;
1484 debug() <<
"Connecting stream: \"" << stream <<
"\" to previously opened TFile: \"" << filename <<
"\"" 1491 if (
service(
"IncidentSvc", pi ).isFailure() ) {
1492 error() <<
"Unable to get the IncidentSvc" <<
endmsg;
1504 error() <<
"Unable to open ROOT file " << filename <<
" for reading" <<
endmsg;
1518 error() <<
"Unable to open ROOT file " << filename <<
" for writing" <<
endmsg;
1528 error() <<
"unable to open file \"" << filename <<
"\" for appending" <<
endmsg;
1539 static int ishared = 0;
1541 filename =
"tmp_THistSvc_" +
std::to_string( ishared++ ) +
".root";
1544 debug() <<
"Creating temp file \"" << filename <<
"\" and realfilename=" << realfilename <<
endmsg;
1551 error() <<
"Unable to open ROOT file " << filename <<
" for writing" <<
endmsg;
1562 error() <<
"Unable to open ROOT file " << filename <<
" for appending" <<
endmsg;
1573 debug() <<
"Opening TFile \"" << filename <<
"\" stream: \"" << stream <<
"\" mode: \"" << typ <<
"\"" 1574 <<
" comp level: " << cl <<
endmsg;
1583 TFile* file = hid.
file;
1596 if ( !gDirectory->GetKey( dir.
c_str() ) ) {
1597 gDirectory->mkdir( dir.
c_str() );
1599 gDirectory->cd( dir.
c_str() );
1607 std::string::size_type i = dir.
find(
"/" );
1609 if ( i == std::string::npos )
return {};
1624 while (
id.find(
"//" ) != std::string::npos ) {
1625 id.replace(
id.find(
"//" ), 2,
"/" );
1632 debug() <<
"Target path: " << target->GetPath() <<
endmsg;
1634 TString
path( (
char*)strstr( target->GetPath(),
":" ) );
1635 path.Remove( 0, 2 );
1638 TDirectory* current_sourcedir = gDirectory;
1641 TList* lkeys = current_sourcedir->GetListOfKeys();
1642 int nkeys = lkeys->GetEntries();
1643 TKey* key =
nullptr;
1644 for (
int jj = 0; jj < nkeys; jj++ ) {
1645 key = (TKey*)lkeys->At( jj );
1648 debug() <<
"Reading Key:" << pathnameinsource <<
endmsg;
1650 TObject* obj = source->Get( pathnameinsource.
c_str() );
1653 if ( obj->IsA()->InheritsFrom(
"TDirectory" ) ) {
1656 debug() <<
"Found subdirectory " << obj->GetName() <<
endmsg;
1661 TDirectory* newtargetdir = target->mkdir( obj->GetName(), obj->GetTitle() );
1665 }
else if ( obj->IsA()->InheritsFrom(
"TTree" ) ) {
1667 debug() <<
"Found TTree " << obj->GetName() <<
endmsg;
1669 TTree* mytree =
dynamic_cast<TTree*
>( obj );
1670 int nentries = (int)mytree->GetEntries();
1671 mytree->SetBranchStatus(
"*", 1 );
1674 debug() <<
"Dumping TTree " << nentries <<
" entries" <<
endmsg;
1677 mytree->CloneTree();
1681 obj->Write( key->GetName() );
1689 auto pos =
id.find(
"/" );
1691 if ( pos == std::string::npos ) {
1695 }
else if ( pos != 0 ) {
1702 auto pos2 =
id.
find(
"/", pos + 1 );
1704 if ( pos2 == std::string::npos ) {
1706 error() <<
"badly formed Hist/Tree id: \"" <<
id <<
"\"" <<
endmsg;
1712 if ( stream ==
"temp" ) {
1718 file = ( itr !=
m_files.
end() ? itr->second.first : nullptr );
1720 warning() <<
"no stream \"" << stream <<
"\" associated with id: \"" <<
id <<
"\"" <<
endmsg;
1728 auto pos =
id.find(
"/" );
1730 if ( pos == std::string::npos ) {
1733 }
else if ( pos == 0 ) {
1736 root =
id.
substr( 0, pos );
1737 rem =
id.
substr( pos + 1 );
1745 debug() <<
"Delaying connection of Input Files until Initialize" 1750 debug() <<
"Now connecting of Input Files" <<
endmsg;
1775 debug() <<
"Delaying connection of Input Files until Initialize" 1800 warning() <<
"\"CompressionLevel\" Property has been deprecated. " 1801 <<
"Set it via the \"CL=\" parameter in the \"Output\" Property" <<
endmsg;
1807 debug() <<
"copyFileLayout() to destination path: " << destination->GetPath() <<
endmsg;
1811 TString
path( (
char*)strstr( destination->GetPath(),
":" ) );
1812 path.Remove( 0, 2 );
1815 TDirectory* current_source_dir = gDirectory;
1818 TList* key_list = current_source_dir->GetListOfKeys();
1819 int n = key_list->GetEntries();
1820 for (
int j = 0; j <
n; ++j ) {
1821 TKey* k = (TKey*)key_list->At( j );
1823 TObject* o = source->Get( source_pathname.
c_str() );
1825 if ( o && o->IsA()->InheritsFrom(
"TDirectory" ) ) {
1827 verbose() <<
" subdir [" << o->GetName() <<
"]..." <<
endmsg;
1830 TDirectory* destination_dir = destination->mkdir( o->GetName(), o->GetTitle() );
1846 if ( idr.
find(
"/" ) == 0 ) {
1854 if ( index >= itr->second->size() ) {
1855 error() <<
"no index " << index <<
" found for Hist " << idr <<
endmsg;
1858 hid = &( itr->second->at( index ) );
1864 if ( mitr.first == mitr.second ) {
1867 }
else if ( distance( mitr.first, mitr.second ) == 1 ) {
1869 if ( index >= mitr.first->second->size() ) {
1870 error() <<
"no index " << index <<
" found for Hist " << idr <<
endmsg;
1873 hid = &( mitr.first->second->at( 0 ) );
1877 hid = &( mitr.first->second->at( 0 ) );
1878 return distance( mitr.first, mitr.second );
1888 ost <<
"m_hlist: size: " <<
m_hlist.
size() <<
"\n";
1890 ost <<
" - " << vh->at( 0 ) <<
" :: [" << vh <<
"] " << vh->size() <<
" {";
1891 for (
auto& e : *vh ) {
1893 ost <<
"[" << o <<
"]";
1901 for (
auto& e :
m_uids ) {
1902 ost <<
" - " << e.first <<
" [" << e.second <<
"]" <<
std::endl;
1908 for (
auto& e :
m_ids ) {
1909 ost <<
" - " << e.first <<
" [" << e.second <<
"]" <<
std::endl;
1916 TObject* o = e.first;
1917 THistID& i = e.second.first->at( e.second.second );
1918 ost <<
" - " << o <<
" -> " << i <<
std::endl;
1929 if ( vh->
size() == 1 ) {
1930 debug() <<
"merge: id: \"" << name <<
"\" is size 1. nothing to do" <<
endmsg;
1934 if ( !vh->
at( 0 ).obj->IsA()->InheritsFrom(
"TH1" ) ) {
1935 error() <<
"merge: id \"" << name <<
"\" is not a THn. Cannot merge" <<
endmsg;
1939 TList*
l =
new TList();
1940 for (
size_t i = 1; i < vh->
size(); ++i ) {
1941 debug() <<
"merge: id: \"" << name <<
"\" (" << vh->
at( i ).obj <<
") adding index " << i <<
endmsg;
1942 l->Add( vh->
at( i ).obj );
1945 TH1* t0 =
dynamic_cast<TH1*
>( vh->
at( 0 ).obj );
1947 error() <<
"merge: could not dcast " << name <<
"(" << t0 <<
") index " << 0 <<
" to TH1" <<
endmsg;
1951 Long64_t
n = t0->Merge( l );
1953 debug() <<
"merge: id: \"" << name <<
"\" merged " << n <<
" entries" <<
endmsg;
1955 for (
size_t i = 1; i < vh->
size(); ++i ) {
1956 TH1* th =
dynamic_cast<TH1*
>( vh->
at( i ).obj );
1958 debug() <<
"clearing index " << i <<
"(" << th <<
")" <<
endmsg;
1959 th->SetDirectory(
nullptr );
1962 error() <<
"merge: could not dcast " << name <<
" index " << i <<
" to TH1" <<
endmsg;
1976 if ( fa->
desc() !=
"HIST" ) {
2001 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
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
const std::string & name() const override
Retrieve name of the service.
TTree * readTree(const std::string &name) const
StatusCode finalize() override
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
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.
void setupCompressionLevel(Gaudi::Details::PropertyBase &cmp)
Gaudi::Property< std::vector< std::string > > m_outputfile
MsgStream & err() const
shortcut for the method msgStream(MSG::ERROR)
std::vector< std::string > getHists() const override
#define DECLARE_COMPONENT(type)
virtual StatusCode regAction(Io::bfcn_action_t, const Io::Action &, const std::string &d="")=0
const std::string & name() const
Gaudi::Property< int > m_autoSave
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.
Provides automatic lock/unlock access to a class upon deref of ptr.
Gaudi::Property< bool > m_print
void handle(const Incident &) override
Gaudi::Property< int > m_maxFileSize
StatusCode getTree(const std::string &name, TTree *&) const override
Return TTree with given name.
~GlobalDirectoryRestore()
StatusCode rootOpenErrAction(FILEMGR_CALLBACK_ARGS)
PropertyBase base class allowing PropertyBase* collections to be "homogeneous".
Gaudi::Property< int > m_compressionLevel
void parseString(const std::string &id, std::string &root, std::string &rem) const
StatusCode finalize() override
StatusCode regHist_i(std::unique_ptr< T > hist, const std::string &name, bool shared)
constexpr static const auto SUCCESS
StatusCode regHist(const std::string &name) override
Register a new ROOT histogram TH*X with a name.
Mode
Enumerating all possible file access modes.
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)
const StatusCode & ignore() const
Ignore/check StatusCode.
Base class for all Incidents (computing events).
virtual void addListener(IIncidentListener *lis, const std::string &type="", long priority=0, bool rethrow=false, bool singleShot=false)=0
Add listener.
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.
MsgStream & fatal() const
shortcut for the method msgStream(MSG::FATAL)
std::set< std::string > m_alreadyConnectedInFiles
list of already connected files.
void setupInputFile(Gaudi::Details::PropertyBase &inputfile)
call-back method to handle input stream property
void setupOutputFile(Gaudi::Details::PropertyBase &outputfile)
call-back method to handle output stream property
StatusCode regGraph(const std::string &name) override
Register a new TGraph with a given name.
Gaudi::Property< int > m_autoFlush
THistSvc(const std::string &name, ISvcLocator *svc)
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)
virtual Io::close_t close(const Io::Fd, const std::string &caller)=0