/search.css" rel="stylesheet" type="text/css"/> /search.js">
00001 #include "RootIOSvc/RootIOCnvSvc.h" 00002 #include "RootIOSvc/RootIOAddress.h" 00003 #include "RootIOSvc/RootIOBaseCnv.h" 00004 #include "RootOutputFileManager.h" 00005 00006 #include "GaudiKernel/DataObject.h" 00007 #include "GaudiKernel/SmartIF.h" 00008 #include "GaudiKernel/IRegistry.h" 00009 #include "GaudiKernel/IDataProviderSvc.h" 00010 #include "GaudiKernel/IDataManagerSvc.h" 00011 #include "GaudiKernel/IIncidentSvc.h" 00012 #include "GaudiKernel/ISvcManager.h" 00013 #include "GaudiKernel/MsgStream.h" 00014 00015 #include "Event/RegistrationSequence.h" 00016 00017 using namespace std; 00018 00019 RootIOCnvSvc::RootIOCnvSvc(const string& name, ISvcLocator* svc) 00020 : ConversionSvc(name,svc,ROOT_StorageType) 00021 , m_dataSvc(0) 00022 { 00023 declareProperty("OutputStreams",m_outputFileMap, 00024 "Map of TES location to output filename"); 00025 declareProperty("DefaultOutput",m_defaultOutputFilename="", 00026 "Name of output file to store unregistered paths."); 00027 00028 declareProperty("InputStreams",m_inputFileMap, 00029 "Map of TES location to input filename"); 00030 declareProperty("DefaultInput",m_defaultInputFilenames, 00031 "Name of input file to store unregistered paths."); 00032 00033 declareProperty("EventDataService",m_dataSvcName="EventDataSvc", 00034 "Name of event data service."); 00035 00036 declareProperty("MajorIndexExpression",m_majorIndex="execNumber", 00037 "Expression to use for building the tree's index."); 00038 declareProperty("MinorIndexExpression",m_minorIndex="0", 00039 "Expression to use for building the tree's index."); 00040 } 00041 RootIOCnvSvc::~RootIOCnvSvc() 00042 { 00043 } 00044 00045 StatusCode RootIOCnvSvc::reinitialize() 00046 { 00047 MsgStream log(msgSvc(), "RootIOCnvSvc"); 00048 log << MSG::DEBUG << "reinitializing @" << (void*)this << endreq; 00049 StatusCode sc = ConversionSvc::initialize(); 00050 if (sc.isFailure()) { 00051 log << MSG::ERROR << "parent class failed to initialize" << endreq; 00052 return sc; 00053 } 00054 sc= this->doInitialize(); 00055 log << MSG::DEBUG << "reinitialized @" << (void*)this << endreq; 00056 return sc; 00057 } 00058 StatusCode RootIOCnvSvc::initialize() 00059 { 00060 MsgStream log(msgSvc(), "RootIOCnvSvc"); 00061 log << MSG::DEBUG << "initializing @" << (void*)this << endreq; 00062 StatusCode sc = ConversionSvc::initialize(); 00063 if (sc.isFailure()) { 00064 log << MSG::ERROR << "parent class failed to initialize" << endreq; 00065 return sc; 00066 } 00067 sc= this->doInitialize(); 00068 log << MSG::DEBUG << "initialized @" << (void*)this << endreq; 00069 return sc; 00070 } 00071 00072 StatusCode RootIOCnvSvc::doInitialize() 00073 { 00074 MsgStream log(msgSvc(), "RootIOCnvSvc"); 00075 00076 if (0 == m_defaultInputFilenames.size() && 0 == m_inputFileMap.size() && 00077 "" == m_defaultOutputFilename && 0 == m_outputFileMap.size()) 00078 { 00079 log << MSG::WARNING 00080 << "No input nor output files specified. Why am I here?" 00081 << endreq; 00082 return StatusCode::FAILURE; 00083 } 00084 00085 00086 // --- ouput --- // 00087 { 00088 map<string,string>::iterator it, done = m_outputFileMap.end(); 00089 log << MSG::INFO 00090 << " default output = \"" << m_defaultOutputFilename << "\"" 00091 << " output file map (" << m_outputFileMap.size() << " entries):"; 00092 for (it = m_outputFileMap.begin(); it != done; ++it) { 00093 log << "\n\t\"" << it->first << "\" ==> \"" << it->second << "\""; 00094 } 00095 log << endreq; 00096 } 00097 if (m_defaultOutputFilename.size()) { // if set, it should override "default" in map 00098 m_outputFileMap["default"] = m_defaultOutputFilename; 00099 } 00100 else { 00101 map<string,string>::iterator it = m_outputFileMap.find("default"); 00102 if (it == m_outputFileMap.end()) { 00103 log << MSG::WARNING 00104 << " no \"default\" output file name specified, " 00105 "unregistered TES paths will not be saved." << endreq; 00106 } 00107 else { 00108 m_defaultOutputFilename = it->second; 00109 } 00110 } 00111 00112 // If we have output, configure the output file manager 00113 if (m_outputFileMap.size()) { 00114 IIncidentSvc *incsvc = 0; 00115 StatusCode sc = service("IncidentSvc", incsvc, true); 00116 if(sc.isFailure()){ 00117 log << MSG::ERROR << "Unable start IncidentSvc service" 00118 << endreq; 00119 return sc; 00120 } 00121 RootOutputFileManager::get().setIncidentSvc(incsvc); 00122 00123 // make sure we get finalized before IncidentSvc does. 00124 // SmartIF<ISvcManager> mgr(IID_ISvcManager, serviceLocator()); 00125 // int pri_inc = mgr->getPriority("IncidentSvc"); 00126 // log << MSG::INFO << "Setting my priority to one more than IncidentSvc (" << pri_inc << ")" << endreq; 00127 // mgr->setPriority("RootIOCnvSvc",pri_inc + 1); 00128 } 00129 00130 00131 // --- input --- // 00132 { 00133 map<string,vector<string> >::iterator it, done = m_inputFileMap.end(); 00134 string defin = ""; 00135 if (m_defaultInputFilenames.size()) defin = m_defaultInputFilenames[0]; 00136 log << MSG::INFO 00137 << " default input = \"" << defin << "\"" 00138 << " input file map (" << m_inputFileMap.size() << " entries):"; 00139 for (it = m_inputFileMap.begin(); it != done; ++it) { 00140 log << "\t" << it->first << " : ["; 00141 vector<string>& vec = it->second; 00142 for (size_t ind = 0; ind < vec.size(); ++ind) { 00143 log << " " << vec[ind]; 00144 } 00145 log << "]\n"; 00146 } 00147 log << endreq; 00148 } 00149 00150 if (0 == m_defaultInputFilenames.size()) { 00151 map<string,vector<string> >::iterator it = m_inputFileMap.find("default"); 00152 if (it == m_inputFileMap.end()) { 00153 log << MSG::WARNING 00154 << " no \"default\" input file name specified, " 00155 "unregistered TES paths will not be saved." << endreq; 00156 } 00157 else { 00158 m_defaultInputFilenames = it->second; 00159 } 00160 } 00161 { 00162 map<string,vector<string> >::iterator it, done = m_inputFileMap.end(); 00163 for (it = m_inputFileMap.begin(); it != done; ++it) { 00164 if (it->first == "default") continue; 00165 if (!it->second.size()) { 00166 log << MSG::WARNING 00167 << "Skipping input stream with no files: " 00168 << it->first << endreq; 00169 continue; 00170 } 00171 initializeInputStream(it->first,it->second); 00172 } 00173 if (m_defaultInputFilenames.size()) 00174 initializeInputStream("default",m_defaultInputFilenames); 00175 } 00176 00177 log << MSG::DEBUG << "Initialized input and output streams." << endreq; 00178 00179 // Get DataSvc 00180 log << MSG::DEBUG << "Getting " << m_dataSvcName << " as IService" << endreq; 00181 IService* isvc = 0; 00182 StatusCode sc = service(m_dataSvcName, isvc, true); 00183 if(sc.isFailure()){ 00184 log << MSG::ERROR << "Unable start EventData service" 00185 << m_dataSvcName << endreq; 00186 return sc; 00187 } 00188 isvc->addRef(); 00189 00190 log << MSG::DEBUG << "Querying " << m_dataSvcName << " for IID_IDataProviderSvc" << endreq; 00191 sc = isvc->queryInterface(IID_IDataProviderSvc, (void**)&m_dataSvc); 00192 if(sc.isFailure()){ 00193 log << MSG::ERROR << "EventData service " << m_dataSvcName 00194 << "not an IDataProviderSvc" << endreq; 00195 return sc; 00196 } 00197 00198 log << MSG::DEBUG << "Querying " << m_dataSvcName << " for IID_IDataManagerSvc" << endreq; 00199 sc = isvc->queryInterface(IDataManagerSvc::interfaceID(), 00200 (void**)(&m_dataMgr)); 00201 if (sc.isFailure()) { 00202 log << MSG::ERROR << "EventData service " << m_dataSvcName 00203 << "not an IDataManagerSvc" << endreq; 00204 return sc; 00205 } 00206 00207 return StatusCode::SUCCESS; 00208 } 00209 00210 void RootIOCnvSvc::initializeInputStream(const string& path, 00211 const string& filename) 00212 { 00213 vector<string> vec; 00214 vec.push_back(filename); 00215 this->initializeInputStream(path,vec); 00216 } 00217 00218 void RootIOCnvSvc::initializeInputStream(const string& path, 00219 const vector<string>& filenames) 00220 { 00221 MsgStream log(msgSvc(), "RootIOCnvSvc"); 00222 00223 // If "default" root through all paths in the file and register them. 00224 if (path == "default") { 00225 // Use the first filename to find all TES paths it represents. 00226 // This could be a problem if a series of files get written 00227 // and a particular path doesn't show up until after the first 00228 // file..... 00229 vector<string> tespaths = RootInputFile::TreePaths(filenames[0]); 00230 00231 if (!tespaths.size()) { 00232 log << MSG::WARNING 00233 << "initializeInputStream found no Trees in " << filenames[0] 00234 << endreq; 00235 return; 00236 } 00237 for (size_t ind=0; ind<tespaths.size(); ++ind) { 00238 log << MSG::DEBUG << "found " << tespaths[ind] << " in file " 00239 << filenames[0] << endreq; 00240 initializeInputStream(tespaths[ind],filenames); 00241 } 00242 return; 00243 } 00244 00245 map<string,RootInputStream*>::iterator it = m_inputStreamMap.find(path); 00246 if (it != m_inputStreamMap.end()) { 00247 log << MSG::WARNING << "path " 00248 << path << " already has an input stream so not reinitializing file " 00249 << filenames[0] << ", ..." << endreq; 00250 return; 00251 } 00252 00253 // Sanity check 00254 string branchname = RootIO::branchname(path); 00255 int clid = RootInputFile::TestForObject(filenames[0],path,branchname); 00256 if (!clid) { 00257 log << MSG::WARNING << "failed to get nonzero class id from path " 00258 << path << ", branch " << branchname << " in file " << filenames[0] << endreq; 00259 return; 00260 } 00261 00262 RootInputAddress ria(clid,path); 00263 00264 RootInputStream* ris = this->inputStream(ria); 00265 if (!ris) { 00266 log << MSG::WARNING << "failed to get input stream for " << path 00267 << " in " << filenames[0] << endreq; 00268 return; 00269 } 00270 00271 m_inputStreamMap[path] = ris; 00272 log << MSG::DEBUG << "retrieving " << path 00273 << " from " << filenames[0] << endreq; 00274 return; 00275 } 00276 00277 00278 void RootIOCnvSvc::associateOutput(const char* filename, const char* streamname) 00279 { 00280 m_outputFileMap[streamname] = filename; 00281 if (string("default") == streamname) { 00282 m_defaultOutputFilename = filename; 00283 } 00284 } 00285 IRootIOSvc::FileMap RootIOCnvSvc::fileMap() 00286 { 00287 return m_outputFileMap; 00288 } 00289 00290 RootOutputStream* RootIOCnvSvc::outputStream(const RootOutputAddress& roa) 00291 { 00292 MsgStream log(msgSvc(), "RootIOCnvSvc"); 00293 00294 const string& filename = this->outputFilename(roa.tespath()); 00295 if ("" == filename) { 00296 log << MSG::ERROR << "Bad (empty) output filename, no ouput stream for " 00297 << roa.tespath() << endreq; 00298 return 0; 00299 } 00300 00301 RootOutputStream* os = m_outputStreamMap[roa.tespath()]; 00302 if (os) { 00303 os->newFile(filename); // noop unless filename differs from old one 00304 log << MSG::DEBUG << "outputStream for " << roa.tespath() 00305 << " cached, file = " << filename << endreq; 00306 return os; 00307 } 00308 00309 IConverter* cnv = converter(roa.clID()); 00310 if (!cnv) { 00311 log << MSG::WARNING 00312 << "Failed to get converter for class ID = " << roa.clID() 00313 << " tespath = " << roa.tespath() << endreq; 00314 return 0; 00315 } 00316 00317 RootIOBaseCnv* riocnv = dynamic_cast<RootIOBaseCnv*>(cnv); 00318 if (!riocnv) { 00319 log << MSG::WARNING 00320 << "Converter not a RootIOBaseCnv for class ID = " << roa.clID() 00321 << " tespath = " << roa.tespath() << endreq; 00322 return 0; 00323 } 00324 00325 os = riocnv->makeOutputStream(roa); 00326 if (!os) { 00327 log << MSG::WARNING 00328 << "Converter failed to make new output stream for class ID = " 00329 << roa.clID() 00330 << " tespath = " << roa.tespath() << endreq; 00331 return 0; 00332 } 00333 00334 if (roa.clID() != DayaBay::RegistrationSequence::classID()) { 00335 log << MSG::DEBUG 00336 << "outputStream for " << roa.tespath() 00337 << " gets major=\"" << m_majorIndex << "\", " 00338 << "minor=\"" << m_minorIndex << "\"" << endreq; 00339 os->setIndexExpression(m_majorIndex,m_minorIndex); 00340 } 00341 00342 m_outputStreamMap[roa.tespath()] = os; 00343 os->newFile(filename); 00344 log << MSG::DEBUG << "outputStream for " << roa.tespath() 00345 << " new, file = " << filename << endreq; 00346 return os; 00347 } 00348 00349 RootInputStream* RootIOCnvSvc::inputStream(const RootInputAddress& ria) 00350 { 00351 MsgStream log(msgSvc(), "RootIOCnvSvc"); 00352 00353 vector<string> filenames = this->inputFilenames(ria.tespath()); 00354 if (0 == filenames.size()) { 00355 log << MSG::DEBUG << "Bad (empty) input filename, no input stream for " 00356 << ria.tespath() << endreq; 00357 return 0; 00358 } 00359 00360 RootInputStream* ris = m_inputStreamMap[ria.tespath()]; 00361 if (ris) { 00362 log << MSG::DEBUG << "inputStream for " << ria.tespath() 00363 << " cached, files = ["; 00364 for (size_t ind=0; ind<filenames.size(); ++ind) { 00365 log << " " << filenames[ind]; 00366 } 00367 log << "]" << endreq; 00368 return ris; 00369 } 00370 00371 IConverter* cnv = converter(ria.clID()); 00372 if (!cnv) { 00373 log << MSG::WARNING 00374 << "Failed to get converter for class ID = " << ria.clID() 00375 << " tespath = " << ria.tespath() << endreq; 00376 return 0; 00377 } 00378 00379 RootIOBaseCnv* riocnv = dynamic_cast<RootIOBaseCnv*>(cnv); 00380 if (!riocnv) { 00381 log << MSG::WARNING 00382 << "Converter not a RootIOBaseCnv for class ID = " << ria.clID() 00383 << " tespath = " << ria.tespath() << endreq; 00384 return 0; 00385 } 00386 00387 ris = riocnv->makeInputStream(ria); 00388 if (!ris) { 00389 log << MSG::WARNING 00390 << "Converter failed to make new input stream for class ID = " 00391 << ria.clID() 00392 << " tespath = " << ria.tespath() << endreq; 00393 return 0; 00394 } 00395 00396 for (size_t ind = 0; ind < filenames.size(); ++ind) { 00397 bool okay = ris->append(filenames[ind], true); 00398 if (!okay) { 00399 log << MSG::ERROR 00400 << "failed to append file " << filenames[ind] << " to input stream for " 00401 << ria.tespath() << endreq; 00402 return 0; 00403 } 00404 } 00405 00406 m_inputStreamMap[ria.tespath()] = ris; 00407 00408 log << MSG::DEBUG << "inputStream for " << ria.tespath() 00409 << " new, files = ["; 00410 for (size_t ind=0; ind<filenames.size(); ++ind) { 00411 log << " " << filenames[ind]; 00412 } 00413 log << "]" << endreq; 00414 00415 return ris; 00416 } 00417 00418 const string& RootIOCnvSvc::outputFilename(const string& tespath) 00419 { 00420 map<string,string>::iterator it = m_outputFileMap.find(tespath); 00421 if (it == m_outputFileMap.end()) return m_defaultOutputFilename; 00422 return it->second; 00423 } 00424 00425 vector<string> RootIOCnvSvc::inputFilenames(const string& tespath) 00426 { 00427 map<string,vector<string> >::iterator it = m_inputFileMap.find(tespath); 00428 if (it == m_inputFileMap.end()) { 00429 return m_defaultInputFilenames; 00430 } 00431 return it->second; 00432 } 00433 00434 StatusCode RootIOCnvSvc::createAddress(long svc_type, 00435 const CLID& clid, 00436 const string* par, 00437 const unsigned long* ip, 00438 IOpaqueAddress*& refpAddress) 00439 { 00440 MsgStream log(msgSvc(), "RootIOCnvSvc"); 00441 log << MSG::ERROR << "generic createAddress(" 00442 << svc_type << ", " << clid 00443 << ",[" << par[0] << "," << par[1] << "], " << ip[0] << ")" 00444 << " unimplemented" 00445 << endreq; 00446 //refpAddress = new RootIOAddress(svc_type,clid,par[0],par[1],ip[0]); 00447 refpAddress = 0; 00448 return StatusCode::FAILURE; 00449 } 00450 00451 00452 StatusCode RootIOCnvSvc::createAddress(DataObject* obj, RootOutputAddress*& newAddr) 00453 { 00454 // wangzhe: There is no ObjectReg created for RegistrationSequence 00455 // So there is no ganrantee there is Registry alive for each RegistrationSequence 00456 string tespath; 00457 if(obj->clID()==DayaBay::RegistrationSequence::classID()) { 00458 tespath=DayaBay::RegistrationSequence::defaultLocation(); 00459 } else { 00460 tespath = obj->registry()->identifier(); 00461 } 00462 // wz 00463 00464 string filename = m_defaultOutputFilename; 00465 map<string,string>::iterator it = m_outputFileMap.find(tespath); 00466 if (it != m_outputFileMap.end()) 00467 filename = it->second; 00468 00469 if ("" == filename) { 00470 MsgStream log(msgSvc(), "RootIOCnvSvc"); 00471 static map<string,int> errorMap; 00472 if (!errorMap[tespath]) { 00473 log << MSG::WARNING 00474 << "Can not create address for " << tespath 00475 << " no output file specified, I won't tell you again." 00476 << endreq; 00477 errorMap[tespath] = 1; 00478 } 00479 return StatusCode::FAILURE; 00480 } 00481 00482 newAddr = new RootOutputAddress(obj->clID(),tespath); 00483 return StatusCode::SUCCESS; 00484 } 00485 00486 00487 StatusCode RootIOCnvSvc::finalize() 00488 { 00489 map<string,RootOutputStream*>::iterator it, done = m_outputStreamMap.end(); 00490 for (it = m_outputStreamMap.begin(); it != done; ++it) { 00491 bool okay = it->second->close(); 00492 if (!okay) { 00493 MsgStream log(msgSvc(), "RootIOCnvSvc"); 00494 log << MSG::WARNING 00495 << "error in closing file for " << it->first 00496 << endreq; 00497 } 00498 } 00499 if (m_outputStreamMap.size()) { 00500 RootOutputFileManager::get().setIncidentSvc(0); // trigger a release 00501 } 00502 return ConversionSvc::finalize(); 00503 } 00504 00505 StatusCode RootIOCnvSvc::queryInterface(const InterfaceID& riid, void** ppint) 00506 { 00507 MsgStream log(msgSvc(), "RootIOCnvSvc"); 00508 00509 if (IID_IRootIOSvc.versionMatch(riid)) { 00510 log << MSG::DEBUG << "queryInterface("<<riid<<") --> (IRootIOSvc*)" 00511 << (void*)this 00512 << endreq; 00513 *ppint = (IRootIOSvc*)this; 00514 } 00515 else if (IID_IConversionSvc.versionMatch(riid)) { 00516 log << MSG::DEBUG << "queryInterface("<<riid<<") --> (IConversionSvc*)" 00517 << (void*)this 00518 << endreq; 00519 *ppint = (IConversionSvc*)this; 00520 } 00521 else { 00522 return this->ConversionSvc::queryInterface(riid,ppint); 00523 } 00524 addRef(); 00525 return StatusCode::SUCCESS; 00526 }