| # Gaudi Framework, version v25r0 |

Home |  | Generated: Mon Feb 17 2014

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
PersistencySvc.cpp
Go to the documentation of this file.
1 //====================================================================
2 // PersistencySvc.cpp
3 //--------------------------------------------------------------------
4 //
5 // Package : System ( The LHCb Offline System)
6 //
7 // Description: implementation of the PersistencySvc
8 //
9 // Author : M.Frank
10 // History :
11 // +---------+----------------------------------------------+---------
12 // | Date | Comment | Who
13 // +---------+----------------------------------------------+---------
14 // | 29/10/98| Initial version | MF
15 // +---------+----------------------------------------------+---------
16 //
17 //====================================================================
18 #define PERSISTENCYSVC_PERSISTENCYSVC_CPP
19
20 // Interface definitions
21 #include "GaudiKernel/SmartIF.h"
22 #include "GaudiKernel/DataObject.h"
23 #include "GaudiKernel/IConverter.h"
24 #include "GaudiKernel/ISvcLocator.h"
25 #include "GaudiKernel/IDataSelector.h"
26 #include "GaudiKernel/IOpaqueAddress.h"
27 #include "GaudiKernel/MsgStream.h"
28 #include "GaudiKernel/strcasecmp.h"
29 #include "GaudiKernel/TypeNameString.h"
30 #include "GaudiKernel/IDataProviderSvc.h"
31
32 // Implementation specific definitions
33 #include "PersistencySvc.h"
34
35 #define ON_DEBUG if (UNLIKELY(outputLevel() <= MSG::DEBUG))
36 #define ON_VERBOSE if (UNLIKELY(outputLevel() <= MSG::VERBOSE))
37
38 #define DEBMSG ON_DEBUG debug()
39 #define VERMSG ON_VERBOSE verbose()
40
41 // Instantiation of a static factory class used by clients to create
42 // instances of this service
43 DECLARE_COMPONENT(PersistencySvc)
44
45 enum CnvSvcAction {
46 CREATE_OBJ,
47 FILL_OBJ_REFS,
48 UPDATE_OBJ,
49 UPDATE_OBJ_REFS,
50 CREATE_REP,
51 FILL_REP_REFS,
52 UPDATE_REP,
53 UPDATE_REP_REFS
54 };
55
56 StatusCode PersistencySvc::makeCall(int typ,
57 IOpaqueAddress*& pAddress,
58 DataObject*& pObject) {
59 if ( m_enable ) {
60 IConversionSvc* svc = 0;
61 switch(typ) {
62 case CREATE_REP:
63 case FILL_REP_REFS:
64 case UPDATE_REP:
65 case UPDATE_REP_REFS:
66 svc = m_cnvDefault;
67 break;
68 default:
69 if ( 0 != pAddress ) {
70 long svc_type = pAddress->svcType();
71 svc = service(svc_type);
72 if ( 0 == svc ) {
73 return BAD_STORAGE_TYPE;
74 }
75 }
76 else {
77 return INVALID_ADDRESS;
78 }
79 break;
80 }
81
82 StatusCode status(StatusCode::FAILURE,true);
83 switch( typ ) {
84 case CREATE_OBJ:
85 pObject = 0;
86 status = svc->createObj(pAddress, pObject);
87 break;
88 case FILL_OBJ_REFS:
89 status = svc->fillObjRefs(pAddress, pObject);
90 break;
91 case UPDATE_OBJ:
92 status = svc->updateObj(pAddress, pObject);
93 break;
94 case UPDATE_OBJ_REFS:
95 status = svc->updateObjRefs(pAddress, pObject);
96 break;
97 case CREATE_REP:
98 status = svc->createRep(pObject, pAddress);
99 break;
100 case FILL_REP_REFS:
101 status = svc->fillRepRefs(pAddress, pObject);
102 break;
103 case UPDATE_REP:
104 status = svc->updateRep(pAddress, pObject);
105 break;
106 case UPDATE_REP_REFS:
107 status = svc->updateRepRefs(pAddress, pObject);
108 break;
109 default:
110 status = StatusCode::FAILURE;
111 break;
112 }
113 status.ignore();
114 return status;
115 }
116 return StatusCode::SUCCESS;
117 }
118
120 StatusCode PersistencySvc::createObj(IOpaqueAddress* pAddr, DataObject*& refpObj) {
121 return makeCall(CREATE_OBJ, pAddr, refpObj);
122 }
123
125 StatusCode PersistencySvc::fillObjRefs(IOpaqueAddress* pAddr, DataObject* pObj) {
126 return makeCall(FILL_OBJ_REFS, pAddr, pObj);
127 }
128
130 StatusCode PersistencySvc::updateObj(IOpaqueAddress* pAddr, DataObject* pObj) {
131 return makeCall(UPDATE_OBJ, pAddr, pObj);
132 }
133
135 StatusCode PersistencySvc::updateObjRefs(IOpaqueAddress* pAddr, DataObject* pObj) {
136 return makeCall(UPDATE_OBJ_REFS, pAddr, pObj);
137 }
138
140 StatusCode PersistencySvc::createRep(DataObject* pObj, IOpaqueAddress*& refpAddr) {
141 return makeCall(CREATE_REP, refpAddr, pObj);
142 }
143
145 StatusCode PersistencySvc::fillRepRefs(IOpaqueAddress* pAddr, DataObject* pObj) {
146 return makeCall(FILL_REP_REFS, pAddr, pObj);
147 }
148
150 StatusCode PersistencySvc::updateRep(IOpaqueAddress* pAddr, DataObject* pObj) {
151 return makeCall(UPDATE_REP, pAddr, pObj);
152 }
153
155 StatusCode PersistencySvc::updateRepRefs(IOpaqueAddress* pAddr, DataObject* pObj) {
156 return makeCall(UPDATE_REP_REFS, pAddr, pObj);
157 }
158
160 SmartIF<IAddressCreator>& PersistencySvc::addressCreator(long type) {
161 long typ = type;
162 Services::iterator it = m_cnvServices.find( typ );
163 if( it == m_cnvServices.end() ) {
164 IConversionSvc* s = service(type);
165 if ( s ) {
166 it = m_cnvServices.find( typ );
167 if ( it != m_cnvServices.end() ) {
168 return (*it).second.addrCreator();
169 }
170 }
171 static SmartIF<IAddressCreator> no_creator;
172 return no_creator;
173 }
174 return (*it).second.addrCreator();
175 }
176
178 StatusCode PersistencySvc::setDataProvider(IDataProviderSvc* pDataSvc) {
179 m_dataSvc = pDataSvc;
180 for ( Services::iterator i = m_cnvServices.begin(); i != m_cnvServices.end(); i++ ) {
181 (*i).second.conversionSvc()->setDataProvider(m_dataSvc).ignore();
182 }
183 return StatusCode(StatusCode::SUCCESS,true);
184 }
185
187 SmartIF<IDataProviderSvc>& PersistencySvc::dataProvider() const {
188 return m_dataSvc;
189 }
190
192 StatusCode PersistencySvc::setConversionSvc(IConversionSvc* svc) {
193 m_cnvDefault = svc;
194 return StatusCode(StatusCode::SUCCESS,true);
195 }
196
198 SmartIF<IConversionSvc>& PersistencySvc::conversionSvc() const {
199 return m_cnvDefault;
200 }
201
203 StatusCode PersistencySvc::addConverter(const CLID& /* clid */) {
204 return StatusCode::FAILURE;
205 }
206
208 StatusCode PersistencySvc::addConverter(IConverter* pConverter) {
209 if ( 0 != pConverter ) {
210 long typ = pConverter->repSvcType();
211 IConversionSvc* svc = service(typ);
212 if ( 0 != svc ) {
213 return svc->addConverter(pConverter);
214 }
215 return BAD_STORAGE_TYPE;
216 }
217 return NO_CONVERTER;
218 }
219
221 StatusCode PersistencySvc::removeConverter(const CLID& clid) {
222 // Remove converter type from all services
223 StatusCode status = NO_CONVERTER, iret = StatusCode::SUCCESS;
224 for ( Services::iterator i = m_cnvServices.begin(); i != m_cnvServices.end(); i++ ) {
225 iret = (*i).second.conversionSvc()->removeConverter(clid);
226 if ( iret.isSuccess() ) {
227 status = iret;
228 }
229 }
230 return status;
231 }
232
234 IConverter* PersistencySvc::converter(const CLID& /*clid*/) {
235 return 0;
236 }
237
239 SmartIF<IConversionSvc>& PersistencySvc::service(const std::string& nam) {
240 Gaudi::Utils::TypeNameString tn(nam);
241 IConversionSvc* svc = 0;
242 for ( Services::iterator it = m_cnvServices.begin(); it != m_cnvServices.end(); it++ ) {
243 if ( (*it).second.service()->name() == tn.name() ) {
244 return (*it).second.conversionSvc();
245 }
246 }
247 StatusCode status = Service::service(nam, svc, true);
248 if ( status.isSuccess() ) {
249 if ( addCnvService(svc).isSuccess() ) {
250 svc->release(); // Do not double-reference count
251 return service(nam); // now it is in the list
252 }
253 }
254 info() << "Cannot access Conversion service:" << nam << endmsg;
255 static SmartIF<IConversionSvc> no_svc;
256 return no_svc;
257 }
258
260 SmartIF<IConversionSvc>& PersistencySvc::service(long type) {
261 typedef std::vector<std::string> SvcNames;
262 // Check wether this is already an active service
263 Services::iterator it = m_cnvServices.find( type );
264 if( it != m_cnvServices.end() ) {
265 return (*it).second.conversionSvc();
266 }
267 // if not, check if the service is in the list and may be requested
268 const SvcNames& theNames = m_svcNames.value();
269 for ( SvcNames::const_iterator i = theNames.begin(); i != theNames.end(); i++ ) {
270 SmartIF<IConversionSvc>& svc = service(*i);
271 if ( svc != 0 ) {
272 long typ = svc->repSvcType();
273 if ( typ == type ) {
274 return svc;
275 }
276 }
277 }
278 static SmartIF<IConversionSvc> no_svc;
279 return no_svc;
280 }
281
283 StatusCode PersistencySvc::addCnvService(IConversionSvc* servc) {
284 if ( 0 != servc ) {
285 long type = servc->repSvcType();
286 long def_typ = (m_cnvDefault) ? m_cnvDefault->repSvcType() : 0;
287 Services::iterator it = m_cnvServices.find( type );
288 IConversionSvc* cnv_svc = 0;
289 if ( it != m_cnvServices.end() ) {
290 cnv_svc = (*it).second.conversionSvc();
291 }
292 if ( type == def_typ ) {
293 m_cnvDefault = servc;
294 }
295 if ( cnv_svc != servc ) {
296 IAddressCreator* icr = 0;
297 StatusCode status = servc->queryInterface(IAddressCreator::interfaceID(), pp_cast<void>(&icr));
298 if ( status.isSuccess() ) {
299 IService* isvc = 0;
300 status = servc->queryInterface(IService::interfaceID(), pp_cast<void>(&isvc));
301 if ( status.isSuccess() ) {
302 if ( 0 != cnv_svc ) {
303 removeCnvService (type).ignore();
304 }
305 std::pair<Services::iterator, bool> p =
306 m_cnvServices.insert( Services::value_type( type, ServiceEntry(type, isvc, servc, icr)));
307 if( p.second ) {
308 info() << "Added successfully Conversion service:" << isvc->name() << endmsg;
309 servc->addRef();
310 servc->setAddressCreator(this).ignore();
311 servc->setDataProvider(m_dataSvc).ignore();
312 return StatusCode::SUCCESS;
313 }
314 info() << "Cannot add Conversion service of type " << isvc->name() << endmsg;
315 isvc->release();
316 icr->release();
317 return StatusCode::FAILURE;
318 }
319 icr->release();
320 }
321 info() << "Cannot add Conversion service of type " << type << endmsg;
322 return StatusCode::FAILURE;
323 }
324 else {
325 return StatusCode::SUCCESS;
326 }
327 }
328 return BAD_STORAGE_TYPE;
329 }
330
332 StatusCode PersistencySvc::removeCnvService(long svctype) {
333 Services::iterator it = m_cnvServices.find( svctype );
334 if( it != m_cnvServices.end() ) {
335 (*it).second.service()->release();
336 (*it).second.addrCreator()->release();
337 m_cnvServices.erase(it);
338 return StatusCode::SUCCESS;
339 }
340 return BAD_STORAGE_TYPE;
341 }
342
344 long PersistencySvc::repSvcType() const {
345 long typ = (m_cnvDefault) ? m_cnvDefault->repSvcType() : 0;
346 return typ;
347 }
348
350 StatusCode PersistencySvc::setDefaultCnvService(long type) {
351 m_cnvDefault = service(type);
352 return StatusCode::SUCCESS;
353 }
354
356 StatusCode PersistencySvc::connectOutput(const std::string& outputFile,
357 const std::string& /* openMode */) {
358 return connectOutput(outputFile);
359 }
360
362 StatusCode PersistencySvc::connectOutput(const std::string&) {
363 return StatusCode::SUCCESS;
364 }
365
367 StatusCode PersistencySvc::commitOutput(const std::string& , bool ) {
368 return StatusCode::SUCCESS;
369 }
370
372 StatusCode PersistencySvc::createAddress(long svc_type,
373 const CLID& clid,
374 const std::string* pars,
375 const unsigned long* ipars,
376 IOpaqueAddress*& refpAddress) {
377 IAddressCreator* svc = addressCreator(svc_type);
378 StatusCode status = BAD_STORAGE_TYPE; // Preset error
379 refpAddress = 0;
380 if ( 0 != svc ) {
381 status = svc->createAddress(svc_type, clid, pars, ipars, refpAddress);
382 }
383 return status;
384 }
385
387 StatusCode PersistencySvc::convertAddress( const IOpaqueAddress* pAddress,
388 std::string& refAddress)
389 {
390 // Assumuption is that the Persistency service prepends a header
391 // and requests the conversion service refered to by the service
392 // type to encode the rest
393 long svc_type = 0;
394 CLID clid = 0;
395 if ( 0 != pAddress ) {
396 svc_type = pAddress->svcType();
397 clid = pAddress->clID();
398 }
399 IAddressCreator* svc = addressCreator(svc_type);
400 StatusCode status = BAD_STORAGE_TYPE; // Preset error
401 refAddress = "";
402
403 if ( 0 != svc ) {
404 // Found service, set header
405 encodeAddrHdr(svc_type, clid, refAddress);
406 std::string address;
407 // Get rest of address from conversion service
408 status = svc->convertAddress(pAddress, address);
409 refAddress += address;
410 }
411 return status;
412 }
413
415 StatusCode PersistencySvc::createAddress( long /* svc_type */,
416 const CLID& /* clid */,
417 const std::string& refAddress,
418 IOpaqueAddress*& refpAddress)
419 {
420 // Assumption is that the Persistency service decodes that header
421 // and requests the conversion service referred to by the service
422 // type to decode the rest
423 long new_svc_type = 0;
424 CLID new_clid = 0;
425 std::string address_trailer;
426 decodeAddrHdr(refAddress, new_svc_type, new_clid, address_trailer);
427 IAddressCreator* svc = addressCreator(new_svc_type);
428 StatusCode status = BAD_STORAGE_TYPE; // Preset error
429 if ( 0 != svc ) {
430 status = svc->createAddress( new_svc_type, new_clid, address_trailer, refpAddress);
431 }
432 return status;
433 }
434
436 void PersistencySvc::encodeAddrHdr( long service_type,
437 const CLID& clid,
438 std::string& address) const
439 {
440 // For address header, use xml-style format of
441 // <addrhdr service_type="xxx" clid="yyy" />
442 std::stringstream stream;
443 int svctyp = service_type; // must put int into stream, not char
444 stream << "<address_header service_type=\"" << svctyp << "\" clid=\"" << clid << "\" /> ";
445 address = stream.str();
446 }
447
449 void PersistencySvc::decodeAddrHdr( const std::string& address,
450 long& service_type,
451 CLID& clid,
452 std::string& address_trailer) const
453 {
454 // For address header, use xml-style format of
455 // <address_header service_type="xxx" clid="yyy" />
456 service_type = 0;
457 clid = 0;
458 address_trailer = "";
459
460 // Check for address_header tag
461 size_t pos = address.find("<address_header");
462 if (std::string::npos != pos) {
463 // Get service_type
464 pos = address.find("service_type=\"");
465 if (std::string::npos != pos) {
466 pos += 14;
467 size_t end = address.find('"', pos);
468 if (std::string::npos != end) {
469 std::istringstream str(address.substr(pos, end-pos));
470 str >> service_type;
471 // Get clid
472 pos = address.find("clid=\"");
473 if (std::string::npos != pos) {
474 pos += 6;
475 end = address.find('\"', pos);
476 if (std::string::npos != end) {
477 str.clear(); // reuse the istringstream (the error flags must be explicitly cleared)
478 str.str(address.substr(pos, end-pos));
479 str >> clid;
480 // Get trailer_address
481 pos = address.find('>');
482 if (pos < (address.size()-2)) { // this means that '>' was found (pos != npos)
483 // it is before the last char
484 address_trailer = address.substr(pos+1);
485 }
486 }
487 }
488 }
489 }
490 }
491 }
492
494 StatusCode PersistencySvc::setAddressCreator(IAddressCreator*) {
495 // The persistency service is a address creation dispatcher istelf.
496 // The persistency service can NEVER create addresses itself.
497 // The entry point must only be provided in order to fulfill the needs of the
498 // implementing interfaces.
499 return StatusCode::FAILURE;
500 }
501
503 SmartIF<IAddressCreator>& PersistencySvc::addressCreator() const {
504 return m_addrCreator;
505 }
506
508 StatusCode PersistencySvc::getService(long service_type, IConversionSvc*& refpSvc) {
509 refpSvc = service(service_type);
510 return (0==refpSvc) ? StatusCode::FAILURE : StatusCode::SUCCESS;
511 }
512
514 StatusCode PersistencySvc::getService(const std::string& service_type, IConversionSvc*& refpSvc) {
515 const char* imp = service_type.c_str();
516 long len = service_type.length();
517 if ( ::strncasecmp(imp,"SICB", len) == 0 )
518 return getService(SICB_StorageType, refpSvc);
519 else if ( ::strncasecmp(imp,"ZEBRA", len) == 0 )
520 return getService(SICB_StorageType, refpSvc);
521 else if ( ::strncasecmp(imp,"MS Access", len) == 0 )
522 return getService(ACCESS_StorageType, refpSvc);
523 else if ( ::strncasecmp(imp,"Microsoft Access", strlen("Microsoft Access")) == 0 )
524 return getService(ACCESS_StorageType, refpSvc);
525 else if ( ::strncasecmp(imp,"SQL Server", len) == 0 )
526 return getService(SQLSERVER_StorageType, refpSvc);
527 else if ( ::strncasecmp(imp,"Microsoft ODBC for Oracle", len) == 0 )
528 return getService(ORACLE_StorageType, refpSvc);
529 else if ( ::strncasecmp(imp,"Oracle ODBC", strlen("Oracle ODBC")) == 0 )
530 return getService(ORACLE_StorageType, refpSvc);
531 else if ( ::strncasecmp(imp,"Oracle OCI", strlen("Oracle OCI")) == 0 )
532 return getService(ORACLE_StorageType, refpSvc);
533 else if ( ::strncasecmp(imp,"MySQL", len) == 0 )
534 return getService(MYSQL_StorageType, refpSvc);
535 else if ( ::strncasecmp(imp,"ROOT", len) == 0 )
536 return getService(ROOT_StorageType, refpSvc);
537 else if ( ::strncasecmp(imp,"OBJY", len) == 0 )
538 return getService(OBJY_StorageType, refpSvc);
539 else if ( ::strncasecmp(imp,"OBJYECTI", 7) == 0 )
540 return getService(OBJY_StorageType, refpSvc);
541 else if ( ::strncasecmp(imp,"POOL_ROOTKEY", 12) == 0 )
542 return getService(POOL_ROOTKEY_StorageType, refpSvc);
543 else if ( ::strncasecmp(imp,"POOL_ROOTTREE", 12) == 0 )
544 return getService(POOL_ROOTTREE_StorageType, refpSvc);
545 else if ( ::strncasecmp(imp,"POOL_ROOT", 9) == 0 )
546 return getService(POOL_ROOT_StorageType, refpSvc);
547 else if ( ::strncasecmp(imp,"POOL_MySQL", 8) == 0 )
548 return getService(POOL_MYSQL_StorageType, refpSvc);
549 else if ( ::strncasecmp(imp,"POOL_ORACLE", 8) == 0 )
550 return getService(POOL_ORACLE_StorageType, refpSvc);
551 else if ( ::strncasecmp(imp,"POOL_ACCESS", 8) == 0 )
552 return getService(POOL_ACCESS_StorageType, refpSvc);
553 else if ( ::strncasecmp(imp,"POOL", 4) == 0 )
554 return getService(POOL_StorageType, refpSvc);
555
556 for(Services::const_iterator i=m_cnvServices.begin(); i != m_cnvServices.end();++i) {
557 SmartIF<IService> svc((*i).second.conversionSvc());
558 if ( svc ) {
559 // Check wether this is already an active service: first check by service name
560 if ( svc->name() == service_type ) {
561 refpSvc = (*i).second.conversionSvc();
562 return StatusCode::SUCCESS;
563 }
564 // Check wether this is already an active service: now check by service type
565 if ( System::typeinfoName(typeid(*(svc.get()))) == service_type ) {
566 refpSvc = (*i).second.conversionSvc();
567 return StatusCode::SUCCESS;
568 }
569 }
570 }
571 const std::vector<std::string>& names = m_svcNames;
572 // if not, check if the service is in the list and may be requested
573 for(std::vector<std::string>::const_iterator i=names.begin(); i != names.end(); i++) {
574 Gaudi::Utils::TypeNameString itm(*i);
575 if ( itm.name() == service_type || itm.type() == service_type ) {
576 IConversionSvc* svc = service(*i);
577 if ( svc ) {
578 refpSvc = svc;
579 return StatusCode::SUCCESS;
580 }
581 }
582 }
583 return StatusCode::FAILURE;
584 }
585
587 const CLID& PersistencySvc::objType() const {
588 return CLID_NULL;
589 }
590
592 StatusCode PersistencySvc::initialize() {
593 m_addrCreator = this; // initialize internal pointer to IAddressCreator interface
594 // Initialize basic service
595 StatusCode status = Service::initialize();
596 if ( UNLIKELY(!status.isSuccess()) ) {
597 error() << "Error initializing Service base class." << endmsg;
598 }
599 return status;
600 }
601
603 StatusCode PersistencySvc::finalize() {
604 // Release all workers
605 m_cnvServices.clear();
606 // Release references to this to avoid loops
607 m_addrCreator = 0;
608 return StatusCode::SUCCESS;
609 }
610
611 void PersistencySvc::svcNamesHandler( Property& p ) {
612 DEBMSG << p << endmsg;
613 }
614
616 bool PersistencySvc::enable(bool value)
617 {
618 bool old = m_enable;
619 m_enable = value;
620 return old;
621 }
622
624 PersistencySvc::PersistencySvc(const std::string& name, ISvcLocator* svc)
625 : base_class(name, svc),
626 m_cnvDefType(TEST_StorageType),
627 m_enable(true)
628 {
629 declareProperty("CnvServices", m_svcNames);
630 m_svcNames.declareUpdateHandler( &PersistencySvc::svcNamesHandler, this );
631 }
632
634 PersistencySvc::~PersistencySvc() {
635 }