ATLAS Offline Software
ProxyProviderSvc.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include <algorithm>
6 #include <string>
7 #include <vector>
8 
9 #include "SGTools/DataProxy.h"
13 #include "AthenaKernel/BaseInfo.h"
14 
15 #include "GaudiKernel/IClassIDSvc.h"
16 #include "GaudiKernel/IConversionSvc.h"
17 #include "GaudiKernel/TypeNameString.h"
18 #include "GaudiKernel/GaudiException.h"
19 #include "GaudiKernel/ServiceHandle.h"
20 
21 #include "ProxyProviderSvc.h"
22 
23 #include "boost/range/adaptor/reversed.hpp"
24 #include "TClass.h"
25 
26 using namespace std;
27 
28 
29 namespace {
30 
31 
32 const SG::BaseInfoBase* getBaseInfo (CLID clid)
33 {
34  const SG::BaseInfoBase* bi = SG::BaseInfoBase::find (clid);
35  if (bi) return bi;
36 
37  // Try to force a dictionary load to get it defined.
38  ServiceHandle<IClassIDSvc> clidsvc ("ClassIDSvc", "ProxyProviderSvc");
39  if (!clidsvc.retrieve()) return nullptr;
40  std::string name;
41  if (!clidsvc->getTypeNameOfID (clid, name).isSuccess()) {
42  return nullptr;
43  }
44  (void)TClass::GetClass (name.c_str());
45  return SG::BaseInfoBase::find (clid);
46 }
47 
48 
49 } // anonyous namespace
50 
52  ISvcLocator* svcLoc):
53  base_class(name, svcLoc),
54  m_pDataLoader("EventPersistencySvc", name)
55 {
57 }
58 
60 
63 {
64  ATH_MSG_VERBOSE( "Initializing " << name() );
65 
66  // retrieve Persistency Service
67  ATH_CHECK( m_pDataLoader.retrieve() );
68 
69  // get properties set
71 
72  // Take care of any pending preLoadProxies requests.
73  for (IProxyRegistry* reg : m_pendingLoad) {
74  ATH_CHECK( doPreLoadProxies (*reg) );
75  }
76  m_pendingLoad.clear();
77 
78  return StatusCode::SUCCESS;
79 }
80 
81 
82 namespace {
83 
84 
86 void setProviderOnList (ProxyProviderSvc::TAdList& tList,
87  IAddressProvider* provider,
88  StoreID::type storeID)
89 {
90  for (SG::TransientAddress* tad : boost::adaptors::reverse (tList)) {
91  if (tad->provider() != nullptr) break;
92  tad->setProvider (provider, storeID);
93  }
94 }
95 
96 
97 } // anonymous namespace
98 
99 
100 StatusCode
102 {
103  if (m_providers.empty()) return StatusCode::SUCCESS;
104 
105  StoreID::type storeID = store.storeID();
106  TAdList tList;
107  for (IAddressProvider* provider : m_providers) {
108  ATH_CHECK( provider->preLoadAddresses(storeID, tList) );
109  setProviderOnList (tList, provider, storeID);
110  }
111  ATH_CHECK( addAddresses (store, tList) );
112  return StatusCode::SUCCESS;
113 }
114 
115 
118 StatusCode
120 {
121  // Due to initialization loops, it's possible for this to be called
122  // before the service is fully initialized. In that case, we may
123  // skip calling some of the providers. So we haven't been fully initialized,
124  // don't do anything now; rather, remember the store, and call
125  // preLoadProxies again for it at the end of initialize().
126  if (FSMState() == Gaudi::StateMachine::OFFLINE) {
127  m_pendingLoad.push_back (&store);
128  return StatusCode::SUCCESS;
129  }
130  return doPreLoadProxies (store);
131 }
132 
133 
136 StatusCode
138 {
139  if (m_providers.empty()) return StatusCode::SUCCESS;
140 
141  StoreID::type storeID = store.storeID();
142  TAdList tList;
143  for (IAddressProvider* provider : m_providers) {
144  ATH_CHECK( provider->loadAddresses(storeID, tList) );
145  setProviderOnList (tList, provider, storeID);
146  }
147  ATH_CHECK( addAddresses (store, tList) );
148  return StatusCode::SUCCESS;
149 }
150 
151 
158  TAdList& tList)
159 {
160  for (SG::TransientAddress* tad : tList) {
161  SG::DataProxy* proxy = store.proxy_exact(tad->clID(), tad->name());
164  if (0 != proxy)
165  {
166  proxy->setAddress(tad->address());
167  if (proxy->provider() == 0) {
168  proxy->setProvider(tad->provider(), store.storeID());
169  }
170  }
171  else {
172  if ( 0 == addAddress(store, std::move(*tad)) ) return StatusCode::FAILURE;
173  }
174  delete tad;
175  }
176 
177  return StatusCode::SUCCESS;
178 }
179 
180 
184  SG::TransientAddress&& tAddr)
185 {
186  //HACK! The proxies for all object those key starts with "HLTAutoKey" will be deleted at the end of each event (resetOnly=false)
187  //hence avoiding the proxy explosion observed with trigger object for releases <= 14.1.0
188  bool resetOnly(tAddr.name().substr(0,10) != std::string("HLTAutoKey"));
189  // std::cout << "PPS:addAdress: proxy for key " << tAddr->name() << " has resetOnly " << resetOnly << std::endl;
190  SG::DataProxy* dp = new SG::DataProxy(std::move(tAddr),
191  m_pDataLoader.get(), true, resetOnly );
192 
193  // Must add the primary CLID first.
194  bool addedProxy = store.addToStore(dp->clID(), dp).isSuccess();
195  // ATH_MSG_VERBOSE("created proxy for " << tAddr->clID() << "/" << tAddr->name() << "using " << m_pDataLoader->repSvcType());
196  if (!addedProxy) {
197  ATH_MSG_ERROR ("Failed to add proxy to store "
198  << dp->clID() << "/" << dp->name());
199  delete dp;
200  dp = nullptr;
201  }
202  else {
203  // loop over all the transient CLIDs:
204  SG::TransientAddress::TransientClidSet tClid = dp->transientID();
205  for (CLID clid : tClid) {
206  if (clid != dp->clID()) {
207  bool flag = (store.addToStore(clid, dp)).isSuccess();
208  if (!flag) {
209  ATH_MSG_ERROR ("Failed to add proxy to store for symlink "
210  << clid << "/" << dp->name());
211  }
212  addedProxy &= flag;
213  }
214  }
215 
216  // loop over all alias'
217  for (const std::string& alias : dp->alias()) {
218  (store.addAlias(alias, dp)).ignore();
219  }
220 
221  // Add any other allowable conversions.
222  const SG::BaseInfoBase* bi = getBaseInfo (dp->clID());
223  if (bi) {
224  for (CLID clid : bi->get_bases()) {
225  if (std::find (tClid.begin(), tClid.end(), clid) == tClid.end()) {
226  store.addToStore (clid, dp).ignore();
227  dp->setTransientID (clid);
228  }
229  }
230 
231  for (CLID clid : bi->get_copy_conversions()) {
232  if (std::find (tClid.begin(), tClid.end(), clid) == tClid.end()) {
233  store.addToStore (clid, dp).ignore();
234  dp->setTransientID (clid);
235  }
236  }
237  }
238  }
239 
240  return dp;
241 }
242 
247 ProxyProviderSvc::retrieveProxy(const CLID& id, const std::string& key,
249 {
250  if ( !m_providers.empty() ) {
251  const EventContext& ctx = contextFromStore (store);
252  SG::TransientAddress pTAd (id, key);
253  pAPiterator iProvider(m_providers.begin()), iEnd(m_providers.end());
254  for (; iProvider != iEnd; ++iProvider) {
255  if ( ((*iProvider)->updateAddress(store.storeID(),&pTAd,ctx)).isSuccess() )
256  {
257  pTAd.setProvider(*iProvider, store.storeID());
258  return this->addAddress(store,std::move(pTAd));
259  }
260  }
261  }
262 
263  return nullptr;
264 }
265 
274 {
276  "EventContext");
277  if (proxy) {
278  EventContext* ctx = SG::DataProxy_cast<EventContext> (proxy);
279  if (ctx) return *ctx;
280  }
281  static const EventContext emptyContext;
282  return emptyContext;
283 }
284 
285 
286 void
287 ProxyProviderSvc::providerNamesPropertyHandler( Gaudi::Details::PropertyBase& /*theProp*/ ) {
288  //add declared providers to the list;
289  std::vector<std::string> providerNames = m_providerNames.value();
290 
291  // FIXME: AddressRemappingSvc needs to come at the end, if it's provided.
292  auto it = std::find (providerNames.begin(), providerNames.end(),
293  "AddressRemappingSvc");
294  if (it != providerNames.end() && it != providerNames.end()-1) {
295  providerNames.erase (it);
296  providerNames.push_back ("AddressRemappingSvc");
297  }
298 
299  for (const std::string& pName : providerNames) {
300  SmartIF<IAddressProvider> pAP{service(pName)};
301  if (!pAP) {
302  ATH_MSG_ERROR(" getting Address Provider "<< pName);
303  throw GaudiException("Failed to locate address provider",
304  "ProxyProviderSvc::providerNamesPropertyHandle",
305  StatusCode::FAILURE);
306  } else {
307  ATH_MSG_DEBUG(" added Address Provider "<< pName);
308  }
310  }
311 
312 }
313 
store
StoreGateSvc * store
Definition: fbtTestBasics.cxx:71
ProxyProviderSvc::pAPiterator
std::list< IAddressProvider * >::iterator pAPiterator
Definition: ProxyProviderSvc.h:44
TileDCSDataPlotter.dp
dp
Definition: TileDCSDataPlotter.py:840
checkxAOD.ds
ds
Definition: Tools/PyUtils/bin/checkxAOD.py:258
ProxyProviderSvc::ProxyProviderSvc
ProxyProviderSvc(const std::string &name, ISvcLocator *svcLoc)
Standard Service Constructor.
Definition: ProxyProviderSvc.cxx:51
StateLessPT_NewConfig.proxy
proxy
Definition: StateLessPT_NewConfig.py:392
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
IProxyRegistry
a proxy registry (a read/write dictionary)
Definition: IProxyRegistry.h:27
ProxyProviderSvc::addProvider
virtual void addProvider(IAddressProvider *aProvider) override final
IAddressProvider manager functionality add a provider to the set of known ones.
Definition: ProxyProviderSvc.h:119
IProxyRegistry.h
initialize
void initialize()
Definition: run_EoverP.cxx:894
ProxyProviderSvc::m_pendingLoad
std::vector< IProxyRegistry * > m_pendingLoad
List of pending stores on which to run preLoadProxies().
Definition: ProxyProviderSvc.h:115
skel.it
it
Definition: skel.GENtoEVGEN.py:396
ProxyProviderSvc::doPreLoadProxies
StatusCode doPreLoadProxies(IProxyRegistry &storeToModify)
Definition: ProxyProviderSvc.cxx:101
SG::TransientAddress
Definition: TransientAddress.h:32
ProxyProviderSvc::m_providerNames
StringArrayProperty m_providerNames
property: the services declared as providers
Definition: ProxyProviderSvc.h:102
SG::TransientAddress::TransientClidSet
std::vector< CLID > TransientClidSet
Strictly a set, but there shouldn't be more than a handful of entries, so store it as a sorted vector...
Definition: TransientAddress.h:38
ProxyProviderSvc::initialize
virtual StatusCode initialize() override
Service boilerplate.
Definition: ProxyProviderSvc.cxx:62
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
ProxyProviderSvc::addAddresses
StatusCode addAddresses(IProxyRegistry &store, TAdList &tList)
Add lists of TADs to the store.
Definition: ProxyProviderSvc.cxx:157
SG::BaseInfoBase::get_bases
const std::vector< CLID > & get_bases() const
Return the class IDs of all known bases of T (that have class IDs).
Definition: BaseInfo.cxx:304
IAddressProvider::loadAddresses
virtual StatusCode loadAddresses(StoreID::type, tadList &)
get all new addresses from Provider for this Event.
Definition: IAddressProvider.h:42
EventContextClid.h
Assign a CLID to EventContext.
ProxyProviderSvc::loadProxies
virtual StatusCode loadProxies(IProxyRegistry &storeToModify) override
add proxies to the store to modify (during Begin Event)
Definition: ProxyProviderSvc.cxx:137
DeMoUpdate.reverse
reverse
Definition: DeMoUpdate.py:563
ProxyProviderSvc::addAddress
SG::DataProxy * addAddress(IProxyRegistry &storeToModify, SG::TransientAddress &&tad)
create a new Proxy, overriding CLID and/or key
Definition: ProxyProviderSvc.cxx:183
ProxyProviderSvc::m_pDataLoader
ServiceHandle< IConversionSvc > m_pDataLoader
Persistency Service.
Definition: ProxyProviderSvc.h:112
DiTauMassTools::ignore
void ignore(T &&)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:58
ProxyProviderSvc.h
manages the address providers and add proxies on demand to the store
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
ProxyProviderSvc::m_providers
std::list< IAddressProvider * > m_providers
the providers we know about. WE DON'T OWN THEM
Definition: ProxyProviderSvc.h:110
BaseInfo.h
Provide an interface for finding inheritance information at run time.
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
COOLRates.alias
alias
Definition: COOLRates.py:1172
master.flag
bool flag
Definition: master.py:29
ClassID_traits
Default, invalid implementation of ClassID_traits.
Definition: Control/AthenaKernel/AthenaKernel/ClassID_traits.h:40
IAddressProvider
interface for IOA providers
Definition: IAddressProvider.h:28
SG::BaseInfoBase::get_copy_conversions
std::vector< CLID > get_copy_conversions() const
Return known copy conversions.
Definition: BaseInfo.cxx:455
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
ProxyProviderSvc::retrieveProxy
virtual SG::DataProxy * retrieveProxy(const CLID &id, const std::string &key, IProxyRegistry &storeToModify) override
Use a provider to create a proxy for ID/KEY.
Definition: ProxyProviderSvc.cxx:247
CLID
uint32_t CLID
The Class ID type.
Definition: Event/xAOD/xAODCore/xAODCore/ClassID_traits.h:47
SG::TransientAddress::setProvider
void setProvider(IAddressProvider *provider, StoreID::type storeID)
Definition: TransientAddress.h:317
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
SG::BaseInfoBase::find
static const BaseInfoBase * find(CLID clid)
Find the BaseInfoBase instance for clid.
Definition: BaseInfo.cxx:569
ProxyProviderSvc::preLoadProxies
virtual StatusCode preLoadProxies(IProxyRegistry &storeToModify) override
IProxyProvider interface.
Definition: ProxyProviderSvc.cxx:119
ProxyProviderSvc::TAdList
std::list< SG::TransientAddress * > TAdList
Definition: ProxyProviderSvc.h:45
StoreID::type
type
Definition: StoreID.h:24
SG::BaseInfoBase
The non-template portion of the BaseInfo implementation.
Definition: Control/AthenaKernel/AthenaKernel/BaseInfo.h:451
ProxyProviderSvc::contextFromStore
const EventContext & contextFromStore(IProxyRegistry &ds) const
Retrieve the EventContext saved in store DS.
Definition: ProxyProviderSvc.cxx:273
IAddressProvider.h
IAddressProvider::preLoadAddresses
virtual StatusCode preLoadAddresses(StoreID::type, tadList &)
get all addresses from Provider : Called before Begin Event
Definition: IAddressProvider.h:36
SG::DataProxy
Definition: DataProxy.h:44
ProxyProviderSvc::~ProxyProviderSvc
virtual ~ProxyProviderSvc()
Definition: ProxyProviderSvc.cxx:59
ProxyProviderSvc::providerNamesPropertyHandler
void providerNamesPropertyHandler(Gaudi::Details::PropertyBase &theProp)
the handler for m_providerNames
Definition: ProxyProviderSvc.cxx:287
ServiceHandle< IClassIDSvc >
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
DataProxy.h