![]() |
|
|
Generated: 18 Jul 2008 |
00001 #include "THistSvc.h" 00002 00003 #include "GaudiKernel/SvcFactory.h" 00004 #include "GaudiKernel/ISvcLocator.h" 00005 #include "GaudiKernel/MsgStream.h" 00006 #include "GaudiKernel/Tokenizer.h" 00007 #include "GaudiKernel/GaudiException.h" 00008 #include "GaudiKernel/Property.h" 00009 00010 #include "TROOT.h" 00011 #include "TFile.h" 00012 #include "TDirectory.h" 00013 #include "TKey.h" 00014 #include "TError.h" 00015 #include "TGraph.h" 00016 00017 #include <sstream> 00018 #include <streambuf> 00019 #include <cstdio> 00020 00021 using namespace std; 00022 00023 00024 DECLARE_SERVICE_FACTORY(THistSvc) 00025 00026 inline void toupper(std::string &s) 00027 { 00028 std::string::iterator it=s.begin(); 00029 while(it != s.end()) 00030 { 00031 *it = toupper(*it); 00032 it++; 00033 } 00034 } 00035 00036 00037 //*************************************************************************// 00038 00039 THistSvc::THistSvc( const std::string& name, ISvcLocator* svc ) 00040 : Service(name, svc) { 00041 00042 declareProperty ("Output", m_outputfile ); 00043 declareProperty ("Input", m_inputfile ); 00044 declareProperty ("AutoSave", m_autoSave=0 ); 00045 declareProperty ("PrintAll", m_print=false); 00046 00047 m_inputfile.declareUpdateHandler ( &THistSvc::setupInputFile, this ); 00048 m_outputfile.declareUpdateHandler( &THistSvc::setupOutputFile, this ); 00049 } 00050 00051 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00052 00053 THistSvc::~THistSvc() { 00054 00055 } 00056 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00057 00058 StatusCode THistSvc::queryInterface( const InterfaceID& riid, 00059 void** ppvInterface ) { 00060 StatusCode sc = StatusCode::FAILURE; 00061 if ( ppvInterface ) { 00062 *ppvInterface = 0; 00063 00064 if ( ITHistSvc::interfaceID().versionMatch(riid) ) { 00065 *ppvInterface = static_cast<ITHistSvc*>(this); 00066 sc = StatusCode::SUCCESS; 00067 addRef(); 00068 } 00069 else 00070 sc = Service::queryInterface( riid, ppvInterface ); 00071 } 00072 return sc; 00073 } 00074 00075 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00076 00077 StatusCode 00078 THistSvc::initialize() { 00079 m_alreadyConnectedOutFiles.clear(); 00080 m_alreadyConnectedInFiles.clear(); 00081 00082 StatusCode status = Service::initialize(); 00083 00084 GlobalDirectoryRestore restore; 00085 00086 if (status.isFailure()) { 00087 MsgStream log ( msgSvc(), name() ); 00088 log << MSG::ERROR << "initializing service" << endreq; 00089 return status; 00090 } 00091 00092 vector<string>::const_iterator itr; 00093 StatusCode st(StatusCode::SUCCESS); 00094 00095 try { 00096 setupOutputFile( m_outputfile ); 00097 } catch ( GaudiException& err ) { 00098 MsgStream msg( msgSvc(), name() ); 00099 msg << MSG::ERROR 00100 << "Caught: " << err << endreq; 00101 st = StatusCode::FAILURE; 00102 } 00103 00104 try { 00105 setupInputFile( m_inputfile ); 00106 } catch ( GaudiException& err ) { 00107 MsgStream msg( msgSvc(), name() ); 00108 msg << MSG::ERROR 00109 << "Caught: " << err << endreq; 00110 st = StatusCode::FAILURE; 00111 } 00112 00113 // Protect against multiple instances of TROOT 00114 if ( 0 == gROOT ) { 00115 static TROOT root("root","ROOT I/O"); 00116 // gDebug = 99; 00117 } else { 00118 MsgStream log ( msgSvc(), name() ); 00119 log << MSG::VERBOSE << "ROOT already initialized, debug = " 00120 << gDebug<< endreq; 00121 } 00122 00123 00124 if (st.isFailure()) { 00125 MsgStream log ( msgSvc(), name() ); 00126 log << MSG::FATAL << "Unable to initialize THistSvc" << endreq; 00127 } 00128 00129 return st; 00130 00131 } 00132 00133 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00134 00135 StatusCode 00136 THistSvc::reinitialize() { 00137 00138 GlobalDirectoryRestore restore; 00139 00140 MsgStream log ( msgSvc(), name() ); 00141 log << MSG::WARNING << "reinitialize not implemented" << endreq; 00142 00143 00144 return StatusCode::SUCCESS; 00145 00146 } 00147 00148 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00149 00150 StatusCode 00151 THistSvc::finalize() { 00152 00153 GlobalDirectoryRestore restore; 00154 00155 MsgStream log ( msgSvc(), name() ); 00156 log << MSG::DEBUG << "THistSvc::finalize" << endreq; 00157 00158 uidMap::const_iterator uitr; 00159 for (uitr=m_uids.begin(); uitr != m_uids.end(); ++uitr) { 00160 00161 TObject* to = uitr->second.obj; 00162 00163 string dirname("none"); 00164 if (to->IsA()->InheritsFrom("TTree")) { 00165 TTree* tr = dynamic_cast<TTree*>(to); 00166 if (tr->GetDirectory() != 0) { 00167 dirname = tr->GetDirectory()->GetPath(); 00168 } 00169 } else if (to->IsA()->InheritsFrom("TGraph")) { 00170 if (!uitr->second.temp) { 00171 dirname = uitr->second.file->GetPath(); 00172 string id2(uitr->second.id); 00173 id2.erase(0,id2.find("/",1)); 00174 id2.erase(id2.rfind("/"), id2.length()); 00175 if (id2.find("/") == 0) { 00176 id2.erase(0,1); 00177 } 00178 dirname += id2; 00179 } else { 00180 dirname = "/tmp"; 00181 } 00182 } else if (to->IsA()->InheritsFrom("TH1")) { 00183 TH1* th = dynamic_cast<TH1*>(to); 00184 if (th == 0) { 00185 log << MSG::ERROR << "Couldn't dcast: " << uitr->first << endreq; 00186 } else { 00187 if (th->GetDirectory() != 0) { 00188 dirname = th->GetDirectory()->GetPath(); 00189 } 00190 } 00191 } 00192 00193 MsgStream log ( msgSvc(), name() ); 00194 log << MSG::DEBUG << "uid: \"" << uitr->first << "\" temp: " 00195 << uitr->second.temp << " dir: " << dirname 00196 << endreq; 00197 00198 00199 // if (uitr->second.temp == true) { 00200 // MsgStream log ( msgSvc(), name() ); 00201 // log << MSG::INFO << "Deleting \"" << uitr->first << "\"" << endreq; 00202 // delete uitr->second.obj; 00203 // } 00204 } 00205 00206 StatusCode sc = write(); 00207 if (sc.isFailure()) { 00208 MsgStream log ( msgSvc(), name() ); 00209 log << MSG::ERROR << "problems writing histograms" << endreq; 00210 } 00211 00212 if (m_print) { 00213 log << MSG::INFO << "Listing contents of ROOT files: " << endreq; 00214 } 00215 map<string, pair<TFile*,Mode> >::const_iterator itr; 00216 for (itr = m_files.begin(); itr != m_files.end(); ++itr) { 00217 if (m_print && log.level() <= MSG::INFO) { 00218 00219 log << MSG::INFO; 00220 log << "==> File: " << itr->second.first->GetName() 00221 << " stream: " << itr->first << endreq; 00222 00223 itr->second.first->Print("base"); 00224 } 00225 00226 string tmpfn=itr->second.first->GetName(); 00227 00228 itr->second.first->Close(); 00229 00230 if (itr->second.second==SHARE) { 00231 TFile *outputfile; 00232 //Merge File 00233 try { 00234 log << MSG::DEBUG << "Openning Final Output File: " <<m_sharedFiles[itr->first].c_str()<<endreq; 00235 outputfile = new TFile(m_sharedFiles[itr->first].c_str(), "UPDATE"); 00236 } catch (const std::exception& Exception) { 00237 log << MSG::ERROR << "exception caught while trying to open root" 00238 << " file for appending: " << Exception.what() << std::endl 00239 << " -> file probably corrupt." << endreq; 00240 return StatusCode::FAILURE; 00241 } catch (...) { 00242 log << MSG::ERROR << "Problems opening output file \"" << m_sharedFiles[itr->first] 00243 << "\" for append: probably corrupt" << endreq; 00244 return StatusCode::FAILURE; 00245 } 00246 00247 log << MSG::DEBUG << "THistSvc::write()::Merging Rootfile "<<endreq; 00248 TFile *inputfile; 00249 try { 00250 log << MSG::DEBUG << "Openning again Temporary File: " <<tmpfn.c_str()<<endreq; 00251 inputfile=new TFile(tmpfn.c_str(),"READ"); 00252 } catch (const std::exception& Exception) { 00253 log << MSG::ERROR << "exception caught while trying to open root" 00254 << " file for appending: " << Exception.what() << std::endl 00255 << " -> file probably corrupt." << endreq; 00256 return StatusCode::FAILURE; 00257 } catch (...) { 00258 log << MSG::ERROR << "Problems opening output file \"" << tmpfn.c_str() 00259 << "\" for append: probably corrupt" << endreq; 00260 return StatusCode::FAILURE; 00261 } 00262 00263 MergeRootFile(outputfile, inputfile); 00264 00265 outputfile->Write(); 00266 outputfile->Close(); 00267 inputfile->Close(); 00268 00269 log << MSG::DEBUG << "Trying to remove temporary file \"" << tmpfn 00270 << "\""<<endreq; 00271 00272 std::remove(tmpfn.c_str()); 00273 } 00274 delete itr->second.first; 00275 } 00276 00277 return Service::finalize(); 00278 } 00279 00280 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00281 00282 bool 00283 THistSvc::browseTDir(TDirectory *dir) const { 00284 00285 if (dir == 0) { 00286 std::cerr << "TDirectory == 0" << std::endl; 00287 return false; 00288 } 00289 00290 GlobalDirectoryRestore restore; 00291 00292 MsgStream log(msgSvc(), name()); 00293 00294 dir->cd(); 00295 00296 00297 cout << "-> " << dir->GetPath() << " " 00298 << dir->GetListOfKeys()->GetSize() << endl; 00299 00300 // TIter nextkey(dir->GetListOfKeys()); 00301 TIter nextkey(dir->GetList()); 00302 while (TKey *key = (TKey*)nextkey()) { 00303 00304 TObject *obj = key->ReadObj(); 00305 if (obj == 0) { cout << key->GetName() << " obj==0"<< endl; continue; } 00306 // if (obj->IsA()->InheritsFrom("TDirectory")) { 00307 cout << " Key: " << key->GetName() << " " 00308 << " tit: " << obj->GetTitle() << " " 00309 << " (" << key->GetClassName() << ")" << endl; 00310 // } 00311 } 00312 00313 nextkey = dir->GetListOfKeys(); 00314 while (TKey *key = (TKey*)nextkey()) { 00315 00316 TObject *obj = key->ReadObj(); 00317 if (obj == 0) { cout << key->GetName() << " obj==0"<< endl; continue; } 00318 if (obj->IsA()->InheritsFrom("TDirectory")) { 00319 TDirectory *tt = dynamic_cast<TDirectory*>(obj); 00320 browseTDir(tt); 00321 } 00322 } 00323 00324 return true; 00325 } 00326 00327 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00328 00329 StatusCode 00330 THistSvc::getTHists(TDirectory *td, TList & tl) const { 00331 00332 MsgStream log ( msgSvc(), name() ); 00333 GlobalDirectoryRestore restore; 00334 00335 gErrorIgnoreLevel = kBreak; 00336 00337 if (!td->cd()) { 00338 log << MSG::ERROR << "No such TDirectory \"" << td->GetPath() << "\"" 00339 << endreq; 00340 return StatusCode::FAILURE; 00341 } 00342 00343 TIter nextkey(td->GetList()); 00344 while (TObject *key = (TObject*)nextkey()) { 00345 if (key != 0) { 00346 if (key->IsA()->InheritsFrom("TH1")) { tl.Add(key); } 00347 } 00348 } 00349 00350 00351 return StatusCode::SUCCESS; 00352 00353 } 00354 00355 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00356 00357 StatusCode 00358 THistSvc::getTHists(const std::string& dir, TList & tl) const { 00359 00360 MsgStream log ( msgSvc(), name() ); 00361 GlobalDirectoryRestore restore; 00362 00363 gErrorIgnoreLevel = kBreak; 00364 00365 StatusCode sc; 00366 00367 if (!gDirectory->cd(dir.c_str())) { 00368 log << MSG::ERROR << "No such TDirectory \"" << dir << "\"" 00369 << endreq; 00370 sc = StatusCode::FAILURE; 00371 } else { 00372 sc = getTHists(gDirectory,tl); 00373 } 00374 00375 return sc; 00376 00377 } 00378 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00379 00380 StatusCode 00381 THistSvc::getTTrees(TDirectory *td, TList & tl) const { 00382 00383 MsgStream log ( msgSvc(), name() ); 00384 GlobalDirectoryRestore restore; 00385 00386 gErrorIgnoreLevel = kBreak; 00387 00388 if (!td->cd()) { 00389 log << MSG::ERROR << "No such TDirectory \"" << td->GetPath() << "\"" 00390 << endreq; 00391 return StatusCode::FAILURE; 00392 } 00393 00394 TIter nextkey(td->GetList()); 00395 while (TObject *key = (TObject*)nextkey()) { 00396 if (key != 0) { 00397 if (key->IsA()->InheritsFrom("TTree")) { tl.Add(key); } 00398 } 00399 } 00400 00401 return StatusCode::SUCCESS; 00402 00403 } 00404 00405 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00406 00407 StatusCode 00408 THistSvc::getTTrees(const std::string& dir, TList & tl) const { 00409 00410 MsgStream log ( msgSvc(), name() ); 00411 GlobalDirectoryRestore restore; 00412 00413 gErrorIgnoreLevel = kBreak; 00414 00415 StatusCode sc; 00416 00417 if (!gDirectory->cd(dir.c_str())) { 00418 log << MSG::ERROR << "No such TDirectory \"" << dir << "\"" 00419 << endreq; 00420 sc = StatusCode::FAILURE; 00421 } else { 00422 sc = getTTrees(gDirectory,tl); 00423 } 00424 00425 return sc; 00426 00427 } 00428 00429 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00430 00431 StatusCode 00432 THistSvc::deReg(TObject* obj) { 00433 00434 objMap::iterator itr = m_tobjs.find(obj); 00435 if (itr != m_tobjs.end()) { 00436 THistID hid = itr->second; 00437 00438 uidMap::iterator itr2 = m_uids.find(hid.id); 00439 if (itr2 == m_uids.end()) { 00440 MsgStream log ( msgSvc(), name() ); 00441 log << MSG::ERROR << "Problems deregistering TObject \"" 00442 << obj->GetName() 00443 << "\" with id \"" << hid.id << "\"" << endreq; 00444 return StatusCode::FAILURE; 00445 } 00446 00447 std::string id,root,rem; 00448 parseString(hid.id, root, rem); 00449 00450 idMap::iterator itr3; 00451 bool found(false); 00452 00453 std::pair<idMap::iterator, idMap::iterator> mitr = m_ids.equal_range(rem); 00454 if (mitr.first == mitr.second) { 00455 MsgStream log ( msgSvc(), name() ); 00456 log << MSG::ERROR << "Problems deregistering TObject \"" 00457 << obj->GetName() 00458 << "\" with id \"" << hid.id << "\"" << endreq; 00459 return StatusCode::FAILURE; 00460 } else { 00461 for (itr3 = mitr.first; itr3 != mitr.second; ++itr3) { 00462 if (itr3->second.obj == obj) { 00463 found = true; 00464 break; 00465 } 00466 } 00467 if (!found) { 00468 MsgStream log ( msgSvc(), name() ); 00469 log << MSG::ERROR << "Problems deregistering TObject \"" 00470 << obj->GetName() 00471 << "\" with id \"" << hid.id << "\"" << endreq; 00472 } 00473 } 00474 00475 m_tobjs.erase(itr); 00476 m_uids.erase(itr2); 00477 m_ids.erase(itr3); 00478 00479 return StatusCode::SUCCESS; 00480 00481 } else { 00482 MsgStream log ( msgSvc(), name() ); 00483 log << MSG::ERROR << "Cannot unregister TObject \"" << obj->GetName() 00484 << "\": not known to THistSvc" << endreq; 00485 return StatusCode::FAILURE; 00486 } 00487 00488 } 00489 00490 00491 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00492 00493 StatusCode 00494 THistSvc::deReg(const std::string& id) { 00495 00496 uidMap::iterator itr = m_uids.find(id); 00497 if (itr == m_uids.end()) { 00498 MsgStream log ( msgSvc(), name() ); 00499 log << MSG::ERROR << "Problems deregistering id \"" 00500 << id << "\"" << endreq; 00501 return StatusCode::FAILURE; 00502 } 00503 00504 TObject* obj = itr->second.obj; 00505 00506 return deReg(obj); 00507 } 00508 00509 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00510 00511 StatusCode 00512 THistSvc::regHist(const std::string& id) { 00513 00514 TH1 *hist(0); 00515 00516 return regHist_i(hist, id); 00517 } 00518 00519 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00520 00521 StatusCode 00522 THistSvc::regHist(const std::string& id, TH1* hist) { 00523 return regHist_i(hist, id); 00524 } 00525 00526 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00527 00528 StatusCode 00529 THistSvc::regHist(const std::string& id, TH2* hist) { 00530 return regHist_i(hist, id); 00531 } 00532 00533 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00534 00535 StatusCode 00536 THistSvc::regHist(const std::string& id, TH3* hist) { 00537 return regHist_i(hist, id); 00538 } 00539 00540 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00541 00542 StatusCode 00543 THistSvc::regTree(const std::string& id) { 00544 TTree *hist(0); 00545 return regHist_i(hist, id); 00546 } 00547 00548 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00549 00550 StatusCode 00551 THistSvc::regTree(const std::string& id, TTree* hist) { 00552 StatusCode sc = regHist_i(hist, id); 00553 if (hist != 0 && m_autoSave != 0 && sc.isSuccess()) { 00554 hist->SetAutoSave(m_autoSave); 00555 } 00556 return sc; 00557 } 00558 00559 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00560 00561 StatusCode 00562 THistSvc::regGraph(const std::string& id) { 00563 TGraph *hist(0); 00564 return regHist_i(hist, id); 00565 } 00566 00567 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00568 00569 StatusCode 00570 THistSvc::regGraph(const std::string& id, TGraph* hist) { 00571 if ( strcmp(hist->GetName(),"Graph") == 0 ) { 00572 00573 std::string id2(id); 00574 string::size_type i = id2.rfind("/"); 00575 if (i != string::npos) { 00576 id2.erase(0,i+1); 00577 } 00578 00579 MsgStream log ( msgSvc(), name() ); 00580 log << MSG::INFO << "setting name of TGraph id: \"" << id << "\" to \"" 00581 << id2 << "\" since it is unset" << endreq; 00582 hist->SetName(id2.c_str()); 00583 } 00584 00585 return regHist_i(hist, id); 00586 } 00587 00588 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00589 00590 StatusCode 00591 THistSvc::getHist(const std::string& id, TH1*& hist) const { 00592 return getHist_i(id, hist); 00593 } 00594 00595 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00596 00597 StatusCode 00598 THistSvc::getHist(const std::string& id, TH2*& hist) const { 00599 return getHist_i(id, hist); 00600 } 00601 00602 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00603 00604 StatusCode 00605 THistSvc::getHist(const std::string& id, TH3*& hist) const { 00606 return getHist_i(id, hist); 00607 } 00608 00609 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00610 00611 std::vector<std::string> 00612 THistSvc::getHists() const { 00613 00614 std::vector<std::string> names; 00615 00616 uidMap::const_iterator itr; 00617 for (itr = m_uids.begin(); itr != m_uids.end(); ++itr) { 00618 std::string id = itr->first; 00619 THistID tid = itr->second; 00620 00621 if (tid.obj->IsA()->InheritsFrom("TH1")) { 00622 // TTree *tr = dynamic_cast<TTree*>(tid.obj); 00623 // if (tr == 0) { 00624 names.push_back(id); 00625 } 00626 00627 } 00628 00629 return names; 00630 00631 00632 } 00633 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00634 00635 StatusCode 00636 THistSvc::getTree(const std::string& id, TTree*& hist) const { 00637 return getHist_i(id, hist); 00638 } 00639 00640 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00641 00642 StatusCode 00643 THistSvc::getGraph(const std::string& id, TGraph*& hist) const { 00644 return getHist_i(id, hist); 00645 } 00646 00647 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00648 00649 std::vector<std::string> 00650 THistSvc::getTrees() const { 00651 00652 std::vector<std::string> names; 00653 00654 uidMap::const_iterator itr; 00655 for (itr == m_uids.begin(); itr != m_uids.end(); ++itr) { 00656 std::string id = itr->first; 00657 THistID tid = itr->second; 00658 00659 if (tid.obj->IsA()->InheritsFrom("TTree")) { 00660 // TTree *tr = dynamic_cast<TTree*>(tid.obj); 00661 // if (tr != 0) { 00662 names.push_back(id); 00663 } 00664 00665 } 00666 00667 return names; 00668 00669 00670 } 00671 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00672 00673 StatusCode 00674 THistSvc::readHist(const std::string& id, TH1*& hist) const { 00675 return readHist_i(id, hist); 00676 } 00677 00678 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00679 00680 StatusCode 00681 THistSvc::readHist(const std::string& id, TH2*& hist) const { 00682 return readHist_i(id, hist); 00683 } 00684 00685 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00686 00687 StatusCode 00688 THistSvc::readHist(const std::string& id, TH3*& hist) const { 00689 return readHist_i(id, hist); 00690 } 00691 00692 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00693 00694 StatusCode 00695 THistSvc::readTree(const std::string& id, TTree*& hist) const { 00696 return readHist_i(id, hist); 00697 } 00698 00699 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00700 00701 bool 00702 THistSvc::findStream(const string& id, string& stream, string& rem, 00703 TFile*& file) const { 00704 00705 string::size_type pos = id.find("/"); 00706 00707 if (pos == string::npos) { 00708 stream = "temp"; 00709 rem = id; 00710 } else if (pos != 0) { 00711 stream = "temp"; 00712 rem = id; 00713 } else { 00714 00715 string::size_type pos2 = id.find("/",pos+1); 00716 00717 if (pos2 == string::npos) { 00718 MsgStream log( msgSvc(), name() ); 00719 log << MSG::ERROR << "badly formed Hist/Tree id: \"" << id << "\"" 00720 << endreq; 00721 return false; 00722 } 00723 00724 parseString(id,stream,rem); 00725 00726 } 00727 00728 if (stream == "temp") { 00729 file = 0; 00730 return true; 00731 } 00732 00733 map< string,pair<TFile*,Mode> >::const_iterator itr = m_files.find(stream); 00734 if (itr != m_files.end()) { 00735 file = itr->second.first; 00736 } else { 00737 file = 0; 00738 MsgStream log( msgSvc(), name() ); 00739 log << MSG::WARNING << "no stream \"" << stream 00740 << "\" associated with id: \"" << id << "\"" 00741 << endreq; 00742 } 00743 00744 return true; 00745 00746 } 00747 00748 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00749 00750 void 00751 THistSvc::parseString(const string& id, string& root, string& rem) const { 00752 string::size_type pos = id.find("/"); 00753 00754 if (pos == string::npos) { 00755 root = ""; 00756 rem = id; 00757 return; 00758 } 00759 00760 if (pos == 0) { 00761 parseString(id.substr(1,id.length()),root,rem); 00762 } else { 00763 root = id.substr(0,pos); 00764 rem = id.substr(pos+1,id.length()); 00765 } 00766 00767 } 00768 00769 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00770 00771 void 00772 THistSvc::setupInputFile( Property& /*m_inputfile*/ ) 00773 { 00774 StatusCode sc = StatusCode::SUCCESS; 00775 00776 typedef std::vector<std::string> Strings_t; 00777 for ( Strings_t::const_iterator 00778 itr = m_inputfile.value().begin(), 00779 iEnd = m_inputfile.value().end(); 00780 itr != iEnd; 00781 ++itr ) { 00782 if ( m_alreadyConnectedInFiles.end() == 00783 m_alreadyConnectedInFiles.find( *itr ) ) { 00784 if ( connect(*itr).isFailure() ) { 00785 sc = StatusCode::FAILURE; 00786 } else { 00787 m_alreadyConnectedInFiles.insert( *itr ); 00788 } 00789 } 00790 } 00791 00792 if ( !sc.isSuccess() ) { 00793 throw GaudiException( "Problem connecting inputfile !!", name(), 00794 StatusCode::FAILURE ); 00795 } 00796 return; 00797 } 00798 00799 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00800 00801 void 00802 THistSvc::setupOutputFile( Property& /*m_outputfile*/ ) 00803 { 00804 StatusCode sc = StatusCode::SUCCESS; 00805 00806 typedef std::vector<std::string> Strings_t; 00807 for ( Strings_t::const_iterator 00808 itr = m_outputfile.value().begin(), 00809 iEnd = m_outputfile.value().end(); 00810 itr != iEnd; 00811 ++itr ) { 00812 if ( m_alreadyConnectedOutFiles.end() == 00813 m_alreadyConnectedOutFiles.find( *itr ) ) { 00814 if ( connect(*itr).isFailure() ) { 00815 sc = StatusCode::FAILURE; 00816 } else { 00817 m_alreadyConnectedOutFiles.insert( *itr ); 00818 } 00819 } 00820 } 00821 00822 if ( !sc.isSuccess() ) { 00823 throw GaudiException( "Problem connecting outputfile !!", name(), 00824 StatusCode::FAILURE ); 00825 } 00826 return; 00827 } 00828 00829 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00830 00831 void 00832 THistSvc::updateFiles() { 00833 00834 // If TTrees grow beyond TTree::fgMaxFileSize, a new file is 00835 // automatically created by root, and the old one closed. We 00836 // need to migrate all the UIDs over to show the correct file 00837 // pointer. This is ugly. 00838 00839 uidMap::iterator uitr, uitr2; 00840 for (uitr=m_uids.begin(); uitr != m_uids.end(); ++uitr) { 00841 TObject* to = uitr->second.obj; 00842 TFile* oldFile = uitr->second.file; 00843 if (to->IsA()->InheritsFrom("TTree")) { 00844 TTree* tr = dynamic_cast<TTree*>(to); 00845 TFile* newFile = tr->GetCurrentFile(); 00846 00847 if (oldFile != newFile) { 00848 std::string newFileName = newFile->GetName(); 00849 std::string oldFileName(""), streamName, rem; 00850 TFile* dummy; 00851 findStream(uitr->second.id, streamName, rem, dummy); 00852 00853 MsgStream log( msgSvc(), name() ); 00854 log << MSG::DEBUG << "migrating uid: " << uitr->second.id 00855 << " stream: " << streamName << " newFile: " << newFileName 00856 << endreq; 00857 00858 map<string, pair<TFile*,Mode> >::iterator itr; 00859 for (itr=m_files.begin(); itr!= m_files.end(); ++itr) { 00860 if (itr->second.first == oldFile) { 00861 itr->second.first = newFile; 00862 00863 } 00864 } 00865 00866 uitr2 = uitr; 00867 for (uitr2++; uitr2 != m_uids.end(); ++uitr2) { 00868 if (uitr2->second.file == oldFile) { 00869 uitr2->second.file = newFile; 00870 } 00871 } 00872 00873 streamMap::iterator sitr; 00874 for (sitr = m_fileStreams.begin(); sitr!=m_fileStreams.end(); ++sitr) { 00875 if (sitr->second == streamName) { 00876 oldFileName = sitr->first; 00877 break; 00878 } 00879 } 00880 00881 if (oldFileName != "") { 00882 while ( (sitr=m_fileStreams.find(oldFileName)) != m_fileStreams.end() ) { 00883 log << MSG::DEBUG << "changing filename \"" << oldFileName 00884 << "\" to \"" << newFileName << "\" for stream \"" 00885 << sitr->second << "\"" << endreq; 00886 m_fileStreams.erase(sitr); 00887 m_fileStreams.insert( make_pair<std::string,std::string>(newFileName,streamName) ); 00888 } 00889 00890 00891 } else { 00892 log << MSG::ERROR 00893 << "Problems updating fileStreams with new file name" << endreq; 00894 } 00895 00896 } 00897 00898 } 00899 } 00900 00901 } 00902 00903 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00904 00905 StatusCode 00906 THistSvc::write() { 00907 00908 updateFiles(); 00909 00910 map<string, pair<TFile*,Mode> >::const_iterator itr; 00911 for (itr=m_files.begin(); itr!= m_files.end(); ++itr) { 00912 if (itr->second.second == WRITE || itr->second.second == UPDATE 00913 ||itr->second.second==SHARE) { 00914 itr->second.first->Write("",TObject::kOverwrite); 00915 } else if (itr->second.second == APPEND) { 00916 itr->second.first->Write(""); 00917 } 00918 } 00919 00920 MsgStream log(msgSvc(), name() ); 00921 00922 log << MSG::DEBUG << "THistSvc::write()::List of Files connected in ROOT " 00923 <<endreq; 00924 00925 TSeqCollection *filelist=gROOT->GetListOfFiles(); 00926 for (int ii=0; ii<filelist->GetEntries(); ii++) { 00927 log << MSG::DEBUG 00928 << "THistSvc::write()::List of Files connected in ROOT: \"" 00929 <<filelist->At(ii)->GetName()<<"\""<<endreq; 00930 } 00931 00932 return StatusCode::SUCCESS; 00933 00934 } 00935 00936 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 00937 00938 StatusCode 00939 THistSvc::connect(const std::string& ident) { 00940 00941 MsgStream log ( msgSvc(), name() ); 00942 Tokenizer tok(true); 00943 00944 string::size_type loc = ident.find(" "); 00945 string stream = ident.substr(0,loc); 00946 char typ(0); 00947 typedef std::pair<std::string,std::string> Prop; 00948 std::vector<Prop> props; 00949 string val,VAL,TAG,filename,db_typ("ROOT"); 00950 00951 tok.analyse(ident.substr(loc+1,ident.length()), " ", "", "", "=", "'", "'"); 00952 00953 for ( Tokenizer::Items::iterator i = tok.items().begin(); i != tok.items().end(); i++) { 00954 const std::string& tag = (*i).tag(); 00955 TAG = tag; 00956 toupper(TAG); 00957 00958 val = (*i).value(); 00959 VAL = val; 00960 toupper(VAL); 00961 00962 if (TAG == "FILE" || TAG == "DATAFILE") { 00963 filename = val; 00964 removeDoubleSlash( filename ); 00965 } else if ( TAG == "OPT" ) { 00966 if ( VAL == "APPEND" || VAL == "UPDATE" ) { 00967 typ = 'A'; 00968 } else if ( VAL == "CREATE" || VAL == "NEW" || VAL == "WRITE" ) { 00969 typ = 'N'; 00970 } else if ( VAL == "RECREATE" ) { 00971 typ = 'R'; 00972 } else if (VAL == "SHARE") { 00973 typ = 'S'; 00974 } else if ( VAL == "OLD" || VAL == "READ" ) { 00975 typ = 'O'; 00976 } else { 00977 log << MSG::ERROR << "Unknown OPT: \"" << (*i).value() << "\"" 00978 << endreq; 00979 typ = 0; 00980 } 00981 } else if (TAG == "TYP") { 00982 db_typ = (*i).value(); 00983 } else { 00984 props.push_back( Prop((*i).tag(), (*i).value())); 00985 } 00986 00987 } 00988 00989 if (stream == "temp") { 00990 log << MSG::ERROR << "in JobOption \"" << ident 00991 << "\": stream name \"temp\" reserved." 00992 << endreq; 00993 return StatusCode::FAILURE; 00994 } 00995 00996 if (db_typ != "ROOT") { 00997 log << MSG::ERROR << "in JobOption \"" << ident 00998 << "\": technology type \"" << db_typ << "\" not supported." 00999 << endreq; 01000 return StatusCode::FAILURE; 01001 } 01002 01003 01004 if (m_files.find(stream) != m_files.end()) { 01005 log << MSG::ERROR << "in JobOption \"" << ident 01006 << "\":\n stream \"" << stream << "\" already connected to file: \"" 01007 << m_files[stream].first->GetName() << "\"" 01008 << endreq; 01009 return StatusCode::FAILURE; 01010 } 01011 01012 Mode newMode; 01013 if (typ == 'O') { 01014 newMode = THistSvc::READ; 01015 } else if (typ == 'N') { 01016 newMode = THistSvc::WRITE; 01017 } else if (typ == 'A') { 01018 newMode = THistSvc::APPEND; 01019 } else if (typ == 'R') { 01020 newMode = THistSvc::UPDATE; 01021 } else if (typ == 'S') { 01022 newMode = THistSvc::SHARE; 01023 } else { 01024 // something else? 01025 log << MSG::ERROR << "No OPT= specified or unknown access mode in: " 01026 << ident << endreq; 01027 return StatusCode::FAILURE; 01028 } 01029 01030 // Is this file already connected to another stream? 01031 if (m_fileStreams.find(filename) != m_fileStreams.end()) { 01032 std::pair<streamMap::iterator, streamMap::iterator> fitr = 01033 m_fileStreams.equal_range(filename); 01034 01035 std::string oldstream = (fitr.first)->second; 01036 01037 std::pair<TFile*,Mode> f_info = m_files[oldstream]; 01038 01039 if (newMode != f_info.second) { 01040 log << MSG::ERROR << "in JobOption \"" << ident 01041 << "\":\n file \"" << filename << "\" already opened by stream: \"" 01042 << oldstream << "\" with different access mode." 01043 << endreq; 01044 return StatusCode::FAILURE; 01045 } else { 01046 TFile *f2 = f_info.first; 01047 m_files[stream] = make_pair<TFile*,Mode>(f2,newMode); 01048 log << MSG::DEBUG << "Connecting stream: \"" << stream 01049 << "\" to previously opened TFile: \"" << filename << "\"" 01050 << endreq; 01051 return StatusCode::SUCCESS; 01052 } 01053 } 01054 01055 01056 TFile *f(0) ; 01057 if (newMode == THistSvc::READ) { 01058 // old file 01059 01060 try { 01061 f = TFile::Open(filename.c_str(),"READ"); 01062 } catch (const std::exception& Exception) { 01063 log << MSG::ERROR << "exception caught while trying to open root" 01064 << " file for reading: " << Exception.what() << std::endl 01065 << " -> file probably corrupt." << endreq; 01066 return StatusCode::FAILURE; 01067 } catch (...) { 01068 log << MSG::ERROR << "Problems opening input file \"" << filename 01069 << "\": probably corrupt" << endreq; 01070 return StatusCode::FAILURE; 01071 } 01072 01073 if (!f->IsOpen()) { 01074 log << MSG::ERROR << "Unable to open input file \"" << filename 01075 << "\": file does not exist" << endreq; 01076 return StatusCode::FAILURE; 01077 } 01078 01079 01080 } else if (newMode == THistSvc::WRITE) { 01081 // new file 01082 01083 f = TFile::Open(filename.c_str(),"NEW"); 01084 if (!f->IsOpen()) { 01085 log << MSG::ERROR << "Unable to create new output file \"" << filename 01086 << "\" for writing: file already exists" << endreq; 01087 return StatusCode::FAILURE; 01088 } 01089 01090 } else if (newMode == THistSvc::APPEND) { 01091 // update file 01092 01093 try { 01094 f = TFile::Open(filename.c_str(),"UPDATE"); 01095 } catch (const std::exception& Exception) { 01096 log << MSG::ERROR << "exception caught while trying to open root" 01097 << " file for appending: " << Exception.what() << std::endl 01098 << " -> file probably corrupt." << endreq; 01099 return StatusCode::FAILURE; 01100 } catch (...) { 01101 log << MSG::ERROR << "Problems opening output file \"" << filename 01102 << "\" for append: probably corrupt" << endreq; 01103 return StatusCode::FAILURE; 01104 } 01105 01106 if (!f->IsOpen()) { 01107 log << MSG::ERROR << "Unable to open output file \"" << filename 01108 << "\" for appending" << endreq; 01109 return StatusCode::FAILURE; 01110 } 01111 01112 } else if (newMode == THistSvc::SHARE) { 01113 // SHARE file type 01114 //For SHARE files, all data will be stored in a temp file and will be merged into the target file 01115 //in write() when finalize(), this help to solve some confliction. e.g. with storegate 01116 01117 static int ishared = 0; 01118 stringstream out; 01119 string realfilename=filename; 01120 out << ishared; 01121 filename = string("tmp_THistSvc_")+out.str()+string(".root"); 01122 01123 log << MSG::DEBUG << "Creating temp file \"" << filename 01124 << "\" and realfilename="<<realfilename << endreq; 01125 m_sharedFiles[stream]=realfilename; 01126 01127 try { 01128 f = TFile::Open(filename.c_str(),"NEW"); 01129 } catch (const std::exception& Exception) { 01130 log << MSG::ERROR << "exception caught while trying to open root" 01131 << " file for appending: " << Exception.what() << std::endl 01132 << " -> file probably corrupt." << endreq; 01133 return StatusCode::FAILURE; 01134 } catch (...) { 01135 log << MSG::ERROR << "Problems opening output file \"" << filename 01136 << "\" for append: probably corrupt" << endreq; 01137 return StatusCode::FAILURE; 01138 } 01139 01140 if (!f->IsOpen()) { 01141 log << MSG::ERROR << "Unable to open output file \"" << filename 01142 << "\" for appending" << endreq; 01143 return StatusCode::FAILURE; 01144 } 01145 01146 } else if (newMode == THistSvc::UPDATE) { 01147 // update file 01148 01149 try { 01150 f = TFile::Open(filename.c_str(),"RECREATE"); 01151 } catch (const std::exception& Exception) { 01152 log << MSG::ERROR << "exception caught while trying to open root" 01153 << " file for updating: " << Exception.what() << std::endl 01154 << " -> file probably corrupt." << endreq; 01155 return StatusCode::FAILURE; 01156 } catch (...) { 01157 log << MSG::ERROR << "Problems opening output file \"" << filename 01158 << "\" for update: probably corrupt" << endreq; 01159 return StatusCode::FAILURE; 01160 } 01161 01162 if (!f->IsOpen()) { 01163 log << MSG::ERROR << "Unable to open output file \"" << filename 01164 << "\" for updating" << endreq; 01165 return StatusCode::FAILURE; 01166 } 01167 01168 } 01169 01170 m_files[stream] = make_pair<TFile*,Mode>(f,newMode); 01171 m_fileStreams.insert(make_pair<std::string,std::string>(filename,stream)); 01172 01173 log << MSG::DEBUG << "Opening TFile \"" << filename << "\" stream: \"" 01174 << stream << "\" mode: \"" << typ << "\"" 01175 << endreq; 01176 01177 return StatusCode::SUCCESS; 01178 } 01179 01180 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 01181 01182 TDirectory* 01183 THistSvc::changeDir(const THistSvc::THistID& hid) const { 01184 01185 string uid = hid.id; 01186 TFile* file = hid.file; 01187 string stream, fdir, bdir, dir, id; 01188 01189 if (file != 0) { 01190 file->cd("/"); 01191 } else { 01192 gROOT->cd(); 01193 } 01194 01195 fdir = uid; 01196 bdir = dirname(fdir); 01197 01198 while ( (dir = dirname(fdir)) != "") { 01199 if (! gDirectory->GetKey(dir.c_str())) { 01200 gDirectory->mkdir(dir.c_str()); 01201 } 01202 gDirectory->cd(dir.c_str()); 01203 } 01204 01205 return gDirectory; 01206 01207 } 01208 01209 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 01210 01211 std::string 01212 THistSvc::dirname(std::string& dir) const { 01213 01214 01215 string::size_type i = dir.find("/"); 01216 01217 if (i == string::npos) { 01218 return ""; 01219 } 01220 01221 if ( i == 0 ) { 01222 dir.erase(0,1); 01223 return dirname(dir); 01224 } 01225 01226 string root = dir.substr(0,i); 01227 dir.erase(0,i); 01228 01229 return root; 01230 01231 } 01232 01233 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 01234 01235 THistSvc::GlobalDirectoryRestore::GlobalDirectoryRestore() { 01236 m_gd = gDirectory; 01237 m_gf = gFile; 01238 m_ge = gErrorIgnoreLevel; 01239 } 01240 01241 THistSvc::GlobalDirectoryRestore::~GlobalDirectoryRestore() { 01242 gDirectory = m_gd; 01243 gFile = m_gf; 01244 gErrorIgnoreLevel = m_ge; 01245 } 01246 01247 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 01248 01249 void 01250 THistSvc::removeDoubleSlash(std::string& id) const { 01251 01252 while (id.find("//") != std::string::npos) { 01253 id.replace(id.find("//"),2,"/"); 01254 } 01255 01256 } 01257 01258 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// 01259 01260 void THistSvc::MergeRootFile(TDirectory *target, TDirectory *source) { 01261 01262 MsgStream log(msgSvc(), name() ); 01263 01264 log <<MSG::DEBUG << "Target path: " << target->GetPath() << endreq; 01265 TString path( (char*)strstr(target->GetPath(), ":") ); 01266 path.Remove( 0, 2); 01267 01268 source->cd(path); 01269 TDirectory *current_sourcedir = gDirectory; 01270 01271 // loop over all keys in this directory 01272 TList *lkeys=current_sourcedir->GetListOfKeys(); 01273 int nkeys=lkeys->GetEntries(); 01274 TKey *key; 01275 for (int jj=0; jj<nkeys; jj++) { 01276 key=(TKey*) lkeys->At(jj); 01277 string pathnameinsource=current_sourcedir->GetPath()+string("/")+key->GetName(); 01278 log <<MSG::DEBUG << "Reading Key:" << pathnameinsource << endreq; 01279 //key->Dump(); 01280 //TObject *obj=key->ReadObj(); 01281 TObject *obj=source->Get(pathnameinsource.c_str()); 01282 01283 if (obj->IsA()->InheritsFrom("TDirectory") ) { 01284 // it's a subdirectory 01285 01286 log <<MSG::DEBUG << "Found subdirectory " << obj->GetName() 01287 << endreq; 01288 01289 // create a new subdir of same name and title in the target file 01290 target->cd(); 01291 TDirectory *newtargetdir = 01292 target->mkdir(obj->GetName(), obj->GetTitle() ); 01293 01294 MergeRootFile(newtargetdir, source); 01295 01296 } else if (obj->IsA()->InheritsFrom("TTree")) { 01297 log <<MSG::DEBUG << "Found TTree " << obj->GetName() << endreq; 01298 TTree *mytree=dynamic_cast<TTree*>(obj); 01299 int nentries=(int) mytree->GetEntries(); 01300 mytree->SetBranchStatus("*",1); 01301 01302 log <<MSG::DEBUG << "Dumping TTree " << nentries <<" entries" 01303 << endreq; 01304 //mytree->Print(); 01305 //for (int ij=0; ij<nentries; ij++) { 01306 //log <<MSG::DEBUG << "Dumping TTree Show( " << ij <<" )" 01307 //<< endreq; 01308 //mytree->Show(ij); 01309 //} 01310 target->cd(); 01311 // Marco Cl.: avoid compilation warning about unused variable 'mycopiedtree' 01312 // TTree *mycopiedtree=mytree->CloneTree(); 01313 mytree->CloneTree(); 01314 01315 //log <<MSG::DEBUG << "Writing TTree to target file: ( " 01316 //<< mycopiedtree->Write(key->GetName()) <<" ) bytes written" 01317 //<< endreq; 01318 01319 } else if (obj) { 01320 target->cd(); 01321 obj->Write(key->GetName() ); 01322 } 01323 01324 } // while ( ( TKey *key = (TKey*)nextkey() ) ) 01325 01326 // save modifications to target file 01327 01328 } 01329 01330 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *//