ATLAS Offline Software
Loading...
Searching...
No Matches
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"
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 <ranges>
25#include "TClass.h"
26
27using namespace std;
28
29
30namespace {
31
32
33const SG::BaseInfoBase* getBaseInfo (CLID clid)
34{
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
52ProxyProviderSvc::ProxyProviderSvc(const std::string& name,
53 ISvcLocator* svcLoc):
54 base_class(name, svcLoc),
55 m_pDataLoader("EventPersistencySvc", name)
56{
58}
59
61
62StatusCode
64{
65 ATH_MSG_VERBOSE( "Initializing " << name() );
66
67 // retrieve Persistency Service
68 ATH_CHECK( m_pDataLoader.retrieve() );
69
70 // get properties set
71 ATH_CHECK( AthService::initialize() );
72
73 // Take care of any pending preLoadProxies requests.
74 for (IProxyRegistry* reg : m_pendingLoad) {
76 }
77 m_pendingLoad.clear();
78
79 return StatusCode::SUCCESS;
80}
81
82
83namespace {
84
85
87void setProviderOnList (ProxyProviderSvc::TAdList& tList,
88 IAddressProvider* provider,
89 StoreID::type storeID)
90{
91 for (SG::TransientAddress* tad : std::views::reverse (tList)) {
92 if (tad->provider() != nullptr) break;
93 tad->setProvider (provider, storeID);
94 }
95}
96
97
98} // anonymous namespace
99
100
101StatusCode
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
119StatusCode
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
137StatusCode
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
249ProxyProviderSvc::retrieveProxy(const CLID& id, const std::string& key,
250 IProxyRegistry& store)
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
288void
289ProxyProviderSvc::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
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
Provide an interface for finding inheritance information at run time.
Assign a CLID to EventContext.
uint32_t CLID
The Class ID type.
manages the address providers and add proxies on demand to the store
interface for IOA providers
virtual StatusCode loadAddresses(StoreID::type, tadList &)
get all new addresses from Provider for this Event.
virtual StatusCode preLoadAddresses(StoreID::type, tadList &)
get all addresses from Provider : Called before Begin Event
a proxy registry (a read/write dictionary)
ServiceHandle< IConversionSvc > m_pDataLoader
Persistency Service.
StatusCode doPreLoadProxies(IProxyRegistry &storeToModify)
StringArrayProperty m_providerNames
property: the services declared as providers
virtual SG::DataProxy * retrieveProxy(const CLID &id, const std::string &key, IProxyRegistry &storeToModify) override
Use a provider to create a proxy for ID/KEY.
std::list< IAddressProvider * > m_providers
the providers we know about. WE DON'T OWN THEM
virtual StatusCode loadProxies(IProxyRegistry &storeToModify) override
add proxies to the store to modify (during Begin Event)
virtual StatusCode initialize() override
Service boilerplate.
std::vector< IProxyRegistry * > m_pendingLoad
List of pending stores on which to run preLoadProxies().
ProxyProviderSvc(const std::string &name, ISvcLocator *svcLoc)
Standard Service Constructor.
const EventContext & contextFromStore(IProxyRegistry &ds) const
Retrieve the EventContext saved in store DS.
std::list< IAddressProvider * >::iterator pAPiterator
StatusCode addAddresses(IProxyRegistry &store, TAdList &tList)
Add lists of TADs to the store.
virtual StatusCode preLoadProxies(IProxyRegistry &storeToModify) override
IProxyProvider interface.
std::list< SG::TransientAddress * > TAdList
virtual void addProvider(IAddressProvider *aProvider) override final
IAddressProvider manager functionality add a provider to the set of known ones.
void providerNamesPropertyHandler(Gaudi::Details::PropertyBase &theProp)
the handler for m_providerNames
SG::DataProxy * addAddress(IProxyRegistry &storeToModify, SG::TransientAddress &&tad)
create a new Proxy, overriding CLID and/or key
virtual SG::DataProxy * proxy_exact(SG::sgkey_t sgkey) const override
virtual StatusCode addToStore(CLID, SG::DataProxy *proxy) override
The non-template portion of the BaseInfo implementation.
static const BaseInfoBase * find(CLID clid)
Find the BaseInfoBase instance for clid.
Definition BaseInfo.cxx:570
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
std::vector< CLID > get_copy_conversions() const
Return known copy conversions.
Definition BaseInfo.cxx:455
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...
void setProvider(IAddressProvider *provider, StoreID::type storeID)
DATA * DataProxy_cast(DataProxy *proxy)
cast the proxy into the concrete data object it proxies
uint32_t sgkey_t
Type used for hashed StoreGate key+CLID pairs.
Definition sgkey_t.h:32
STL namespace.