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"
10 #include "SGTools/DataStore.h"
14 #include "AthenaKernel/BaseInfo.h"
15 
16 #include "GaudiKernel/IClassIDSvc.h"
17 #include "GaudiKernel/IConversionSvc.h"
18 #include "GaudiKernel/TypeNameString.h"
19 #include "GaudiKernel/GaudiException.h"
20 #include "GaudiKernel/ServiceHandle.h"
21 
22 #include "ProxyProviderSvc.h"
23 
24 #include "boost/range/adaptor/reversed.hpp"
25 #include "TClass.h"
26 
27 using namespace std;
28 
29 
30 namespace {
31 
32 
33 const SG::BaseInfoBase* getBaseInfo (CLID clid)
34 {
35  const SG::BaseInfoBase* bi = SG::BaseInfoBase::find (clid);
36  if (bi) return bi;
37 
38  // Try to force a dictionary load to get it defined.
39  ServiceHandle<IClassIDSvc> clidsvc ("ClassIDSvc", "ProxyProviderSvc");
40  if (!clidsvc.retrieve()) return nullptr;
41  std::string name;
42  if (!clidsvc->getTypeNameOfID (clid, name).isSuccess()) {
43  return nullptr;
44  }
45  (void)TClass::GetClass (name.c_str());
46  return SG::BaseInfoBase::find (clid);
47 }
48 
49 
50 } // anonyous namespace
51 
53  ISvcLocator* svcLoc):
54  base_class(name, svcLoc),
55  m_pDataLoader("EventPersistencySvc", name)
56 {
58 }
59 
61 
64 {
65  ATH_MSG_VERBOSE( "Initializing " << name() );
66 
67  // retrieve Persistency Service
68  ATH_CHECK( m_pDataLoader.retrieve() );
69 
70  // get properties set
72 
73  // Take care of any pending preLoadProxies requests.
74  for (IProxyRegistry* reg : m_pendingLoad) {
75  ATH_CHECK( doPreLoadProxies (*reg) );
76  }
77  m_pendingLoad.clear();
78 
79  return StatusCode::SUCCESS;
80 }
81 
82 
83 namespace {
84 
85 
87 void setProviderOnList (ProxyProviderSvc::TAdList& tList,
88  IAddressProvider* provider,
89  StoreID::type storeID)
90 {
91  for (SG::TransientAddress* tad : boost::adaptors::reverse (tList)) {
92  if (tad->provider() != nullptr) break;
93  tad->setProvider (provider, storeID);
94  }
95 }
96 
97 
98 } // anonymous namespace
99 
100 
101 StatusCode
103 {
104  if (m_providers.empty()) return StatusCode::SUCCESS;
105 
106  StoreID::type storeID = store.storeID();
107  TAdList tList;
108  for (IAddressProvider* provider : m_providers) {
109  ATH_CHECK( provider->preLoadAddresses(storeID, tList) );
110  setProviderOnList (tList, provider, storeID);
111  }
112  ATH_CHECK( addAddresses (store, tList) );
113  return StatusCode::SUCCESS;
114 }
115 
116 
119 StatusCode
121 {
122  // Due to initialization loops, it's possible for this to be called
123  // before the service is fully initialized. In that case, we may
124  // skip calling some of the providers. So we haven't been fully initialized,
125  // don't do anything now; rather, remember the store, and call
126  // preLoadProxies again for it at the end of initialize().
127  if (FSMState() == Gaudi::StateMachine::OFFLINE) {
128  m_pendingLoad.push_back (&store);
129  return StatusCode::SUCCESS;
130  }
131  return doPreLoadProxies (store);
132 }
133 
134 
137 StatusCode
139 {
140  if (m_providers.empty()) return StatusCode::SUCCESS;
141 
142  StoreID::type storeID = store.storeID();
143  TAdList tList;
144  for (IAddressProvider* provider : m_providers) {
145  ATH_CHECK( provider->loadAddresses(storeID, tList) );
146  setProviderOnList (tList, provider, storeID);
147  }
148  ATH_CHECK( addAddresses (store, tList) );
149  return StatusCode::SUCCESS;
150 }
151 
152 
159  TAdList& tList)
160 {
161  for (SG::TransientAddress* tad : tList) {
162  SG::sgkey_t sgkey = tad->sgkey();
163  SG::DataProxy* proxy = sgkey ? store.proxy_exact(tad->sgkey()) : store.proxy_exact(tad->clID(), tad->name());
166  if (0 != proxy)
167  {
168  proxy->setAddress(tad->address());
169  if (proxy->provider() == 0) {
170  proxy->setProvider(tad->provider(), store.storeID());
171  }
172  }
173  else {
174  if ( 0 == addAddress(store, std::move(*tad)) ) return StatusCode::FAILURE;
175  }
176  delete tad;
177  }
178 
179  return StatusCode::SUCCESS;
180 }
181 
182 
186  SG::TransientAddress&& tAddr)
187 {
188  //HACK! The proxies for all object those key starts with "HLTAutoKey" will be deleted at the end of each event (resetOnly=false)
189  //hence avoiding the proxy explosion observed with trigger object for releases <= 14.1.0
190  bool resetOnly(tAddr.name().substr(0,10) != std::string("HLTAutoKey"));
191  // std::cout << "PPS:addAdress: proxy for key " << tAddr->name() << " has resetOnly " << resetOnly << std::endl;
192  SG::DataProxy* dp = new SG::DataProxy(std::move(tAddr),
193  m_pDataLoader.get(), true, resetOnly );
194 
195  // Must add the primary CLID first.
196  bool addedProxy = store.addToStore(dp->clID(), dp).isSuccess();
197  // ATH_MSG_VERBOSE("created proxy for " << tAddr->clID() << "/" << tAddr->name() << "using " << m_pDataLoader->repSvcType());
198  if (!addedProxy) {
199  ATH_MSG_ERROR ("Failed to add proxy to store "
200  << dp->clID() << "/" << dp->name());
201  delete dp;
202  dp = nullptr;
203  }
204  else {
205  // loop over all the transient CLIDs:
206  SG::TransientAddress::TransientClidSet tClid = dp->transientID();
207  for (CLID clid : tClid) {
208  if (clid != dp->clID()) {
209  bool flag = (store.addToStore(clid, dp)).isSuccess();
210  if (!flag) {
211  ATH_MSG_ERROR ("Failed to add proxy to store for symlink "
212  << clid << "/" << dp->name());
213  }
214  addedProxy &= flag;
215  }
216  }
217 
218  // loop over all alias'
219  for (const std::string& alias : dp->alias()) {
220  (store.addAlias(alias, dp)).ignore();
221  }
222 
223  // Add any other allowable conversions.
224  const SG::BaseInfoBase* bi = getBaseInfo (dp->clID());
225  if (bi) {
226  for (CLID clid : bi->get_bases()) {
227  if (std::find (tClid.begin(), tClid.end(), clid) == tClid.end()) {
228  store.addToStore (clid, dp).ignore();
229  dp->setTransientID (clid);
230  }
231  }
232 
233  for (CLID clid : bi->get_copy_conversions()) {
234  if (std::find (tClid.begin(), tClid.end(), clid) == tClid.end()) {
235  store.addToStore (clid, dp).ignore();
236  dp->setTransientID (clid);
237  }
238  }
239  }
240  }
241 
242  return dp;
243 }
244 
249 ProxyProviderSvc::retrieveProxy(const CLID& id, const std::string& key,
251 {
252  if ( !m_providers.empty() ) {
253  const EventContext& ctx = contextFromStore (store);
254  SG::TransientAddress pTAd (id, key);
255  pAPiterator iProvider(m_providers.begin()), iEnd(m_providers.end());
256  for (; iProvider != iEnd; ++iProvider) {
257  if ( ((*iProvider)->updateAddress(store.storeID(),&pTAd,ctx)).isSuccess() )
258  {
259  pTAd.setProvider(*iProvider, store.storeID());
260  return this->addAddress(store,std::move(pTAd));
261  }
262  }
263  }
264 
265  return nullptr;
266 }
267 
276 {
278  "EventContext");
279  if (proxy) {
280  EventContext* ctx = SG::DataProxy_cast<EventContext> (proxy);
281  if (ctx) return *ctx;
282  }
283  static const EventContext emptyContext;
284  return emptyContext;
285 }
286 
287 
288 void
289 ProxyProviderSvc::providerNamesPropertyHandler( Gaudi::Details::PropertyBase& /*theProp*/ ) {
290  //add declared providers to the list;
291  std::vector<std::string> providerNames = m_providerNames.value();
292 
293  // FIXME: AddressRemappingSvc needs to come at the end, if it's provided.
294  auto it = std::find (providerNames.begin(), providerNames.end(),
295  "AddressRemappingSvc");
296  if (it != providerNames.end() && it != providerNames.end()-1) {
297  providerNames.erase (it);
298  providerNames.push_back ("AddressRemappingSvc");
299  }
300 
301  for (const std::string& pName : providerNames) {
302  SmartIF<IAddressProvider> pAP{service(pName)};
303  if (!pAP) {
304  ATH_MSG_ERROR(" getting Address Provider "<< pName);
305  throw GaudiException("Failed to locate address provider",
306  "ProxyProviderSvc::providerNamesPropertyHandle",
307  StatusCode::FAILURE);
308  } else {
309  ATH_MSG_DEBUG(" added Address Provider "<< pName);
310  }
312  }
313 
314 }
315 
SGTest::store
TestStore store
Definition: TestStore.cxx:23
common.sgkey
def sgkey(tool)
Definition: common.py:1027
ProxyProviderSvc::pAPiterator
std::list< IAddressProvider * >::iterator pAPiterator
Definition: ProxyProviderSvc.h:44
TileDCSDataPlotter.dp
dp
Definition: TileDCSDataPlotter.py:842
checkxAOD.ds
ds
Definition: Tools/PyUtils/bin/checkxAOD.py:260
ProxyProviderSvc::ProxyProviderSvc
ProxyProviderSvc(const std::string &name, ISvcLocator *svcLoc)
Standard Service Constructor.
Definition: ProxyProviderSvc.cxx:52
StateLessPT_NewConfig.proxy
proxy
Definition: StateLessPT_NewConfig.py:407
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
DataStore.h
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:407
ProxyProviderSvc::doPreLoadProxies
StatusCode doPreLoadProxies(IProxyRegistry &storeToModify)
Definition: ProxyProviderSvc.cxx:102
SG::TransientAddress
Definition: TransientAddress.h:32
SGTest::TestStore::proxy_exact
virtual SG::DataProxy * proxy_exact(SG::sgkey_t sgkey) const override
Definition: TestStore.cxx:140
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:63
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:158
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:138
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:185
SGTest::TestStore::addToStore
virtual StatusCode addToStore(CLID, SG::DataProxy *proxy) override
Definition: TestStore.cxx:176
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:37
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:249
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:340
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
SG::BaseInfoBase::find
static const BaseInfoBase * find(CLID clid)
Find the BaseInfoBase instance for clid.
Definition: BaseInfo.cxx:570
SG::sgkey_t
uint32_t sgkey_t
Type used for hashed StoreGate key+CLID pairs.
Definition: CxxUtils/CxxUtils/sgkey_t.h:32
ProxyProviderSvc::preLoadProxies
virtual StatusCode preLoadProxies(IProxyRegistry &storeToModify) override
IProxyProvider interface.
Definition: ProxyProviderSvc.cxx:120
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:275
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:45
ProxyProviderSvc::~ProxyProviderSvc
virtual ~ProxyProviderSvc()
Definition: ProxyProviderSvc.cxx:60
ProxyProviderSvc::providerNamesPropertyHandler
void providerNamesPropertyHandler(Gaudi::Details::PropertyBase &theProp)
the handler for m_providerNames
Definition: ProxyProviderSvc.cxx:289
ServiceHandle< IClassIDSvc >
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
DataProxy.h