ATLAS Offline Software
Loading...
Searching...
No Matches
AthCnvSvc.cxx
Go to the documentation of this file.
1
2
3/*
4 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
5*/
6
7// AthCnvSvc.cxx
8// Implementation file for class AthCnvSvc
9// Author: S.Binet<binet@cern.ch>
11
12// STL includes
13
14// Framework includes
15#include "Gaudi/Property.h"
16#include "GaudiKernel/DataObject.h"
17#include "GaudiKernel/System.h"
18#include "GaudiKernel/IConverter.h"
19#include "GaudiKernel/IDataProviderSvc.h"
20#include "GaudiKernel/IOpaqueAddress.h"
21
22// AthenaBaseComps includes
24
25#include "GaudiKernel/Converter.h"
26
28
39
41// Public methods:
43
44// Constructors
46AthCnvSvc::AthCnvSvc (const std::string& name,
47 ISvcLocator* pSvcLocator,
48 long type) :
49 base_class (name, pSvcLocator),
50 m_dataSvc (0),
52 m_type (type),
53 m_workers ( )
54{
55}
56
57// Destructor
60{
61 // the following is hopefully (!) temporary hack to prevent deleting
62 // services we hold a reference count to.
63 // the problem is that these references might point back to us (so we
64 // end up recursively calling the d-tor) or be double-deleted later on
65 // by the ServiceManager.
66 // the correct fix is to have everybody use SmartIF<T> all over the code...
67 //
68 // "temporary hack" ha ha! (CGL 5/2014)
69 //
70 if (m_cnvSvc) {
71 m_cnvSvc->addRef();
72 m_cnvSvc = 0;
73 }
74 if (m_addressCreator) {
75 m_addressCreator->addRef();
77 }
78 if (m_dataSvc) {
79 m_dataSvc->addRef();
80 m_dataSvc = 0;
81 }
82
83 ATH_MSG_DEBUG ("release-ing all workers (" << m_workers.size() << ")...");
84 for ( Workers::iterator
85 i = m_workers.begin(),
86 iend = m_workers.end();
87 i != iend;
88 ++i ) {
89 IConverter *cnv = i->second.m_converter;
90 if (cnv) {
91
92 if (!cnv->release()) {
93 i->second.m_converter = 0;
94 }
95 }
96 }
97 ATH_MSG_DEBUG ("release-ing all workers (" << m_workers.size() << ")... [done]");
98 m_workers.clear();
99
100}
101
102// Athena Service's Hooks
105{
106 m_cnvSvc = this; // needed for conversionSvc()
108
109 return StatusCode::SUCCESS;
110}
111
113{
114 ATH_MSG_DEBUG ("releasing all workers");
115 for ( Workers::iterator
116 i = m_workers.begin(),
117 iend = m_workers.end();
118 i != iend;
119 ++i ) {
120 if (!i->second.converter()->finalize().isSuccess()) {
121 ATH_MSG_ERROR ("finalizing worker w/ clid=[" << i->first << "]");
122 }
123 i->second.converter()->release();
124 }
125 //m_workers.clear();
126 Workers().swap (m_workers);
127
128 if (m_addressCreator) m_addressCreator->addRef();
129 if (m_dataSvc) m_dataSvc->addRef();
130 if (m_cnvSvc) m_cnvSvc->addRef();
131
133 m_dataSvc = 0;
134 m_cnvSvc = 0;
135
136 return StatusCode::SUCCESS;
137}
138
140
141
142long
144{
145 return m_type;
146}
147
149const CLID&
151{
152 return CLID_NULL;
153}
154
159StatusCode
160AthCnvSvc::setDataProvider(IDataProviderSvc* pDataSvc)
161{
162 if ( !pDataSvc ) return StatusCode::SUCCESS; //Atlas does not use DataSvc
163 if ( m_dataSvc ) m_dataSvc->release();
164 m_dataSvc = pDataSvc;
165 m_dataSvc->addRef();
166 Workers::iterator stop = m_workers.end();
167 Workers::iterator start = m_workers.begin();
168 for(Workers::iterator i=start; i != stop; ++i ) {
169 IConverter* cnv = i->second.converter();
170 if ( 0 != cnv ) {
171 if (cnv->setDataProvider(m_dataSvc).isFailure()) {
172 ATH_MSG_ERROR ("setting Data Provider");
173 }
174 }
175 }
176 return StatusCode::SUCCESS;
177}
178
182SmartIF<IDataProviderSvc>&
184{
185 // FIXME: Ideally the return type should be const, but that would require
186 // changes in the Gaudi IConverter base class.
187 SmartIF<IDataProviderSvc>& svc ATLAS_THREAD_SAFE =
188 const_cast<SmartIF<IDataProviderSvc>&>(m_dataSvc);
189 return svc;
190}
191
194StatusCode
195AthCnvSvc::setConversionSvc(IConversionSvc* /*svc*/)
196{
197 return StatusCode::FAILURE;
198}
199
202SmartIF<IConversionSvc>&
204{
205 // FIXME: Ideally the return type should be const, but that would require
206 // changes in the Gaudi IConverter base class.
207 SmartIF<IConversionSvc>& svc ATLAS_THREAD_SAFE =
208 const_cast<SmartIF<IConversionSvc>&>(m_cnvSvc);
209 return svc;
210}
211
213StatusCode
214AthCnvSvc::setAddressCreator(IAddressCreator* creator)
215{
216 m_addressCreator = creator;
217 Workers::iterator stop = m_workers.end();
218 Workers::iterator start = m_workers.begin();
219 for(Workers::iterator i=start; i != stop; ++i ) {
220 IConverter* cnv = i->second.converter();
221 if ( 0 != cnv ) {
222 if (cnv->setAddressCreator(m_addressCreator).isFailure()) {
223 ATH_MSG_ERROR ("setting Address Creator");
224 }
225 }
226 }
227 return StatusCode::SUCCESS;
228}
229
231SmartIF<IAddressCreator>&
233{
234 // FIXME: Ideally the return type should be const, but that would require
235 // changes in the Gaudi IConverter base class.
236 SmartIF<IAddressCreator>& svc ATLAS_THREAD_SAFE =
237 const_cast<SmartIF<IAddressCreator>&>(m_addressCreator);
238 return svc;
239}
240
243StatusCode
244AthCnvSvc::createObj(IOpaqueAddress* pAddress,DataObject*& refpObject)
245{
246 return makeCall (CREATE_OBJ, false, true, false, pAddress, refpObject);
247}
248
251StatusCode
252AthCnvSvc::fillObjRefs(IOpaqueAddress* pAddress, DataObject* pObject)
253{
254 return makeCall (FILL_OBJ_REFS, false, true, true, pAddress, pObject);
255}
256
259StatusCode
260AthCnvSvc::updateObj(IOpaqueAddress* pAddress, DataObject* pObject)
261{
262 return makeCall (UPDATE_OBJ, false, true, false, pAddress, pObject);
263}
264
267StatusCode
268AthCnvSvc::updateObjRefs(IOpaqueAddress* pAddress, DataObject* pObject)
269{
270 return makeCall (UPDATE_OBJ_REFS, false, true, true, pAddress, pObject);
271}
272
275StatusCode
276AthCnvSvc::createRep(DataObject* pObject, IOpaqueAddress*& refpAddress)
277{
278 return makeCall (CREATE_REP, true, false, false, refpAddress, pObject);
279}
280
283StatusCode
284AthCnvSvc::fillRepRefs(IOpaqueAddress* pAddress,DataObject* pObject)
285{
286 return makeCall (FILL_REP_REFS, true, false, false, pAddress, pObject);
287}
288
291StatusCode
292AthCnvSvc::updateRep(IOpaqueAddress* pAddress, DataObject* pObject)
293{
294 return makeCall (UPDATE_REP, true, false, false, pAddress, pObject);
295}
296
299StatusCode
300AthCnvSvc::updateRepRefs(IOpaqueAddress* pAddress, DataObject* pObject)
301{
302 return makeCall (UPDATE_REP_REFS, true, false, false, pAddress, pObject);
303}
304
306StatusCode
308{
309 // First look for the more specific converter
310 long typ = repSvcType();
311 IConverter* pConverter = createConverter(typ, clid, 0);
312 if ( 0 != pConverter ) {
313 StatusCode status = configureConverter( typ, clid, pConverter );
314 if ( status.isSuccess() ) {
315 status = initializeConverter( typ, clid, pConverter );
316 if ( status.isSuccess() ) {
317 status = activateConverter( typ, clid, pConverter );
318 if ( status.isSuccess() ) {
319 long conv_typ = pConverter->repSvcType();
320 const CLID& conv_clid = pConverter->objType();
321 typ = (typ<0xFF) ? typ : typ&0xFFFFFF00;
322 conv_typ = (conv_typ<0xFF) ? conv_typ : conv_typ&0xFFFFFF00;
323 if ( conv_typ == typ && conv_clid == clid ) {
324 return addConverter(pConverter);
325 }
326 }
327 }
328 }
329 pConverter->release();
330 }
331 return Status::NO_CONVERTER;
332}
333
335StatusCode
336AthCnvSvc::addConverter(IConverter* pConverter)
337{
338 if ( 0 != pConverter ) {
339 const CLID& clid = pConverter->objType();
340 removeConverter(clid).ignore();
341 m_workers.insert (std::make_pair(clid,WorkerEntry(clid, pConverter)));
342 pConverter->addRef();
343 return StatusCode::SUCCESS;
344 }
345 return Status::NO_CONVERTER;
346}
347
349StatusCode
351{
352 Workers::iterator worker = m_workers.find (clid);
353 if ( worker != m_workers.end() ) {
354 worker->second.converter()->finalize().ignore();
355 worker->second.converter()->release();
356
357 m_workers.erase (worker);
358 return StatusCode::SUCCESS;
359 }
360 return Status::NO_CONVERTER;
361}
362
364IConverter*
366{
367 std::lock_guard<CallMutex> lock(m_conv_mut);
368 Workers::iterator worker = m_workers.find (clid);
369 if ( worker != m_workers.end() ) {
370 return worker->second.converter();
371 }
372 if (addConverter (clid).isSuccess()) {
373 worker = m_workers.find (clid);
374 if (worker != m_workers.end()) {
375 return worker->second.converter();
376 }
377 } else {
378 ATH_MSG_INFO("problem adding converter for CLID [" << clid << "]");
379 }
380 return 0;
381}
382
384StatusCode
385AthCnvSvc::connectOutput (const std::string& outputFile,
386 const std::string& /*openMode*/)
387{
388 return connectOutput (outputFile);
389}
390
392StatusCode
393AthCnvSvc::connectOutput(const std::string& /*output*/)
394{
395 return StatusCode::SUCCESS;
396}
397
399StatusCode
400AthCnvSvc::commitOutput(const std::string& /*output*/, bool /*do_commit*/)
401{
402 return StatusCode::SUCCESS;
403}
404
405
407StatusCode
408AthCnvSvc::disconnectOutput(const std::string& /*output*/)
409{
410 return StatusCode::SUCCESS;
411}
412
414
415
417StatusCode
418AthCnvSvc::createAddress (long /*svc_type*/,
419 const CLID& /*clid*/,
420 const std::string* /*par*/,
421 const unsigned long* /*ip*/,
422 IOpaqueAddress*& refpAddress)
423{
424 refpAddress = 0;
425 return StatusCode::FAILURE;
426}
427
429StatusCode
430AthCnvSvc::convertAddress (const IOpaqueAddress* /*pAddress*/,
431 std::string& refAddress)
432{
433 refAddress = "";
434 return StatusCode::FAILURE;
435}
436
438StatusCode
439AthCnvSvc::createAddress (long /*svc_type*/,
440 const CLID& /*clid*/,
441 const std::string& /*refAddress*/,
442 IOpaqueAddress*& refpAddress)
443{
444 refpAddress = 0;
445 return StatusCode::FAILURE;
446}
447
449StatusCode
450AthCnvSvc::updateServiceState(IOpaqueAddress* /*pAddress*/)
451{
452 return StatusCode::SUCCESS;
453}
454
455
457// Protected methods:
459
461IConverter*
463 const CLID& clid,
464 const ICnvFactory* /*fac*/)
465{
466
467 std::unique_ptr<IConverter> cnv{Converter::Factory::create
468 (ConverterID(typ,clid), serviceLocator().get() )};
469
470 if (!cnv) {
471 typ = (typ<0xFF) ? typ : typ&0xFFFFFF00;
472 cnv = Converter::Factory::create
473 (ConverterID(typ,clid), serviceLocator().get() );
474 }
475 return cnv.release();
476
477}
478
480StatusCode
481AthCnvSvc::configureConverter (long /*typ*/, const CLID& /*clid*/,
482 IConverter* cnv)
483{
484 if (cnv) {
485 cnv->setConversionSvc(this).ignore();
486 cnv->setAddressCreator(m_addressCreator).ignore();
487 cnv->setDataProvider(m_dataSvc).ignore();
488 return StatusCode::SUCCESS;
489 }
490 return Status::NO_CONVERTER;
491
492}
493
495StatusCode
496AthCnvSvc::initializeConverter (long /*typ*/, const CLID& /*clid*/,
497 IConverter* cnv)
498{
499 if (cnv) {
500 return cnv->initialize();
501 }
502 return Status::NO_CONVERTER;
503}
504
506StatusCode
507AthCnvSvc::activateConverter (long /*typ*/, const CLID& /*clid*/,
508 IConverter* cnv)
509{
510 if (cnv) {
511 return StatusCode::SUCCESS;
512 }
513 return Status::NO_CONVERTER;
514}
515
517void
518AthCnvSvc::loadConverter(DataObject* /*pObject*/)
519{
520}
521
522
523StatusCode
525 bool ignore_add,
526 bool ignore_obj,
527 bool update,
528 IOpaqueAddress*& pAddress,
529 DataObject*& pObject)
530{
531 if ( 0 != pAddress || ignore_add ) {
532 if ( 0 != pObject || ignore_obj ) {
533 const CLID& obj_class =
534 (0 != pObject && !ignore_obj) ? pObject->clID()
535 : (0 != pAddress && !ignore_add)
536 ? pAddress->clID()
537 : CLID_NULL;
538 IConverter* cnv = converter(obj_class);
539 if ( !cnv && pObject ) {
540 //Give it a try to autoload the class (dictionary) for which the converter is needed
541 loadConverter( pObject);
542 cnv = converter(obj_class);
543 }
544
545 StatusCode status(StatusCode::FAILURE);
546 if ( 0 != cnv ) {
547 switch(typ) {
548 case CREATE_OBJ:
549 status = cnv->createObj(pAddress, pObject);
550 break;
551 case FILL_OBJ_REFS:
552 status = cnv->fillObjRefs(pAddress, pObject);
553 break;
554 case UPDATE_OBJ:
555 status = cnv->updateObj(pAddress, pObject);
556 break;
557 case UPDATE_OBJ_REFS:
558 status = cnv->updateObjRefs(pAddress, pObject);
559 break;
560 case CREATE_REP:
561 status = cnv->createRep(pObject, pAddress);
562 break;
563 case FILL_REP_REFS:
564 status = cnv->fillRepRefs(pAddress, pObject);
565 break;
566 case UPDATE_REP:
567 status = cnv->updateRep(pAddress, pObject);
568 break;
569 case UPDATE_REP_REFS:
570 status = cnv->updateRepRefs(pAddress, pObject);
571 break;
572 default:
573 status = StatusCode::FAILURE;
574 break;
575 }
576 if ( status.isSuccess() && update ) {
577 status = updateServiceState(pAddress);
578 }
579 return status;
580 }
581 status.ignore();
582 msg(MSG::INFO) << "No converter for object ";
583 if ( pObject != 0 ) {
584 msg(MSG::INFO) << System::typeinfoName(typeid(*pObject));
585 }
586 msg(MSG::INFO) << " CLID= " << obj_class << endmsg;
587 return Status::NO_CONVERTER;
588 }
589 return Status::INVALID_OBJECT;
590 }
591 return Status::INVALID_ADDRESS;
592}
593
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
CnvSvcAction
Definition AthCnvSvc.cxx:29
@ CREATE_OBJ
Definition AthCnvSvc.cxx:30
@ UPDATE_OBJ
Definition AthCnvSvc.cxx:32
@ UPDATE_REP
Definition AthCnvSvc.cxx:36
@ UPDATE_REP_REFS
Definition AthCnvSvc.cxx:37
@ CREATE_REP
Definition AthCnvSvc.cxx:34
@ FILL_OBJ_REFS
Definition AthCnvSvc.cxx:31
@ FILL_REP_REFS
Definition AthCnvSvc.cxx:35
@ UPDATE_OBJ_REFS
Definition AthCnvSvc.cxx:33
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
uint32_t CLID
The Class ID type.
Define macros for attributes used to control the static checker.
#define ATLAS_THREAD_SAFE
virtual SmartIF< IAddressCreator > & addressCreator() const override
Retrieve address creator facility.
virtual StatusCode setAddressCreator(IAddressCreator *creator) override
Set address creator facility.
virtual StatusCode activateConverter(long typ, const CLID &clid, IConverter *cnv)
Activate the new converter after initialization.
virtual StatusCode connectOutput(const std::string &outputFile, const std::string &openMode) override
Connect the output file to the service with open mode.
virtual IConverter * createConverter(long typ, const CLID &clid, const ICnvFactory *fac)
Create new Converter using factory.
virtual StatusCode updateRepRefs(IOpaqueAddress *pAddress, DataObject *pObject) override
Implementation of IConverter: Update the references of an already converted object.
virtual StatusCode updateObjRefs(IOpaqueAddress *pAddress, DataObject *pObject) override
Implementation of IConverter: Update the references of an updated transient object.
virtual StatusCode updateServiceState(IOpaqueAddress *pAddress)
Update state of the service.
StatusCode makeCall(int typ, bool ignore_add, bool ignore_obj, bool update, IOpaqueAddress *&pAddress, DataObject *&pObject)
SmartIF< IDataProviderSvc > m_dataSvc
Pointer to data provider service.
Definition AthCnvSvc.h:310
virtual StatusCode updateObj(IOpaqueAddress *pAddress, DataObject *refpObject) override
Implementation of IConverter: Update the transient object from the other representation.
virtual void loadConverter(DataObject *pObject)
Load converter or dictionary needed by the converter.
virtual StatusCode finalize() override
virtual SmartIF< IConversionSvc > & conversionSvc() const override
Implementation of IConverter: Get conversion service the converter is connected to.
virtual StatusCode createRep(DataObject *pObject, IOpaqueAddress *&refpAddress) override
Implementation of IConverter: Convert the transient object to the requested representation.
virtual StatusCode setDataProvider(IDataProviderSvc *pService) override
Implementation of IConverter: Set Data provider service.
virtual ~AthCnvSvc()
Destructor:
Definition AthCnvSvc.cxx:59
virtual long repSvcType() const override
Retrieve the class type of the data store the converter uses.
virtual StatusCode addConverter(const CLID &clid) override
Add converter object to conversion service.
virtual StatusCode removeConverter(const CLID &clid) override
Remove converter object from conversion service (if present).
virtual StatusCode convertAddress(const IOpaqueAddress *pAddress, std::string &refAddress) override
Convert an address to string form.
Workers m_workers
List of conversion workers.
Definition AthCnvSvc.h:318
virtual const CLID & objType() const override
Implementation of IConverter: dummy call.
virtual StatusCode updateRep(IOpaqueAddress *pAddress, DataObject *pObject) override
Implementation of IConverter: Update the converted representation of a transient object.
virtual StatusCode createAddress(long svc_type, const CLID &clid, const std::string *par, const unsigned long *ip, IOpaqueAddress *&refpAddress) override
Create a Generic address using explicit arguments to identify a single object.
virtual StatusCode initializeConverter(long typ, const CLID &clid, IConverter *cnv)
Initialize the new converter.
std::unordered_map< CLID, WorkerEntry > Workers
Definition AthCnvSvc.h:105
AthCnvSvc()
Default constructor:
virtual StatusCode createObj(IOpaqueAddress *pAddress, DataObject *&refpObject) override
Implementation of IConverter: Create the transient representation of an object.
virtual StatusCode disconnectOutput(const std::string &output)
Disconnect output files from the service.
SmartIF< IAddressCreator > m_addressCreator
Pointer to the address creation service interface.
Definition AthCnvSvc.h:312
long m_type
Conversion service type.
Definition AthCnvSvc.h:316
CallMutex m_conv_mut
Definition AthCnvSvc.h:321
virtual StatusCode initialize() override
Gaudi Service Implementation.
virtual StatusCode fillObjRefs(IOpaqueAddress *pAddress, DataObject *pObject) override
Implementation of IConverter: Resolve the references of the created transient object.
virtual IConverter * converter(const CLID &wanted) override
Retrieve converter from list.
virtual StatusCode fillRepRefs(IOpaqueAddress *pAddress, DataObject *pObject) override
Implementation of IConverter: Resolve the references of the converted object.
virtual StatusCode commitOutput(const std::string &output, bool do_commit) override
Commit pending output.
virtual SmartIF< IDataProviderSvc > & dataProvider() const override
Implementation of IConverter: Get Data provider service.
virtual StatusCode configureConverter(long typ, const CLID &clid, IConverter *cnv)
Configure the new converter before initialize is called.
SmartIF< IConversionSvc > m_cnvSvc
Pointer to the IConversionSvc interface of this.
Definition AthCnvSvc.h:314
virtual StatusCode setConversionSvc(IConversionSvc *svc) override
Implementation of IConverter: Set conversion service the converter is connected to.
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130
MsgStream & msg
Definition testRead.cxx:32