00001 #ifdef __ICC
00002
00003
00004 #pragma warning(disable:2259)
00005 #endif
00006
00007 #include "THistSvc.h"
00008
00009 #include "GaudiKernel/SvcFactory.h"
00010 #include "GaudiKernel/ISvcLocator.h"
00011 #include "GaudiKernel/Tokenizer.h"
00012 #include "GaudiKernel/GaudiException.h"
00013 #include "GaudiKernel/Property.h"
00014 #include "GaudiKernel/IIncidentSvc.h"
00015 #include "GaudiKernel/FileIncident.h"
00016 #include "GaudiKernel/IEventProcessor.h"
00017 #include "GaudiKernel/IJobOptionsSvc.h"
00018
00019
00020 #include "TROOT.h"
00021 #include "TFile.h"
00022 #include "TDirectory.h"
00023 #include "TKey.h"
00024 #include "TError.h"
00025 #include "TGraph.h"
00026
00027 #include <sstream>
00028 #include <streambuf>
00029 #include <cstdio>
00030
00031 using namespace std;
00032
00033
00034 DECLARE_SERVICE_FACTORY(THistSvc)
00035
00036 inline void toupper(std::string &s)
00037 {
00038 std::transform(s.begin(), s.end(), s.begin(),
00039 (int(*)(int)) toupper);
00040 }
00041
00042
00043
00044
00045 THistSvc::THistSvc( const std::string& name, ISvcLocator* svc )
00046 : base_class(name, svc), m_log(msgSvc(), name ), signaledStop(false) {
00047
00048 declareProperty ("AutoSave", m_autoSave=0 );
00049 declareProperty ("AutoFlush", m_autoFlush=0 );
00050 declareProperty ("PrintAll", m_print=false);
00051 declareProperty ("MaxFileSize", m_maxFileSize=10240,
00052 "maximum file size in MB. if exceeded, will cause an abort");
00053 declareProperty ("CompressionLevel", m_compressionLevel=1 )->declareUpdateHandler( &THistSvc::setupCompressionLevel, this );
00054 declareProperty ("Output", m_outputfile )->declareUpdateHandler( &THistSvc::setupOutputFile, this );
00055 declareProperty ("Input", m_inputfile )->declareUpdateHandler ( &THistSvc::setupInputFile, this );
00056
00057
00058 }
00059
00060
00061
00062 THistSvc::~THistSvc() {
00063
00064 }
00065
00066
00067
00068 StatusCode
00069 THistSvc::initialize() {
00070 GlobalDirectoryRestore restore;
00071
00072 m_alreadyConnectedOutFiles.clear();
00073 m_alreadyConnectedInFiles.clear();
00074
00075
00076
00077
00078 IJobOptionsSvc* jos(0);
00079 if( serviceLocator()->service( "JobOptionsSvc", jos, true ).isSuccess() ) {
00080 const std::vector<const Property*> *props = jos->getProperties( name() );
00081
00082 if (props != NULL) {
00083 for ( std::vector<const Property*>::const_iterator cur = props->begin();
00084 cur != props->end(); cur++) {
00085 if ( (*cur)->name() == "OutputLevel" ) {
00086 setProperty( **cur ).ignore();
00087 m_log.setLevel( m_outputLevel.value() );
00088 break;
00089 }
00090 }
00091 }
00092 }
00093
00094
00095 StatusCode status = Service::initialize();
00096 m_log.setLevel( m_outputLevel.value() );
00097
00098 if (status.isFailure()) {
00099 m_log << MSG::ERROR << "initializing service" << endmsg;
00100 return status;
00101 }
00102
00103 vector<string>::const_iterator itr;
00104 StatusCode st(StatusCode::SUCCESS);
00105
00106 try {
00107 setupOutputFile( m_outputfile );
00108 } catch ( GaudiException& err ) {
00109 m_log << MSG::ERROR
00110 << "Caught: " << err << endmsg;
00111 st = StatusCode::FAILURE;
00112 }
00113
00114 try {
00115 setupInputFile( m_inputfile );
00116 } catch ( GaudiException& err ) {
00117 m_log << MSG::ERROR
00118 << "Caught: " << err << endmsg;
00119 st = StatusCode::FAILURE;
00120 }
00121
00122
00123 if ( 0 == gROOT ) {
00124 static TROOT root("root","ROOT I/O");
00125
00126 } else {
00127 if (m_log.level() <= MSG::VERBOSE)
00128 m_log << MSG::VERBOSE << "ROOT already initialized, debug = "
00129 << gDebug<< endmsg;
00130 }
00131
00132 IIncidentSvc* p_incSvc(0);
00133
00134 if (service("IncidentSvc", p_incSvc, true).isFailure()) {
00135 m_log << MSG::ERROR << "unable to get the IncidentSvc" << endmsg;
00136 st = StatusCode::FAILURE;
00137 } else {
00138 p_incSvc->addListener( this, "EndEvent", 100, true);
00139 }
00140
00141 if (st.isFailure()) {
00142 m_log << MSG::FATAL << "Unable to initialize THistSvc" << endmsg;
00143 }
00144
00145 return st;
00146
00147 }
00148
00149
00150
00151 StatusCode
00152 THistSvc::reinitialize() {
00153
00154 GlobalDirectoryRestore restore;
00155
00156 m_log << MSG::WARNING << "reinitialize not implemented" << endmsg;
00157
00158
00159 return StatusCode::SUCCESS;
00160
00161 }
00162
00163
00164
00165 StatusCode
00166 THistSvc::finalize() {
00167
00168 GlobalDirectoryRestore restore;
00169
00170 if (m_log.level() <= MSG::DEBUG)
00171 m_log << MSG::DEBUG << "THistSvc::finalize" << endmsg;
00172
00173 uidMap::const_iterator uitr;
00174 for (uitr=m_uids.begin(); uitr != m_uids.end(); ++uitr) {
00175
00176 TObject* to = uitr->second.obj;
00177
00178 string dirname("none");
00179 if (to->IsA()->InheritsFrom("TTree")) {
00180 TTree* tr = dynamic_cast<TTree*>(to);
00181 if (tr->GetDirectory() != 0) {
00182 dirname = tr->GetDirectory()->GetPath();
00183 }
00184 } else if (to->IsA()->InheritsFrom("TGraph")) {
00185 if (!uitr->second.temp) {
00186 dirname = uitr->second.file->GetPath();
00187 string id2(uitr->second.id);
00188 id2.erase(0,id2.find("/",1));
00189 id2.erase(id2.rfind("/"), id2.length());
00190 if (id2.find("/") == 0) {
00191 id2.erase(0,1);
00192 }
00193 dirname += id2;
00194 } else {
00195 dirname = "/tmp";
00196 }
00197 } else if (to->IsA()->InheritsFrom("TH1")) {
00198 TH1* th = dynamic_cast<TH1*>(to);
00199 if (th == 0) {
00200 m_log << MSG::ERROR << "Couldn't dcast: " << uitr->first << endmsg;
00201 } else {
00202 if (th->GetDirectory() != 0) {
00203 dirname = th->GetDirectory()->GetPath();
00204 }
00205 }
00206 }
00207
00208 #ifndef NDEBUG
00209 if (m_log.level() <= MSG::DEBUG)
00210 m_log << MSG::DEBUG << "uid: \"" << uitr->first << "\" temp: "
00211 << uitr->second.temp << " dir: " << dirname
00212 << endmsg;
00213 #endif
00214
00215
00216
00217
00218
00219
00220 }
00221
00222 StatusCode sc = write();
00223 if (sc.isFailure()) {
00224 m_log << MSG::ERROR << "problems writing histograms" << endmsg;
00225 }
00226
00227 if (m_print) {
00228 m_log << MSG::INFO << "Listing contents of ROOT files: " << endmsg;
00229 }
00230 vector<TFile*> deleted_files;
00231 map<string, pair<TFile*,Mode> >::const_iterator itr;
00232 for (itr = m_files.begin(); itr != m_files.end(); ++itr) {
00233
00234 if (find(deleted_files.begin(), deleted_files.end(), itr->second.first) ==
00235 deleted_files.end()) {
00236 deleted_files.push_back(itr->second.first);
00237
00238 #ifndef NDEBUG
00239 if (m_log.level() <= MSG::DEBUG)
00240 m_log << MSG::DEBUG << "finalizing stream/file " << itr->first << ":"
00241 << itr->second.first->GetName()
00242 << endmsg;
00243 #endif
00244 } else {
00245 #ifndef NDEBUG
00246 if (m_log.level() <= MSG::DEBUG)
00247 m_log << MSG::DEBUG << "already finalized stream " << itr->first << endmsg;
00248 #endif
00249 continue;
00250 }
00251
00252
00253 if (m_print && m_log.level() <= MSG::INFO) {
00254
00255 m_log << MSG::INFO;
00256 m_log << "==> File: " << itr->second.first->GetName()
00257 << " stream: " << itr->first << endmsg;
00258
00259 itr->second.first->Print("base");
00260 }
00261
00262 string tmpfn=itr->second.first->GetName();
00263
00264 itr->second.first->Close();
00265
00266 IIncidentSvc *pi(0);
00267 if (service("IncidentSvc",pi).isFailure()) {
00268 m_log << MSG::ERROR << "Unable to get the IncidentSvc" << endmsg;
00269 return StatusCode::FAILURE;
00270 }
00271
00272 if (itr->second.second==SHARE) {
00273 TFile *outputfile;
00274
00275 try {
00276 if (m_log.level() <= MSG::DEBUG)
00277 m_log << MSG::DEBUG << "Opening Final Output File: " <<m_sharedFiles[itr->first].c_str()<<endmsg;
00278 outputfile = new TFile(m_sharedFiles[itr->first].c_str(), "UPDATE");
00279 } catch (const std::exception& Exception) {
00280 m_log << MSG::ERROR << "exception caught while trying to open root"
00281 << " file for appending: " << Exception.what() << std::endl
00282 << " -> file probably corrupt." << endmsg;
00283 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
00284 m_sharedFiles[itr->first]));
00285 return StatusCode::FAILURE;
00286 } catch (...) {
00287 m_log << MSG::ERROR << "Problems opening output file \""
00288 << m_sharedFiles[itr->first]
00289 << "\" for append: probably corrupt" << endmsg;
00290 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
00291 m_sharedFiles[itr->first]));
00292 return StatusCode::FAILURE;
00293 }
00294
00295 pi->fireIncident(FileIncident(name(), IncidentType::WroteToOutputFile,
00296 m_sharedFiles[itr->first]));
00297
00298 if (m_log.level() <= MSG::DEBUG)
00299 m_log << MSG::DEBUG << "THistSvc::write()::Merging Rootfile "<<endmsg;
00300 TFile *inputfile;
00301 try {
00302 if (m_log.level() <= MSG::DEBUG)
00303 m_log << MSG::DEBUG << "Openning again Temporary File: " <<tmpfn.c_str()<<endmsg;
00304 inputfile=new TFile(tmpfn.c_str(),"READ");
00305 } catch (const std::exception& Exception) {
00306 m_log << MSG::ERROR << "exception caught while trying to open root"
00307 << " file for appending: " << Exception.what() << std::endl
00308 << " -> file probably corrupt." << endmsg;
00309 return StatusCode::FAILURE;
00310 } catch (...) {
00311 m_log << MSG::ERROR << "Problems opening output file \""
00312 << tmpfn.c_str()
00313 << "\" for append: probably corrupt" << endmsg;
00314 return StatusCode::FAILURE;
00315 }
00316
00317 outputfile->SetCompressionLevel( inputfile->GetCompressionLevel() );
00318
00319 MergeRootFile(outputfile, inputfile);
00320
00321 outputfile->Write();
00322 outputfile->Close();
00323 inputfile->Close();
00324
00325 if (m_log.level() <= MSG::DEBUG)
00326 m_log << MSG::DEBUG << "Trying to remove temporary file \"" << tmpfn
00327 << "\""<<endmsg;
00328
00329 std::remove(tmpfn.c_str());
00330 }
00331 delete itr->second.first;
00332 }
00333
00334 m_sharedFiles.clear();
00335 m_fileStreams.clear();
00336 m_files.clear();
00337 m_uids.clear();
00338 m_ids.clear();
00339 m_tobjs.clear();
00340
00341 return Service::finalize();
00342 }
00343
00344
00345
00346 bool
00347 THistSvc::browseTDir(TDirectory *dir) const {
00348
00349 if (dir == 0) {
00350 std::cerr << "TDirectory == 0" << std::endl;
00351 return false;
00352 }
00353
00354 GlobalDirectoryRestore restore;
00355
00356 dir->cd();
00357
00358
00359 cout << "-> " << dir->GetPath() << " "
00360 << dir->GetListOfKeys()->GetSize() << endl;
00361
00362
00363 TIter nextkey(dir->GetList());
00364 while (TKey *key = (TKey*)nextkey()) {
00365
00366 TObject *obj = key->ReadObj();
00367 if (obj == 0) { cout << key->GetName() << " obj==0"<< endl; continue; }
00368
00369 cout << " Key: " << key->GetName() << " "
00370 << " tit: " << obj->GetTitle() << " "
00371 << " (" << key->GetClassName() << ")" << endl;
00372
00373 }
00374
00375 nextkey = dir->GetListOfKeys();
00376 while (TKey *key = (TKey*)nextkey()) {
00377
00378 TObject *obj = key->ReadObj();
00379 if (obj == 0) { cout << key->GetName() << " obj==0"<< endl; continue; }
00380 if (obj->IsA()->InheritsFrom("TDirectory")) {
00381 TDirectory *tt = dynamic_cast<TDirectory*>(obj);
00382 browseTDir(tt);
00383 }
00384 }
00385
00386 return true;
00387 }
00388
00389
00390
00391
00392 StatusCode
00393 THistSvc::getTHists(TDirectory *td, TList & tl, bool rcs) const {
00394 GlobalDirectoryRestore restore;
00395
00396 gErrorIgnoreLevel = kBreak;
00397
00398 if (!td->cd()) {
00399 m_log << MSG::ERROR << "getTHists: No such TDirectory \"" << td->GetPath()
00400 << "\"" << endmsg;
00401 return StatusCode::FAILURE;
00402 }
00403
00404 if (m_log.level() <= MSG::DEBUG)
00405 m_log << MSG::DEBUG << "getTHists: \"" << td->GetPath() << "\": found "
00406 << td->GetListOfKeys()->GetSize() << " keys" << endmsg;
00407
00408 TIter nextkey(td->GetListOfKeys());
00409 while (TKey *key = (TKey*)nextkey()) {
00410 if (m_log.level() <= MSG::DEBUG)
00411 m_log << MSG::DEBUG << " key: " << key->GetName();
00412 TObject *obj = key->ReadObj();
00413 if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00414 if (m_log.level() <= MSG::DEBUG)
00415 m_log << " (" << obj->IsA()->GetName() << ")";
00416 } else if (obj != 0 && obj->IsA()->InheritsFrom("TH1")) {
00417 if (m_log.level() <= MSG::DEBUG)
00418 m_log << " (" << obj->IsA()->GetName() << ")";
00419 tl.Add(obj);
00420 } else if (obj != 0) {
00421 if (m_log.level() <= MSG::DEBUG)
00422 m_log << " [" << obj->IsA()->GetName() << "]";
00423 }
00424 if (m_log.level() <= MSG::DEBUG)
00425 m_log << endmsg;
00426 }
00427
00428
00429 if (rcs) {
00430 nextkey = td->GetListOfKeys();
00431 while (TKey *key = (TKey*)nextkey()) {
00432 TObject *obj = key->ReadObj();
00433 if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00434 TDirectory *tt = dynamic_cast<TDirectory*>(obj);
00435 getTHists(tt, tl, rcs);
00436 }
00437 }
00438 }
00439
00440 return StatusCode::SUCCESS;
00441
00442
00443 }
00444
00445
00446
00447 StatusCode
00448 THistSvc::getTHists(const std::string& dir, TList & tl, bool rcs) const {
00449
00450 GlobalDirectoryRestore restore;
00451
00452 gErrorIgnoreLevel = kBreak;
00453
00454 StatusCode sc;
00455
00456 std::string stream,rem,r2;
00457 parseString(dir,stream,rem);
00458
00459 map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
00460 if (itr != m_files.end()) {
00461 r2 = itr->second.first->GetName();
00462 r2 += ":/";
00463 r2 += rem;
00464
00465 if (m_log.level() <= MSG::DEBUG)
00466 m_log << MSG::DEBUG << "getTHists: \"" << dir
00467 << "\" looks like a stream name." << " associated TFile: \""
00468 << itr->second.first->GetName() << "\"" << endmsg;
00469
00470 if (gDirectory->cd(r2.c_str())) {
00471 m_curstream = stream;
00472 sc = getTHists(gDirectory,tl,rcs);
00473 m_curstream = "";
00474 return sc;
00475 } else {
00476 if (m_log.level() <= MSG::DEBUG)
00477 m_log << MSG::DEBUG << "getTHists: no such TDirectory \""
00478 << r2 << "\"" << endmsg;
00479 }
00480
00481 } else {
00482 if (m_log.level() <= MSG::DEBUG)
00483 m_log << MSG::DEBUG << "getTHists: stream \"" << stream << "\" not found"
00484 << endmsg;
00485 }
00486
00487 if (!gDirectory->cd(dir.c_str())) {
00488 m_log << MSG::ERROR << "getTHists: No such TDirectory/stream \"" << dir
00489 << "\"" << endmsg;
00490 sc = StatusCode::FAILURE;
00491 } else {
00492 sc = getTHists(gDirectory,tl,rcs);
00493 }
00494
00495 return sc;
00496
00497 }
00498
00499
00500 StatusCode
00501 THistSvc::getTTrees(TDirectory *td, TList & tl, bool rcs) const {
00502 GlobalDirectoryRestore restore;
00503
00504 gErrorIgnoreLevel = kBreak;
00505
00506 if (!td->cd()) {
00507 m_log << MSG::ERROR << "getTTrees: No such TDirectory \""
00508 << td->GetPath() << "\"" << endmsg;
00509 return StatusCode::FAILURE;
00510 }
00511
00512 if (m_log.level() <= MSG::DEBUG)
00513 m_log << MSG::DEBUG << "getTHists: \"" << td->GetPath() << "\": found "
00514 << td->GetListOfKeys()->GetSize() << " keys" << endmsg;
00515
00516 TIter nextkey(td->GetListOfKeys());
00517 while (TKey *key = (TKey*)nextkey()) {
00518 if (m_log.level() <= MSG::DEBUG)
00519 m_log << MSG::DEBUG << " key: " << key->GetName();
00520 TObject *obj = key->ReadObj();
00521 if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00522 if (m_log.level() <= MSG::DEBUG)
00523 m_log << " (" << obj->IsA()->GetName() << ")";
00524 } else if (obj != 0 && obj->IsA()->InheritsFrom("TTree")) {
00525 if (m_log.level() <= MSG::DEBUG)
00526 m_log << " (" << obj->IsA()->GetName() << ")";
00527 tl.Add(obj);
00528 } else if (obj != 0) {
00529 if (m_log.level() <= MSG::DEBUG)
00530 m_log << " [" << obj->IsA()->GetName() << "]";
00531 }
00532 m_log << endmsg;
00533 }
00534
00535
00536 if (rcs) {
00537 nextkey = td->GetListOfKeys();
00538 while (TKey *key = (TKey*)nextkey()) {
00539 TObject *obj = key->ReadObj();
00540 if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00541 TDirectory *tt = dynamic_cast<TDirectory*>(obj);
00542 getTTrees(tt, tl, rcs);
00543 }
00544 }
00545 }
00546
00547 return StatusCode::SUCCESS;
00548
00549 }
00550
00551
00552
00553 StatusCode
00554 THistSvc::getTTrees(const std::string& dir, TList & tl, bool rcs) const {
00555 GlobalDirectoryRestore restore;
00556
00557 gErrorIgnoreLevel = kBreak;
00558
00559 StatusCode sc;
00560
00561 std::string stream,rem,r2;
00562 parseString(dir,stream,rem);
00563
00564 map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
00565 if (itr != m_files.end()) {
00566 r2 = itr->second.first->GetName();
00567 r2 += ":/";
00568 r2 += rem;
00569
00570 if (m_log.level() <= MSG::DEBUG)
00571 m_log << MSG::DEBUG << "getTTrees: \"" << dir
00572 << "\" looks like a stream name." << " associated TFile: \""
00573 << itr->second.first->GetName() << "\"" << endmsg;
00574
00575 if (gDirectory->cd(r2.c_str())) {
00576 return getTTrees(gDirectory,tl,rcs);
00577 } else {
00578 if (m_log.level() <= MSG::DEBUG)
00579 m_log << MSG::DEBUG << "getTTrees: no such TDirectory \""
00580 << r2 << "\"" << endmsg;
00581 }
00582
00583 } else {
00584 if (m_log.level() <= MSG::DEBUG)
00585 m_log << MSG::DEBUG << "getTTrees: stream \"" << stream << "\" not found"
00586 << endmsg;
00587 }
00588
00589 if (!gDirectory->cd(dir.c_str())) {
00590 m_log << MSG::ERROR << "getTTrees: No such TDirectory/stream \"" << dir
00591 << "\"" << endmsg;
00592 sc = StatusCode::FAILURE;
00593 } else {
00594 sc = getTTrees(gDirectory,tl,rcs);
00595 }
00596
00597 return sc;
00598
00599
00600 }
00601
00602
00603
00604
00605 StatusCode
00606 THistSvc::getTHists(TDirectory *td, TList & tl, bool rcs, bool reg) {
00607
00608 GlobalDirectoryRestore restore;
00609
00610 gErrorIgnoreLevel = kBreak;
00611
00612 if (!td->cd()) {
00613 m_log << MSG::ERROR << "getTHists: No such TDirectory \"" << td->GetPath()
00614 << "\"" << endmsg;
00615 return StatusCode::FAILURE;
00616 }
00617
00618 if (m_log.level() <= MSG::DEBUG)
00619 m_log << MSG::DEBUG << "getTHists: \"" << td->GetPath() << "\": found "
00620 << td->GetListOfKeys()->GetSize() << " keys" << endmsg;
00621
00622 TIter nextkey(td->GetListOfKeys());
00623 while (TKey *key = (TKey*)nextkey()) {
00624 if (m_log.level() <= MSG::DEBUG)
00625 m_log << MSG::DEBUG << " key: " << key->GetName();
00626 TObject *obj = key->ReadObj();
00627 if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00628 if (m_log.level() <= MSG::DEBUG)
00629 m_log << " (" << obj->IsA()->GetName() << ")";
00630 } else if (obj != 0 && obj->IsA()->InheritsFrom("TH1")) {
00631 if (m_log.level() <= MSG::DEBUG)
00632 m_log << " (" << obj->IsA()->GetName() << ")";
00633 tl.Add(obj);
00634 if (reg && m_curstream != "") {
00635 string dir = td->GetPath();
00636 string fil = td->GetFile()->GetName();
00637 dir.erase(0,fil.length()+1);
00638 string id = "/" + m_curstream;
00639 if ( dir == "/" ) {
00640 id = id + "/" + key->GetName();
00641 } else {
00642 id = id + dir + "/" + key->GetName();
00643 }
00644 if (!exists(id)) {
00645 if (m_log.level() <= MSG::DEBUG)
00646 m_log << " reg as \"" << id << "\"";
00647 regHist(id).ignore();
00648 } else {
00649 if (m_log.level() <= MSG::DEBUG)
00650 m_log << " already registered";
00651 }
00652 }
00653 } else if (obj != 0) {
00654 if (m_log.level() <= MSG::DEBUG)
00655 m_log << " [" << obj->IsA()->GetName() << "]";
00656 }
00657 if (m_log.level() <= MSG::DEBUG)
00658 m_log << endmsg;
00659 }
00660
00661
00662 if (rcs) {
00663 nextkey = td->GetListOfKeys();
00664 while (TKey *key = (TKey*)nextkey()) {
00665 TObject *obj = key->ReadObj();
00666 if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00667 TDirectory *tt = dynamic_cast<TDirectory*>(obj);
00668 getTHists(tt, tl, rcs, reg);
00669 }
00670 }
00671 }
00672
00673 return StatusCode::SUCCESS;
00674
00675 }
00676
00677
00678
00679 StatusCode
00680 THistSvc::getTHists(const std::string& dir, TList & tl, bool rcs, bool reg) {
00681
00682 GlobalDirectoryRestore restore;
00683
00684 gErrorIgnoreLevel = kBreak;
00685
00686 StatusCode sc;
00687
00688 std::string stream,rem,r2;
00689 parseString(dir,stream,rem);
00690
00691 map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
00692 if (itr != m_files.end()) {
00693 r2 = itr->second.first->GetName();
00694 r2 += ":/";
00695 r2 += rem;
00696
00697 if (m_log.level() <= MSG::DEBUG)
00698 m_log << MSG::DEBUG << "getTHists: \"" << dir
00699 << "\" looks like a stream name." << " associated TFile: \""
00700 << itr->second.first->GetName() << "\"" << endmsg;
00701
00702 if (gDirectory->cd(r2.c_str())) {
00703 m_curstream = stream;
00704 sc = getTHists(gDirectory,tl,rcs,reg);
00705 m_curstream = "";
00706 return sc;
00707 } else {
00708 if (m_log.level() <= MSG::DEBUG)
00709 m_log << MSG::DEBUG << "getTHists: no such TDirectory \""
00710 << r2 << "\"" << endmsg;
00711 }
00712
00713 } else {
00714 if (m_log.level() <= MSG::DEBUG)
00715 m_log << MSG::DEBUG << "getTHists: stream \"" << stream << "\" not found"
00716 << endmsg;
00717 }
00718
00719 if (!gDirectory->cd(dir.c_str())) {
00720 m_log << MSG::ERROR << "getTHists: No such TDirectory/stream \"" << dir
00721 << "\"" << endmsg;
00722 sc = StatusCode::FAILURE;
00723 } else {
00724 if (reg) {
00725 m_log << MSG::WARNING << "Unable to register histograms automatically "
00726 << "without a valid stream name" << endmsg;
00727 reg = false;
00728 }
00729 sc = getTHists(gDirectory,tl,rcs,reg);
00730 }
00731
00732 return sc;
00733
00734 }
00735
00736
00737 StatusCode
00738 THistSvc::getTTrees(TDirectory *td, TList & tl, bool rcs, bool reg) {
00739
00740 GlobalDirectoryRestore restore;
00741
00742 gErrorIgnoreLevel = kBreak;
00743
00744 if (!td->cd()) {
00745 m_log << MSG::ERROR << "getTTrees: No such TDirectory \""
00746 << td->GetPath() << "\"" << endmsg;
00747 return StatusCode::FAILURE;
00748 }
00749
00750 if (m_log.level() <= MSG::DEBUG)
00751 m_log << MSG::DEBUG << "getTHists: \"" << td->GetPath() << "\": found "
00752 << td->GetListOfKeys()->GetSize() << " keys" << endmsg;
00753
00754 TIter nextkey(td->GetListOfKeys());
00755 while (TKey *key = (TKey*)nextkey()) {
00756 if (m_log.level() <= MSG::DEBUG)
00757 m_log << MSG::DEBUG << " key: " << key->GetName();
00758 TObject *obj = key->ReadObj();
00759 if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00760 if (m_log.level() <= MSG::DEBUG)
00761 m_log << " (" << obj->IsA()->GetName() << ")";
00762 } else if (obj != 0 && obj->IsA()->InheritsFrom("TTree")) {
00763 if (m_log.level() <= MSG::DEBUG)
00764 m_log << " (" << obj->IsA()->GetName() << ")";
00765 tl.Add(obj);
00766 if (reg && m_curstream != "") {
00767 string dir = td->GetPath();
00768 string fil = td->GetFile()->GetName();
00769 dir.erase(0,fil.length()+1);
00770 string id = "/" + m_curstream;
00771 if ( dir == "/" ) {
00772 id = id + "/" + key->GetName();
00773 } else {
00774 id = id + dir + "/" + key->GetName();
00775 }
00776 if (!exists(id)) {
00777 if (m_log.level() <= MSG::DEBUG)
00778 m_log << " reg as \"" << id << "\"";
00779 regHist(id).ignore();
00780 } else {
00781 if (m_log.level() <= MSG::DEBUG)
00782 m_log << " already registered";
00783 }
00784 }
00785 } else if (obj != 0) {
00786 if (m_log.level() <= MSG::DEBUG)
00787 m_log << " [" << obj->IsA()->GetName() << "]";
00788 }
00789 if (m_log.level() <= MSG::DEBUG)
00790 m_log << endmsg;
00791 }
00792
00793
00794 if (rcs) {
00795 nextkey = td->GetListOfKeys();
00796 while (TKey *key = (TKey*)nextkey()) {
00797 TObject *obj = key->ReadObj();
00798 if (obj != 0 && obj->IsA()->InheritsFrom("TDirectory")) {
00799 TDirectory *tt = dynamic_cast<TDirectory*>(obj);
00800 getTTrees(tt, tl, rcs, reg);
00801 }
00802 }
00803 }
00804
00805 return StatusCode::SUCCESS;
00806
00807 }
00808
00809
00810
00811 StatusCode
00812 THistSvc::getTTrees(const std::string& dir, TList & tl, bool rcs, bool reg) {
00813
00814 GlobalDirectoryRestore restore;
00815
00816 gErrorIgnoreLevel = kBreak;
00817
00818 StatusCode sc;
00819
00820 std::string stream,rem,r2;
00821 parseString(dir,stream,rem);
00822
00823 map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
00824 if (itr != m_files.end()) {
00825 r2 = itr->second.first->GetName();
00826 r2 += ":/";
00827 r2 += rem;
00828
00829 if (m_log.level() <= MSG::DEBUG)
00830 m_log << MSG::DEBUG << "getTTrees: \"" << dir
00831 << "\" looks like a stream name." << " associated TFile: \""
00832 << itr->second.first->GetName() << "\"" << endmsg;
00833
00834 if (gDirectory->cd(r2.c_str())) {
00835 return getTTrees(gDirectory,tl,rcs,reg);
00836 } else {
00837 if (m_log.level() <= MSG::DEBUG)
00838 m_log << MSG::DEBUG << "getTTrees: no such TDirectory \""
00839 << r2 << "\"" << endmsg;
00840 }
00841
00842 } else {
00843 if (m_log.level() <= MSG::DEBUG)
00844 m_log << MSG::DEBUG << "getTTrees: stream \"" << stream << "\" not found"
00845 << endmsg;
00846 }
00847
00848 if (!gDirectory->cd(dir.c_str())) {
00849 m_log << MSG::ERROR << "getTTrees: No such TDirectory/stream \"" << dir
00850 << "\"" << endmsg;
00851 sc = StatusCode::FAILURE;
00852 } else {
00853 sc = getTTrees(gDirectory,tl,rcs,reg);
00854 }
00855
00856 return sc;
00857
00858 }
00859
00860
00861
00862 StatusCode
00863 THistSvc::deReg(TObject* obj) {
00864
00865 objMap::iterator itr = m_tobjs.find(obj);
00866 if (itr != m_tobjs.end()) {
00867 THistID hid = itr->second;
00868
00869 uidMap::iterator itr2 = m_uids.find(hid.id);
00870 if (itr2 == m_uids.end()) {
00871 m_log << MSG::ERROR << "Problems deregistering TObject \""
00872 << obj->GetName()
00873 << "\" with id \"" << hid.id << "\"" << endmsg;
00874 return StatusCode::FAILURE;
00875 }
00876
00877 std::string id,root,rem;
00878 parseString(hid.id, root, rem);
00879
00880 idMap::iterator itr3;
00881 bool found(false);
00882
00883 std::pair<idMap::iterator, idMap::iterator> mitr = m_ids.equal_range(rem);
00884 if (mitr.first == mitr.second) {
00885 m_log << MSG::ERROR << "Problems deregistering TObject \""
00886 << obj->GetName()
00887 << "\" with id \"" << hid.id << "\"" << endmsg;
00888 return StatusCode::FAILURE;
00889 } else {
00890 for (itr3 = mitr.first; itr3 != mitr.second; ++itr3) {
00891 if (itr3->second.obj == obj) {
00892 found = true;
00893 break;
00894 }
00895 }
00896 if (!found) {
00897 m_log << MSG::ERROR << "Problems deregistering TObject \""
00898 << obj->GetName()
00899 << "\" with id \"" << hid.id << "\"" << endmsg;
00900 }
00901 }
00902
00903 m_tobjs.erase(itr);
00904 m_uids.erase(itr2);
00905 m_ids.erase(itr3);
00906
00907 return StatusCode::SUCCESS;
00908
00909 } else {
00910 m_log << MSG::ERROR << "Cannot unregister TObject \"" << obj->GetName()
00911 << "\": not known to THistSvc" << endmsg;
00912 return StatusCode::FAILURE;
00913 }
00914
00915 }
00916
00917
00918
00919
00920 StatusCode
00921 THistSvc::deReg(const std::string& id) {
00922
00923 uidMap::iterator itr = m_uids.find(id);
00924 if (itr == m_uids.end()) {
00925 m_log << MSG::ERROR << "Problems deregistering id \""
00926 << id << "\"" << endmsg;
00927 return StatusCode::FAILURE;
00928 }
00929
00930 TObject* obj = itr->second.obj;
00931
00932 return deReg(obj);
00933 }
00934
00935
00936
00937 StatusCode
00938 THistSvc::regHist(const std::string& id) {
00939
00940 TH1 *hist(0);
00941
00942 return regHist_i(hist, id);
00943 }
00944
00945
00946
00947 StatusCode
00948 THistSvc::regHist(const std::string& id, TH1* hist) {
00949 return regHist_i(hist, id);
00950 }
00951
00952
00953
00954 StatusCode
00955 THistSvc::regHist(const std::string& id, TH2* hist) {
00956 return regHist_i(hist, id);
00957 }
00958
00959
00960
00961 StatusCode
00962 THistSvc::regHist(const std::string& id, TH3* hist) {
00963 return regHist_i(hist, id);
00964 }
00965
00966
00967
00968 StatusCode
00969 THistSvc::regTree(const std::string& id) {
00970 TTree *hist(0);
00971 return regHist_i(hist, id);
00972 }
00973
00974
00975
00976 StatusCode
00977 THistSvc::regTree(const std::string& id, TTree* hist) {
00978 StatusCode sc = regHist_i(hist, id);
00979 if (hist != 0 && sc.isSuccess()) {
00980 if (m_autoSave != 0)
00981 hist->SetAutoSave(m_autoSave);
00982 hist->SetAutoFlush(m_autoFlush);
00983 }
00984 return sc;
00985 }
00986
00987
00988
00989 StatusCode
00990 THistSvc::regGraph(const std::string& id) {
00991 TGraph *hist(0);
00992 return regHist_i(hist, id);
00993 }
00994
00995
00996
00997 StatusCode
00998 THistSvc::regGraph(const std::string& id, TGraph* hist) {
00999 if ( strcmp(hist->GetName(),"Graph") == 0 ) {
01000
01001 std::string id2(id);
01002 string::size_type i = id2.rfind("/");
01003 if (i != string::npos) {
01004 id2.erase(0,i+1);
01005 }
01006
01007 m_log << MSG::INFO << "setting name of TGraph id: \"" << id << "\" to \""
01008 << id2 << "\" since it is unset" << endmsg;
01009 hist->SetName(id2.c_str());
01010 }
01011
01012 return regHist_i(hist, id);
01013 }
01014
01015
01016
01017 StatusCode
01018 THistSvc::getHist(const std::string& id, TH1*& hist) const {
01019 return getHist_i(id, hist);
01020 }
01021
01022
01023
01024 StatusCode
01025 THistSvc::getHist(const std::string& id, TH2*& hist) const {
01026 return getHist_i(id, hist);
01027 }
01028
01029
01030
01031 StatusCode
01032 THistSvc::getHist(const std::string& id, TH3*& hist) const {
01033 return getHist_i(id, hist);
01034 }
01035
01036
01037
01038 std::vector<std::string>
01039 THistSvc::getHists() const {
01040
01041 std::vector<std::string> names;
01042 names.reserve(m_uids.size());
01043
01044 uidMap::const_iterator itr;
01045 for (itr = m_uids.begin(); itr != m_uids.end(); ++itr) {
01046 THistID tid = itr->second;
01047
01048 if (tid.obj->IsA()->InheritsFrom("TH1")) {
01049 names.push_back(itr->first);
01050 }
01051
01052 }
01053
01054 return names;
01055
01056 }
01057
01058
01059 StatusCode
01060 THistSvc::getTree(const std::string& id, TTree*& hist) const {
01061 return getHist_i(id, hist);
01062 }
01063
01064
01065
01066 std::vector<std::string>
01067 THistSvc::getTrees() const {
01068
01069 std::vector<std::string> names;
01070 names.reserve(m_uids.size());
01071
01072 uidMap::const_iterator itr;
01073 for (itr = m_uids.begin(); itr != m_uids.end(); ++itr) {
01074 THistID tid = itr->second;
01075
01076 if (tid.obj->IsA()->InheritsFrom("TTree")) {
01077 names.push_back(itr->first);
01078 }
01079
01080 }
01081
01082 return names;
01083
01084 }
01085
01086
01087 StatusCode
01088 THistSvc::getGraph(const std::string& id, TGraph*& hist) const {
01089 return getHist_i(id, hist);
01090 }
01091
01092
01093
01094 std::vector<std::string>
01095 THistSvc::getGraphs() const {
01096
01097 std::vector<std::string> names;
01098 names.reserve(m_uids.size());
01099
01100 uidMap::const_iterator itr;
01101 for (itr = m_uids.begin(); itr != m_uids.end(); ++itr) {
01102 THistID tid = itr->second;
01103
01104 if (tid.obj->IsA()->InheritsFrom("TGraph")) {
01105 names.push_back(itr->first);
01106 }
01107
01108 }
01109
01110 return names;
01111
01112 }
01113
01114
01115 StatusCode
01116 THistSvc::readHist(const std::string& id, TH1*& hist) const {
01117 return readHist_i(id, hist);
01118 }
01119
01120
01121
01122 StatusCode
01123 THistSvc::readHist(const std::string& id, TH2*& hist) const {
01124 return readHist_i(id, hist);
01125 }
01126
01127
01128
01129 StatusCode
01130 THistSvc::readHist(const std::string& id, TH3*& hist) const {
01131 return readHist_i(id, hist);
01132 }
01133
01134
01135
01136 StatusCode
01137 THistSvc::readTree(const std::string& id, TTree*& hist) const {
01138 return readHist_i(id, hist);
01139 }
01140
01141
01142
01143 bool
01144 THistSvc::findStream(const string& id, string& stream, string& rem,
01145 TFile*& file) const {
01146
01147 string::size_type pos = id.find("/");
01148
01149 if (pos == string::npos) {
01150 stream = "temp";
01151 rem = id;
01152 } else if (pos != 0) {
01153 stream = "temp";
01154 rem = id;
01155 } else {
01156
01157 string::size_type pos2 = id.find("/",pos+1);
01158
01159 if (pos2 == string::npos) {
01160 m_log << MSG::ERROR << "badly formed Hist/Tree id: \"" << id << "\""
01161 << endmsg;
01162 return false;
01163 }
01164
01165 parseString(id,stream,rem);
01166
01167 }
01168
01169 if (stream == "temp") {
01170 file = 0;
01171 return true;
01172 }
01173
01174 map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream);
01175 if (itr != m_files.end()) {
01176 file = itr->second.first;
01177 } else {
01178 file = 0;
01179 m_log << MSG::WARNING << "no stream \"" << stream
01180 << "\" associated with id: \"" << id << "\""
01181 << endmsg;
01182 }
01183
01184 return true;
01185
01186 }
01187
01188
01189
01190 void
01191 THistSvc::parseString(const string& id, string& root, string& rem) const {
01192 string::size_type pos = id.find("/");
01193
01194 if (pos == string::npos) {
01195 root = "";
01196 rem = id;
01197 return;
01198 }
01199
01200 if (pos == 0) {
01201 parseString(id.substr(1,id.length()),root,rem);
01202 } else {
01203 root = id.substr(0,pos);
01204 rem = id.substr(pos+1,id.length());
01205 }
01206
01207 }
01208
01209
01210
01211 void
01212 THistSvc::setupCompressionLevel( Property& )
01213 {
01214
01215 m_log << MSG::WARNING << "\"CompressionLevel\" Property has been deprecated. "
01216 << "Set it via the \"CL=\" parameter in the \"Output\" Property"
01217 << endmsg;
01218
01219 }
01220
01221
01222
01223
01224 void
01225 THistSvc::setupInputFile( Property& )
01226 {
01227 StatusCode sc = StatusCode::SUCCESS;
01228
01229 typedef std::vector<std::string> Strings_t;
01230 for ( Strings_t::const_iterator
01231 itr = m_inputfile.value().begin(),
01232 iEnd = m_inputfile.value().end();
01233 itr != iEnd;
01234 ++itr ) {
01235 if ( m_alreadyConnectedInFiles.end() ==
01236 m_alreadyConnectedInFiles.find( *itr ) ) {
01237 if ( connect(*itr).isFailure() ) {
01238 sc = StatusCode::FAILURE;
01239 } else {
01240 m_alreadyConnectedInFiles.insert( *itr );
01241 }
01242 }
01243 }
01244
01245 if ( !sc.isSuccess() ) {
01246 throw GaudiException( "Problem connecting inputfile !!", name(),
01247 StatusCode::FAILURE );
01248 }
01249 return;
01250 }
01251
01252
01253
01254 void
01255 THistSvc::setupOutputFile( Property& )
01256 {
01257 StatusCode sc = StatusCode::SUCCESS;
01258
01259 typedef std::vector<std::string> Strings_t;
01260 for ( Strings_t::const_iterator
01261 itr = m_outputfile.value().begin(),
01262 iEnd = m_outputfile.value().end();
01263 itr != iEnd;
01264 ++itr ) {
01265 if ( m_alreadyConnectedOutFiles.end() ==
01266 m_alreadyConnectedOutFiles.find( *itr ) ) {
01267 if ( connect(*itr).isFailure() ) {
01268 sc = StatusCode::FAILURE;
01269 } else {
01270 m_alreadyConnectedOutFiles.insert( *itr );
01271 }
01272 }
01273 }
01274
01275 if ( !sc.isSuccess() ) {
01276 throw GaudiException( "Problem connecting outputfile !!", name(),
01277 StatusCode::FAILURE );
01278 }
01279 return;
01280 }
01281
01282
01283
01284 void
01285 THistSvc::updateFiles() {
01286
01287
01288
01289
01290
01291
01292 uidMap::iterator uitr, uitr2;
01293 for (uitr=m_uids.begin(); uitr != m_uids.end(); ++uitr) {
01294 TObject* to = uitr->second.obj;
01295 TFile* oldFile = uitr->second.file;
01296 if (to->IsA()->InheritsFrom("TTree")) {
01297 TTree* tr = dynamic_cast<TTree*>(to);
01298 TFile* newFile = tr->GetCurrentFile();
01299
01300 if (oldFile != newFile) {
01301 std::string newFileName = newFile->GetName();
01302 std::string oldFileName(""), streamName, rem;
01303 TFile* dummy;
01304 findStream(uitr->second.id, streamName, rem, dummy);
01305
01306 map<string, pair<TFile*,Mode> >::iterator itr;
01307 for (itr=m_files.begin(); itr!= m_files.end(); ++itr) {
01308 if (itr->second.first == oldFile) {
01309 itr->second.first = newFile;
01310
01311 }
01312 }
01313
01314 uitr2 = uitr;
01315 for (; uitr2 != m_uids.end(); ++uitr2) {
01316 if (uitr2->second.file == oldFile) {
01317 uitr2->second.file = newFile;
01318 }
01319 }
01320
01321 streamMap::iterator sitr;
01322 for (sitr = m_fileStreams.begin(); sitr!=m_fileStreams.end(); ++sitr) {
01323 if (sitr->second == streamName) {
01324 oldFileName = sitr->first;
01325 break;
01326 }
01327 }
01328
01329
01330 #ifndef NDEBUG
01331 if (m_log.level() <= MSG::DEBUG)
01332 m_log << MSG::DEBUG << "migrating uid: " << uitr->second.id
01333 << " stream: " << streamName
01334 << " oldFile: " << oldFileName
01335 << " newFile: " << newFileName
01336 << endmsg;
01337 #endif
01338
01339
01340 if (oldFileName != "") {
01341 while ( (sitr=m_fileStreams.find(oldFileName)) != m_fileStreams.end() ) {
01342
01343 #ifndef NDEBUG
01344 if (m_log.level() <= MSG::DEBUG)
01345 m_log << MSG::DEBUG << "changing filename \"" << oldFileName
01346 << "\" to \"" << newFileName << "\" for stream \""
01347 << sitr->second << "\"" << endmsg;
01348 #endif
01349 m_fileStreams.erase(sitr);
01350 m_fileStreams.insert( make_pair<std::string,std::string>(newFileName,streamName) );
01351 }
01352
01353
01354 } else {
01355 m_log << MSG::ERROR
01356 << "Problems updating fileStreams with new file name" << endmsg;
01357 }
01358
01359 }
01360
01361 }
01362 }
01363
01364 }
01365
01366
01367
01368 StatusCode
01369 THistSvc::write() {
01370
01371 updateFiles();
01372
01373 map<string, pair<TFile*,Mode> >::const_iterator itr;
01374 for (itr=m_files.begin(); itr!= m_files.end(); ++itr) {
01375 if (itr->second.second == WRITE || itr->second.second == UPDATE
01376 ||itr->second.second==SHARE) {
01377 itr->second.first->Write("",TObject::kOverwrite);
01378 } else if (itr->second.second == APPEND) {
01379 itr->second.first->Write("");
01380 }
01381 }
01382
01383
01384 if (m_log.level() <= MSG::DEBUG)
01385 m_log << MSG::DEBUG << "THistSvc::write()::List of Files connected in ROOT "
01386 << endmsg;
01387
01388 TSeqCollection *filelist=gROOT->GetListOfFiles();
01389 for (int ii=0; ii<filelist->GetEntries(); ii++) {
01390 if (m_log.level() <= MSG::DEBUG)
01391 m_log << MSG::DEBUG
01392 << "THistSvc::write()::List of Files connected in ROOT: \""
01393 << filelist->At(ii)->GetName()<<"\""<<endmsg;
01394 }
01395
01396 return StatusCode::SUCCESS;
01397
01398 }
01399
01400
01401
01402 StatusCode
01403 THistSvc::connect(const std::string& ident) {
01404
01405 Tokenizer tok(true);
01406
01407 string::size_type loc = ident.find(" ");
01408 string stream = ident.substr(0,loc);
01409 char typ(0);
01410 typedef std::pair<std::string,std::string> Prop;
01411 std::vector<Prop> props;
01412 string val,VAL,TAG,filename,db_typ("ROOT");
01413 int cl(1);
01414
01415 tok.analyse(ident.substr(loc+1,ident.length()), " ", "", "", "=", "'", "'");
01416
01417 for ( Tokenizer::Items::iterator i = tok.items().begin(); i != tok.items().end(); i++) {
01418 const std::string& tag = (*i).tag();
01419 TAG = tag;
01420 toupper(TAG);
01421
01422 val = (*i).value();
01423 VAL = val;
01424 toupper(VAL);
01425
01426 if (TAG == "FILE" || TAG == "DATAFILE") {
01427 filename = val;
01428 removeDoubleSlash( filename );
01429 } else if ( TAG == "OPT" ) {
01430 if ( VAL == "APPEND" || VAL == "UPDATE" ) {
01431 typ = 'A';
01432 } else if ( VAL == "CREATE" || VAL == "NEW" || VAL == "WRITE" ) {
01433 typ = 'N';
01434 } else if ( VAL == "RECREATE" ) {
01435 typ = 'R';
01436 } else if (VAL == "SHARE") {
01437 typ = 'S';
01438 } else if ( VAL == "OLD" || VAL == "READ" ) {
01439 typ = 'O';
01440 } else {
01441 m_log << MSG::ERROR << "Unknown OPT: \"" << (*i).value() << "\""
01442 << endmsg;
01443 typ = 0;
01444 }
01445 } else if (TAG == "TYP") {
01446 db_typ = (*i).value();
01447 } else if (TAG == "CL") {
01448 cl = atoi(val.c_str());
01449 } else {
01450 props.push_back( Prop((*i).tag(), (*i).value()));
01451 }
01452
01453 }
01454
01455 if (stream == "temp") {
01456 m_log << MSG::ERROR << "in JobOption \"" << ident
01457 << "\": stream name \"temp\" reserved."
01458 << endmsg;
01459 return StatusCode::FAILURE;
01460 }
01461
01462 if (db_typ != "ROOT") {
01463 m_log << MSG::ERROR << "in JobOption \"" << ident
01464 << "\": technology type \"" << db_typ << "\" not supported."
01465 << endmsg;
01466 return StatusCode::FAILURE;
01467 }
01468
01469
01470 if (m_files.find(stream) != m_files.end()) {
01471 m_log << MSG::ERROR << "in JobOption \"" << ident
01472 << "\":\n stream \"" << stream << "\" already connected to file: \""
01473 << m_files[stream].first->GetName() << "\""
01474 << endmsg;
01475 return StatusCode::FAILURE;
01476 }
01477
01478 Mode newMode;
01479 if (typ == 'O') {
01480 newMode = THistSvc::READ;
01481 } else if (typ == 'N') {
01482 newMode = THistSvc::WRITE;
01483 } else if (typ == 'A') {
01484 newMode = THistSvc::APPEND;
01485 } else if (typ == 'R') {
01486 newMode = THistSvc::UPDATE;
01487 } else if (typ == 'S') {
01488 newMode = THistSvc::SHARE;
01489 } else {
01490
01491 m_log << MSG::ERROR << "No OPT= specified or unknown access mode in: "
01492 << ident << endmsg;
01493 return StatusCode::FAILURE;
01494 }
01495
01496
01497 if (m_fileStreams.find(filename) != m_fileStreams.end()) {
01498 std::pair<streamMap::iterator, streamMap::iterator> fitr =
01499 m_fileStreams.equal_range(filename);
01500
01501 std::string oldstream = (fitr.first)->second;
01502
01503 std::pair<TFile*,Mode> f_info = m_files[oldstream];
01504
01505 if (newMode != f_info.second) {
01506 m_log << MSG::ERROR << "in JobOption \"" << ident
01507 << "\":\n file \"" << filename << "\" already opened by stream: \""
01508 << oldstream << "\" with different access mode."
01509 << endmsg;
01510 return StatusCode::FAILURE;
01511 } else {
01512 TFile *f2 = f_info.first;
01513 m_files[stream] = make_pair<TFile*,Mode>(f2,newMode);
01514 if (m_log.level() <= MSG::DEBUG)
01515 m_log << MSG::DEBUG << "Connecting stream: \"" << stream
01516 << "\" to previously opened TFile: \"" << filename << "\""
01517 << endmsg;
01518 return StatusCode::SUCCESS;
01519 }
01520 }
01521
01522
01523 IIncidentSvc *pi(0);
01524 if (service("IncidentSvc",pi).isFailure()) {
01525 m_log << MSG::ERROR << "Unable to get the IncidentSvc" << endmsg;
01526 return StatusCode::FAILURE;
01527 }
01528
01529 TFile *f(0) ;
01530 if (newMode == THistSvc::READ) {
01531
01532
01533 try {
01534 f = TFile::Open(filename.c_str(),"READ");
01535 } catch (const std::exception& Exception) {
01536 m_log << MSG::ERROR << "exception caught while trying to open root"
01537 << " file for reading: " << Exception.what() << std::endl
01538 << " -> file probably corrupt." << endmsg;
01539 pi->fireIncident(FileIncident(name(), IncidentType::FailInputFile,
01540 filename));
01541 return StatusCode::FAILURE;
01542 } catch (...) {
01543 m_log << MSG::ERROR << "Problems opening input file \"" << filename
01544 << "\": probably corrupt" << endmsg;
01545 pi->fireIncident(FileIncident(name(), IncidentType::FailInputFile,
01546 filename));
01547 return StatusCode::FAILURE;
01548 }
01549
01550 if (!f->IsOpen()) {
01551 m_log << MSG::ERROR << "Unable to open input file \"" << filename
01552 << "\": file does not exist" << endmsg;
01553 pi->fireIncident(FileIncident(name(), IncidentType::FailInputFile,
01554 filename));
01555 return StatusCode::FAILURE;
01556 }
01557
01558
01559 pi->fireIncident(FileIncident(name(), "BeginHistFile",
01560 filename));
01561
01562
01563 } else if (newMode == THistSvc::WRITE) {
01564
01565
01566 f = TFile::Open(filename.c_str(),"NEW",stream.c_str(),cl);
01567 if (!f->IsOpen()) {
01568 m_log << MSG::ERROR << "Unable to create new output file \"" << filename
01569 << "\" for writing: file already exists" << endmsg;
01570 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01571 filename));
01572 return StatusCode::FAILURE;
01573 }
01574
01575
01576 pi->fireIncident(FileIncident(name(), "BeginHistFile",
01577 filename));
01578
01579 } else if (newMode == THistSvc::APPEND) {
01580
01581
01582 try {
01583 f = TFile::Open(filename.c_str(),"UPDATE",stream.c_str(),cl);
01584 } catch (const std::exception& Exception) {
01585 m_log << MSG::ERROR << "exception caught while trying to open root"
01586 << " file for appending: " << Exception.what() << std::endl
01587 << " -> file probably corrupt." << endmsg;
01588 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01589 filename));
01590 return StatusCode::FAILURE;
01591 } catch (...) {
01592 m_log << MSG::ERROR << "Problems opening output file \"" << filename
01593 << "\" for append: probably corrupt" << endmsg;
01594 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01595 filename));
01596 return StatusCode::FAILURE;
01597 }
01598
01599 if (!f->IsOpen()) {
01600 m_log << MSG::ERROR << "Unable to open output file \"" << filename
01601 << "\" for appending" << endmsg;
01602 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01603 filename));
01604 return StatusCode::FAILURE;
01605 }
01606 pi->fireIncident(FileIncident(name(), IncidentType::BeginOutputFile,
01607 filename));
01608
01609 } else if (newMode == THistSvc::SHARE) {
01610
01611
01612
01613
01614 static int ishared = 0;
01615 stringstream out;
01616 string realfilename=filename;
01617 out << ishared++;
01618 filename = string("tmp_THistSvc_")+out.str()+string(".root");
01619
01620 if (m_log.level() <= MSG::DEBUG)
01621 m_log << MSG::DEBUG << "Creating temp file \"" << filename
01622 << "\" and realfilename="<<realfilename << endmsg;
01623 m_sharedFiles[stream]=realfilename;
01624
01625 try {
01626 f = TFile::Open(filename.c_str(),"NEW",stream.c_str(),cl);
01627 } catch (const std::exception& Exception) {
01628 m_log << MSG::ERROR << "exception caught while trying to open root"
01629 << " file for appending: " << Exception.what() << std::endl
01630 << " -> file probably corrupt." << endmsg;
01631 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01632 filename));
01633 return StatusCode::FAILURE;
01634 } catch (...) {
01635 m_log << MSG::ERROR << "Problems opening output file \"" << filename
01636 << "\" for append: probably corrupt" << endmsg;
01637 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01638 filename));
01639 return StatusCode::FAILURE;
01640 }
01641
01642 if (!f->IsOpen()) {
01643 m_log << MSG::ERROR << "Unable to open output file \"" << filename
01644 << "\" for appending" << endmsg;
01645 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01646 filename));
01647 return StatusCode::FAILURE;
01648 }
01649 pi->fireIncident(FileIncident(name(), IncidentType::BeginOutputFile,
01650 filename));
01651
01652 } else if (newMode == THistSvc::UPDATE) {
01653
01654
01655 try {
01656 f = TFile::Open(filename.c_str(),"RECREATE",stream.c_str(),cl);
01657 } catch (const std::exception& Exception) {
01658 m_log << MSG::ERROR << "exception caught while trying to open root"
01659 << " file for updating: " << Exception.what() << std::endl
01660 << " -> file probably corrupt." << endmsg;
01661 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01662 filename));
01663 return StatusCode::FAILURE;
01664 } catch (...) {
01665 m_log << MSG::ERROR << "Problems opening output file \"" << filename
01666 << "\" for update: probably corrupt" << endmsg;
01667 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01668 filename));
01669 return StatusCode::FAILURE;
01670 }
01671
01672 if (!f->IsOpen()) {
01673 m_log << MSG::ERROR << "Unable to open output file \"" << filename
01674 << "\" for updating" << endmsg;
01675 pi->fireIncident(FileIncident(name(), IncidentType::FailOutputFile,
01676 filename));
01677 return StatusCode::FAILURE;
01678 }
01679 pi->fireIncident(FileIncident(name(), IncidentType::BeginOutputFile,
01680 filename));
01681
01682 }
01683
01684 m_files[stream] = make_pair<TFile*,Mode>(f,newMode);
01685 m_fileStreams.insert(make_pair<std::string,std::string>(filename,stream));
01686
01687 if (m_log.level() <= MSG::DEBUG)
01688 m_log << MSG::DEBUG << "Opening TFile \"" << filename << "\" stream: \""
01689 << stream << "\" mode: \"" << typ << "\"" << " comp level: " << cl
01690 << endmsg;
01691
01692 return StatusCode::SUCCESS;
01693 }
01694
01695
01696
01697 TDirectory*
01698 THistSvc::changeDir(const THistSvc::THistID& hid) const {
01699
01700 string uid = hid.id;
01701 TFile* file = hid.file;
01702 string stream, fdir, bdir, dir, id;
01703
01704 if (file != 0) {
01705 file->cd("/");
01706 } else {
01707 gROOT->cd();
01708 }
01709
01710 fdir = uid;
01711 bdir = dirname(fdir);
01712
01713 while ( (dir = dirname(fdir)) != "") {
01714 if (! gDirectory->GetKey(dir.c_str())) {
01715 gDirectory->mkdir(dir.c_str());
01716 }
01717 gDirectory->cd(dir.c_str());
01718 }
01719
01720 return gDirectory;
01721
01722 }
01723
01724
01725
01726 std::string
01727 THistSvc::dirname(std::string& dir) const {
01728
01729
01730 string::size_type i = dir.find("/");
01731
01732 if (i == string::npos) {
01733 return "";
01734 }
01735
01736 if ( i == 0 ) {
01737 dir.erase(0,1);
01738 return dirname(dir);
01739 }
01740
01741 string root = dir.substr(0,i);
01742 dir.erase(0,i);
01743
01744 return root;
01745
01746 }
01747
01748
01749
01750 THistSvc::GlobalDirectoryRestore::GlobalDirectoryRestore() {
01751 m_gd = gDirectory;
01752 m_gf = gFile;
01753 m_ge = gErrorIgnoreLevel;
01754 }
01755
01756 THistSvc::GlobalDirectoryRestore::~GlobalDirectoryRestore() {
01757 gDirectory = m_gd;
01758 gFile = m_gf;
01759 gErrorIgnoreLevel = m_ge;
01760 }
01761
01762
01763
01764 void
01765 THistSvc::removeDoubleSlash(std::string& id) const {
01766
01767 while (id.find("//") != std::string::npos) {
01768 id.replace(id.find("//"),2,"/");
01769 }
01770
01771 }
01772
01773
01774
01775 void THistSvc::MergeRootFile(TDirectory *target, TDirectory *source) {
01776
01777 if (m_log.level() <= MSG::DEBUG)
01778 m_log <<MSG::DEBUG << "Target path: " << target->GetPath() << endmsg;
01779 TString path( (char*)strstr(target->GetPath(), ":") );
01780 path.Remove( 0, 2);
01781
01782 source->cd(path);
01783 TDirectory *current_sourcedir = gDirectory;
01784
01785
01786 TList *lkeys=current_sourcedir->GetListOfKeys();
01787 int nkeys=lkeys->GetEntries();
01788 TKey *key;
01789 for (int jj=0; jj<nkeys; jj++) {
01790 key=(TKey*) lkeys->At(jj);
01791 string pathnameinsource=current_sourcedir->GetPath()+string("/")+key->GetName();
01792 if (m_log.level() <= MSG::DEBUG)
01793 m_log <<MSG::DEBUG << "Reading Key:" << pathnameinsource << endmsg;
01794
01795
01796 TObject *obj=source->Get(pathnameinsource.c_str());
01797
01798 if (obj->IsA()->InheritsFrom("TDirectory") ) {
01799
01800
01801 if (m_log.level() <= MSG::DEBUG)
01802 m_log <<MSG::DEBUG << "Found subdirectory " << obj->GetName()
01803 << endmsg;
01804
01805
01806 target->cd();
01807 TDirectory *newtargetdir =
01808 target->mkdir(obj->GetName(), obj->GetTitle() );
01809
01810 MergeRootFile(newtargetdir, source);
01811
01812 } else if (obj->IsA()->InheritsFrom("TTree")) {
01813 if (m_log.level() <= MSG::DEBUG)
01814 m_log <<MSG::DEBUG << "Found TTree " << obj->GetName() << endmsg;
01815 TTree *mytree=dynamic_cast<TTree*>(obj);
01816 int nentries=(int) mytree->GetEntries();
01817 mytree->SetBranchStatus("*",1);
01818
01819 if (m_log.level() <= MSG::DEBUG)
01820 m_log <<MSG::DEBUG << "Dumping TTree " << nentries <<" entries"
01821 << endmsg;
01822
01823
01824
01825
01826
01827
01828 target->cd();
01829 mytree->CloneTree();
01830
01831
01832
01833
01834
01835 } else if (obj) {
01836 target->cd();
01837 obj->Write(key->GetName() );
01838 }
01839
01840 }
01841
01842
01843
01844 }
01845
01846
01847
01848 bool
01849 THistSvc::exists( const std::string& name ) const {
01850
01851 TH1* h;
01852
01853 return getHist_i(name,h,true).isSuccess();
01854
01855
01856 }
01857
01858
01859
01860 void
01861 THistSvc::handle( const Incident& ) {
01862
01863 if (signaledStop) return ;
01864
01865
01866 Long64_t mfs = (Long64_t)m_maxFileSize.value() * (Long64_t)1048576;
01867 Long64_t mfs_warn = mfs * 95 / 100;
01868
01869 updateFiles();
01870
01871 map<string, pair<TFile*,Mode> >::const_iterator itr;
01872 for (itr=m_files.begin(); itr!= m_files.end(); ++itr) {
01873 TFile* tf = itr->second.first;
01874
01875 #ifndef NDEBUG
01876 if (m_log.level() <= MSG::DEBUG)
01877 m_log << MSG::DEBUG << "stream: " << itr->first << " name: "
01878 << tf->GetName() << " size: " << tf->GetSize()
01879 << endmsg;
01880 #endif
01881
01882
01883 if (tf->GetSize() > mfs) {
01884
01885 signaledStop = true;
01886
01887 m_log << MSG::FATAL << "file \"" << tf->GetName()
01888 << "\" associated with stream \"" << itr->first
01889 << "\" has exceeded the max file size of "
01890 << m_maxFileSize.value() << "MB. Terminating Job."
01891 << endmsg;
01892
01893 IEventProcessor* evt(0);
01894 if (service("ApplicationMgr", evt, true).isSuccess()) {
01895 evt->stopRun();
01896 evt->release();
01897 } else {
01898 abort();
01899 }
01900 } else if (tf->GetSize() > mfs_warn) {
01901 m_log << MSG::WARNING << "file \"" << tf->GetName()
01902 << "\" associated with stream \"" << itr->first
01903 << "\" is at 95% of its maximum allowable file size of "
01904 << m_maxFileSize.value() << "MB"
01905 << endmsg;
01906 }
01907 }
01908 }