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