ATLAS Offline Software
Loading...
Searching...
No Matches
AthCnvSvc.cxx
Go to the documentation of this file.
1
2
3/*
4 Copyright (C) 2002-2026 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_addressCreator) {
71 m_addressCreator->addRef();
73 }
74 if (m_dataSvc) {
75 m_dataSvc->addRef();
76 m_dataSvc = 0;
77 }
78
79 ATH_MSG_DEBUG ("release-ing all workers ({})...", m_workers.size());
80 for ( Workers::iterator
81 i = m_workers.begin(),
82 iend = m_workers.end();
83 i != iend;
84 ++i ) {
85 IConverter *cnv = i->second.m_converter;
86 if (cnv) {
87
88 if (!cnv->release()) {
89 i->second.m_converter = 0;
90 }
91 }
92 }
93 ATH_MSG_DEBUG ("release-ing all workers ({})... [done]", m_workers.size());
94 m_workers.clear();
95
96}
97
98// Athena Service's Hooks
101{
103
104 return StatusCode::SUCCESS;
105}
106
108{
109 ATH_MSG_DEBUG ("releasing all workers");
110 for ( Workers::iterator
111 i = m_workers.begin(),
112 iend = m_workers.end();
113 i != iend;
114 ++i ) {
115 if (!i->second.converter()->finalize().isSuccess()) {
116 ATH_MSG_ERROR ("finalizing worker w/ clid=[{}]", i->first);
117 }
118 i->second.converter()->release();
119 }
120 //m_workers.clear();
121 Workers().swap (m_workers);
122
123 if (m_addressCreator) m_addressCreator->addRef();
124 if (m_dataSvc) m_dataSvc->addRef();
125
127 m_dataSvc = 0;
128
129 return StatusCode::SUCCESS;
130}
131
133
134
135long
137{
138 return m_type;
139}
140
142const CLID&
144{
145 return CLID_NULL;
146}
147
152StatusCode
153AthCnvSvc::setDataProvider(IDataProviderSvc* pDataSvc)
154{
155 if ( !pDataSvc ) return StatusCode::SUCCESS; //Atlas does not use DataSvc
156 if ( m_dataSvc ) m_dataSvc->release();
157 m_dataSvc = pDataSvc;
158 m_dataSvc->addRef();
159 Workers::iterator stop = m_workers.end();
160 Workers::iterator start = m_workers.begin();
161 for(Workers::iterator i=start; i != stop; ++i ) {
162 IConverter* cnv = i->second.converter();
163 if ( 0 != cnv ) {
164 if (cnv->setDataProvider(m_dataSvc).isFailure()) {
165 ATH_MSG_ERROR ("setting Data Provider");
166 }
167 }
168 }
169 return StatusCode::SUCCESS;
170}
171
175SmartIF<IDataProviderSvc>&
177{
178 // FIXME: Ideally the return type should be const, but that would require
179 // changes in the Gaudi IConverter base class.
180 SmartIF<IDataProviderSvc>& svc ATLAS_THREAD_SAFE =
181 const_cast<SmartIF<IDataProviderSvc>&>(m_dataSvc);
182 return svc;
183}
184
187StatusCode
188AthCnvSvc::setConversionSvc(IConversionSvc* /*svc*/)
189{
190 return StatusCode::FAILURE;
191}
192
195SmartIF<IConversionSvc>
197{
198 return SmartIF<IConversionSvc>(this);
199}
200
202StatusCode
203AthCnvSvc::setAddressCreator(IAddressCreator* creator)
204{
205 m_addressCreator = creator;
206 Workers::iterator stop = m_workers.end();
207 Workers::iterator start = m_workers.begin();
208 for(Workers::iterator i=start; i != stop; ++i ) {
209 IConverter* cnv = i->second.converter();
210 if ( 0 != cnv ) {
211 if (cnv->setAddressCreator(m_addressCreator).isFailure()) {
212 ATH_MSG_ERROR ("setting Address Creator");
213 }
214 }
215 }
216 return StatusCode::SUCCESS;
217}
218
220SmartIF<IAddressCreator>&
222{
223 // FIXME: Ideally the return type should be const, but that would require
224 // changes in the Gaudi IConverter base class.
225 SmartIF<IAddressCreator>& svc ATLAS_THREAD_SAFE =
226 const_cast<SmartIF<IAddressCreator>&>(m_addressCreator);
227 return svc;
228}
229
232StatusCode
233AthCnvSvc::createObj(IOpaqueAddress* pAddress,DataObject*& refpObject)
234{
235 return makeCall (CREATE_OBJ, false, true, false, pAddress, refpObject);
236}
237
240StatusCode
241AthCnvSvc::fillObjRefs(IOpaqueAddress* pAddress, DataObject* pObject)
242{
243 return makeCall (FILL_OBJ_REFS, false, true, true, pAddress, pObject);
244}
245
248StatusCode
249AthCnvSvc::updateObj(IOpaqueAddress* pAddress, DataObject* pObject)
250{
251 return makeCall (UPDATE_OBJ, false, true, false, pAddress, pObject);
252}
253
256StatusCode
257AthCnvSvc::updateObjRefs(IOpaqueAddress* pAddress, DataObject* pObject)
258{
259 return makeCall (UPDATE_OBJ_REFS, false, true, true, pAddress, pObject);
260}
261
264StatusCode
265AthCnvSvc::createRep(DataObject* pObject, IOpaqueAddress*& refpAddress)
266{
267 return makeCall (CREATE_REP, true, false, false, refpAddress, pObject);
268}
269
272StatusCode
273AthCnvSvc::fillRepRefs(IOpaqueAddress* pAddress,DataObject* pObject)
274{
275 return makeCall (FILL_REP_REFS, true, false, false, pAddress, pObject);
276}
277
280StatusCode
281AthCnvSvc::updateRep(IOpaqueAddress* pAddress, DataObject* pObject)
282{
283 return makeCall (UPDATE_REP, true, false, false, pAddress, pObject);
284}
285
288StatusCode
289AthCnvSvc::updateRepRefs(IOpaqueAddress* pAddress, DataObject* pObject)
290{
291 return makeCall (UPDATE_REP_REFS, true, false, false, pAddress, pObject);
292}
293
295StatusCode
297{
298 // First look for the more specific converter
299 long typ = repSvcType();
300 IConverter* pConverter = createConverter(typ, clid, 0);
301 if ( 0 != pConverter ) {
302 StatusCode status = configureConverter( typ, clid, pConverter );
303 if ( status.isSuccess() ) {
304 status = initializeConverter( typ, clid, pConverter );
305 if ( status.isSuccess() ) {
306 status = activateConverter( typ, clid, pConverter );
307 if ( status.isSuccess() ) {
308 long conv_typ = pConverter->repSvcType();
309 const CLID& conv_clid = pConverter->objType();
310 typ = (typ<0xFF) ? typ : typ&0xFFFFFF00;
311 conv_typ = (conv_typ<0xFF) ? conv_typ : conv_typ&0xFFFFFF00;
312 if ( conv_typ == typ && conv_clid == clid ) {
313 return addConverter(pConverter);
314 }
315 }
316 }
317 }
318 pConverter->release();
319 }
320 return Status::NO_CONVERTER;
321}
322
324StatusCode
325AthCnvSvc::addConverter(IConverter* pConverter)
326{
327 if ( 0 != pConverter ) {
328 const CLID& clid = pConverter->objType();
329 removeConverter(clid).ignore();
330 m_workers.insert (std::make_pair(clid,WorkerEntry(clid, pConverter)));
331 pConverter->addRef();
332 return StatusCode::SUCCESS;
333 }
334 return Status::NO_CONVERTER;
335}
336
338StatusCode
340{
341 Workers::iterator worker = m_workers.find (clid);
342 if ( worker != m_workers.end() ) {
343 worker->second.converter()->finalize().ignore();
344 worker->second.converter()->release();
345
346 m_workers.erase (worker);
347 return StatusCode::SUCCESS;
348 }
349 return Status::NO_CONVERTER;
350}
351
353IConverter*
355{
356 std::lock_guard<CallMutex> lock(m_convsvc_mut);
357 Workers::iterator worker = m_workers.find (clid);
358 if ( worker != m_workers.end() ) {
359 return worker->second.converter();
360 }
361 if (addConverter (clid).isSuccess()) {
362 worker = m_workers.find (clid);
363 if (worker != m_workers.end()) {
364 return worker->second.converter();
365 }
366 } else {
367 ATH_MSG_INFO("problem adding converter for CLID [{}]", clid);
368 }
369 return 0;
370}
371
373StatusCode
374AthCnvSvc::connectOutput (const std::string& outputFile,
375 const std::string& /*openMode*/)
376{
377 return connectOutput (outputFile);
378}
379
381StatusCode
382AthCnvSvc::connectOutput(const std::string& /*output*/)
383{
384 return StatusCode::SUCCESS;
385}
386
388StatusCode
389AthCnvSvc::commitOutput(const std::string& /*output*/, bool /*do_commit*/)
390{
391 return StatusCode::SUCCESS;
392}
393
394
396StatusCode
397AthCnvSvc::disconnectOutput(const std::string& /*output*/)
398{
399 return StatusCode::SUCCESS;
400}
401
403
404
406StatusCode
407AthCnvSvc::createAddress (long /*svc_type*/,
408 const CLID& /*clid*/,
409 const std::string* /*par*/,
410 const unsigned long* /*ip*/,
411 IOpaqueAddress*& refpAddress)
412{
413 refpAddress = 0;
414 return StatusCode::FAILURE;
415}
416
418StatusCode
419AthCnvSvc::convertAddress (const IOpaqueAddress* /*pAddress*/,
420 std::string& refAddress)
421{
422 refAddress = "";
423 return StatusCode::FAILURE;
424}
425
427StatusCode
428AthCnvSvc::createAddress (long /*svc_type*/,
429 const CLID& /*clid*/,
430 const std::string& /*refAddress*/,
431 IOpaqueAddress*& refpAddress)
432{
433 refpAddress = 0;
434 return StatusCode::FAILURE;
435}
436
438StatusCode
439AthCnvSvc::updateServiceState(IOpaqueAddress* /*pAddress*/)
440{
441 return StatusCode::SUCCESS;
442}
443
444
446// Protected methods:
448
450IConverter*
452 const CLID& clid,
453 const ICnvFactory* /*fac*/)
454{
455
456 std::unique_ptr<IConverter> cnv{Converter::Factory::create
457 (ConverterID(typ,clid), serviceLocator().get() )};
458
459 if (!cnv) {
460 typ = (typ<0xFF) ? typ : typ&0xFFFFFF00;
461 cnv = Converter::Factory::create
462 (ConverterID(typ,clid), serviceLocator().get() );
463 }
464 return cnv.release();
465
466}
467
469StatusCode
470AthCnvSvc::configureConverter (long /*typ*/, const CLID& /*clid*/,
471 IConverter* cnv)
472{
473 if (cnv) {
474 cnv->setConversionSvc(this).ignore();
475 cnv->setAddressCreator(m_addressCreator).ignore();
476 cnv->setDataProvider(m_dataSvc).ignore();
477 return StatusCode::SUCCESS;
478 }
479 return Status::NO_CONVERTER;
480
481}
482
484StatusCode
485AthCnvSvc::initializeConverter (long /*typ*/, const CLID& /*clid*/,
486 IConverter* cnv)
487{
488 if (cnv) {
489 return cnv->initialize();
490 }
491 return Status::NO_CONVERTER;
492}
493
495StatusCode
496AthCnvSvc::activateConverter (long /*typ*/, const CLID& /*clid*/,
497 IConverter* cnv)
498{
499 if (cnv) {
500 return StatusCode::SUCCESS;
501 }
502 return Status::NO_CONVERTER;
503}
504
506void
507AthCnvSvc::loadConverter(DataObject* /*pObject*/)
508{
509}
510
511
512StatusCode
514 bool ignore_add,
515 bool ignore_obj,
516 bool update,
517 IOpaqueAddress*& pAddress,
518 DataObject*& pObject)
519{
520 if ( 0 != pAddress || ignore_add ) {
521 if ( 0 != pObject || ignore_obj ) {
522 const CLID& obj_class =
523 (0 != pObject && !ignore_obj) ? pObject->clID()
524 : (0 != pAddress && !ignore_add)
525 ? pAddress->clID()
526 : CLID_NULL;
527 IConverter* cnv = converter(obj_class);
528 if ( !cnv && pObject ) {
529 //Give it a try to autoload the class (dictionary) for which the converter is needed
530 loadConverter( pObject);
531 cnv = converter(obj_class);
532 }
533
534 StatusCode status(StatusCode::FAILURE);
535 if ( 0 != cnv ) {
536 switch(typ) {
537 case CREATE_OBJ:
538 status = cnv->createObj(pAddress, pObject);
539 break;
540 case FILL_OBJ_REFS:
541 status = cnv->fillObjRefs(pAddress, pObject);
542 break;
543 case UPDATE_OBJ:
544 status = cnv->updateObj(pAddress, pObject);
545 break;
546 case UPDATE_OBJ_REFS:
547 status = cnv->updateObjRefs(pAddress, pObject);
548 break;
549 case CREATE_REP:
550 status = cnv->createRep(pObject, pAddress);
551 break;
552 case FILL_REP_REFS:
553 status = cnv->fillRepRefs(pAddress, pObject);
554 break;
555 case UPDATE_REP:
556 status = cnv->updateRep(pAddress, pObject);
557 break;
558 case UPDATE_REP_REFS:
559 status = cnv->updateRepRefs(pAddress, pObject);
560 break;
561 default:
562 status = StatusCode::FAILURE;
563 break;
564 }
565 if ( status.isSuccess() && update ) {
566 status = updateServiceState(pAddress);
567 }
568 return status;
569 }
570 status.ignore();
571 ATH_MSG_INFO("No converter for object {} CLID={}",
572 pObject != 0 ? System::typeinfoName(typeid(*pObject)) : "",
573 obj_class);
574 return Status::NO_CONVERTER;
575 }
576 return Status::INVALID_OBJECT;
577 }
578 return Status::INVALID_ADDRESS;
579}
580
#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_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_INFO(x,...)
uint32_t CLID
The Class ID type.
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
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 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.
CallMutex m_convsvc_mut
Definition AthCnvSvc.h:319
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:316
virtual const CLID & objType() const override
Implementation of IConverter: dummy call.
virtual SmartIF< IConversionSvc > conversionSvc() override
Implementation of IConverter: Get conversion service the converter is connected to.
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:314
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.
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:132