ATLAS Offline Software
Loading...
Searching...
No Matches
StoreGateSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "GaudiKernel/IIncidentSvc.h"
9
12#include "SGTools/DataStore.h"
13
14#include "Gaudi/Interfaces/IOptionsSvc.h"
15#include "GaudiKernel/IAppMgrUI.h"
16#include <fstream>
17#include <algorithm>
18
19using namespace SG;
20using namespace std;
21
22namespace {
23 thread_local HiveEventSlot* currentHiveEventSlot = nullptr;
24 thread_local StoreGateSvc* currentStoreGate = nullptr;
25}
26
28StoreGateSvc::StoreGateSvc(const std::string& name,ISvcLocator* svc) :
29 base_class(name,svc),
30 m_storeID (StoreID::findStoreID(name))
31{
32}
33
37
38void
42
43void
45 currentHiveEventSlot=pSlot;
46 if ( 0 != currentHiveEventSlot) {
47 currentHiveEventSlot->pEvtStore->makeCurrent();
48 }
49}
50
52 if (!::currentStoreGate) {
53 // this is a static function so we don't have many conveniences
54 ISvcLocator *svcLocator = Gaudi::svcLocator();
55 SmartIF<StoreGateSvc> sg{svcLocator->service("StoreGateSvc/StoreGateSvc")};
56 if ( !sg.isValid() ) {
57 throw GaudiException(
58 "Could not get \"StoreGateSvc\" to initialize currentStoreGate",
59 "StoreGateSvc", StatusCode::FAILURE);
60 }
61 sg->makeCurrent();
62 return sg;
63 }
64 return ::currentStoreGate;
65}
66
69 return currentHiveEventSlot;
70}
71
73
74
75void
79
81StatusCode
82StoreGateSvc::recordAddress(const std::string& skey,
84 bool clearAddressFlag,
85 const std::vector<CLID>& bases)
86{
87 _SGXCALL(recordAddress, (skey, std::move(pAddress), clearAddressFlag, bases), StatusCode::FAILURE);
88}
89
90StatusCode
92 bool clearAddressFlag,
93 const std::vector<CLID>& bases)
94{
95 _SGXCALL(recordAddress, (std::move(pAddress), clearAddressFlag, bases), StatusCode::FAILURE);
96}
97
98
99StatusCode
100StoreGateSvc::setConst(const void* pObject) {
101 _SGXCALL(setConst, (pObject), StatusCode::FAILURE);
102}
103
104
108
109 // Initialize service:
110 CHECK( Service::initialize() );
111
112 verbose() << "Initializing " << name() << endmsg;
113
114 SmartIF<Gaudi::Interfaces::IOptionsSvc> pJOSvc{serviceLocator()->service("JobOptionsSvc")};
115 if ( !pJOSvc.isValid() ) {
116 error() << "Failed to retrieve JobOptionsSvc" << endmsg;
117 }
118 //copy our properties to the prototype (default) SGImplSvc
119 const std::string implStoreName = name() + "_Impl";
120 for (const Gaudi::Details::PropertyBase* p : getProperties()) {
121 pJOSvc->set( implStoreName + "." + p->name(), p->toString() );
122 }
123
124 //HACK ALERT: using createService rather then the customary service(...,CREATEIF=true) we set our pointer
125 // to SGImplSvc early (even before it is initialized). This should help take care of some initialize loops
126 // for example when we try to record an address from one of the address providers initialize methods
127
128 std::string implStoreFullName = "SGImplSvc/" + implStoreName;
129 debug() << "trying to create store " << implStoreFullName << endmsg;
130
131 m_defaultStore = serviceLocator().as<ISvcManager>()->createService(implStoreFullName);
132
133 if (!m_defaultStore) {
134 error() << "Could not create store " << implStoreFullName << endmsg;
135 return StatusCode::FAILURE;
136 }
137
138 if ( m_defaultStore->sysInitialize().isSuccess() ) {
139 // If this is the default event store (StoreGateSvc), then declare
140 // our arena as the default for memory allocations.
141 if (name() == "StoreGateSvc") {
142 m_defaultStore->makeCurrent();
143 }
144 } else {
145 error() << "Could not initialize default store " << implStoreFullName
146 << endmsg;
147 return StatusCode::FAILURE;
148 }
149 if ( !m_incSvc.retrieve().isSuccess() ) {
150 error() << "Could not locate IncidentSvc" << endmsg;
151 return StatusCode::FAILURE;
152 }
153
154 // Don't retrieve m_activeStoreSvc here to prevent a possible
155 // initialization loop.
156
157 if (m_DumpStore) {
158 const int PRIORITY=100;
159 m_incSvc->addListener(this, "EndEvent",PRIORITY);
160 }
161
162 return StatusCode::SUCCESS;
163}
164
166StatusCode StoreGateSvc::stop() {
167 verbose() << "Stop " << name() << endmsg;
168 //HACK ALERT: ID event store objects refer to det store objects
169 //by setting an ad-hoc priority for event store(s) we make sure they are finalized and hence cleared first
170 // see e.g. https://savannah.cern.ch/bugs/index.php?99993
171 if (m_defaultStore->store()->storeID() == StoreID::EVENT_STORE) {
172 auto pISM = serviceLocator().as<ISvcManager>();
173 pISM->setPriority(name(), pISM->getPriority(name())+1).ignore();
174 verbose() << "stop: setting service priority to " << pISM->getPriority(name())
175 << " so that event stores get finalized and cleared before other stores" <<endmsg;
176 }
177 return StatusCode::SUCCESS;
178}
179
180void StoreGateSvc::handle(const Incident &inc) {
181 currentStore()->handle(inc);
182}
183
185
186StatusCode
188 CHECK( Service::finalize() );
189 verbose() << "Finalizing " << name() << endmsg;
190 if (m_defaultStore) {
191 // m_defaultStore is not active, so ServiceManager won't finalize it!
192 CHECK( m_defaultStore->finalize());
193 }
194
195 printBadList (m_badRetrieves, "retrieve()");
196 printBadList (m_badRecords, "record()");
197 return StatusCode::SUCCESS;
198}
199
200
202DataProxy*
203StoreGateSvc::proxy(const void* const pTransient) const {
204 _SGXCALL(proxy, (pTransient), 0);
205}
206
208DataProxy*
209StoreGateSvc::proxy(const CLID& id) const {
210 _SGXCALL(proxy, (id), 0);
211}
212
214DataProxy*
215StoreGateSvc::proxy(const CLID& id, const std::string& key) const {
216 _SGXCALL(proxy, (id, key), 0);
217}
218
219
223StoreGateSvc::proxy(const CLID& id, bool checkValid) const {
224 _SGXCALL(proxy, (id, checkValid), 0);
225}
226
230StoreGateSvc::proxy(const CLID& id, const std::string& key, bool checkValid) const {
231 _SGXCALL(proxy, (id, key, checkValid), 0);
232}
233
234
241{
242 _SGXCALL(addToStore, (id, proxy), StatusCode::FAILURE);
243}
244
245
268 const std::string& key,
269 bool allowMods,
270 bool returnExisting)
271{
272 _SGXCALL(recordObject, (std::move(obj), key, allowMods, returnExisting), nullptr);
273}
274
275
277vector<const SG::DataProxy*>
279 vector<const SG::DataProxy*> nullV;
280 _SGXCALL(proxies, (), nullV);
281}
282
284vector<CLID>
286{
287 vector<CLID> nullV;
288 _SGXCALL(clids, (), nullV);
289}
290
294StoreGateSvc::transientProxy(const CLID& id, const std::string& key) const {
295 _SGXCALL(transientProxy, (id, key), 0);
296}
297
298
300DataObject*
302 _SGXCALL(accessData, (id), 0);
303}
304
306DataObject*
307StoreGateSvc::accessData(const CLID& id, const std::string& key) const {
308 _SGXCALL(accessData, (id, key), 0);
309}
310
311bool
313 const std::string& keyA, const std::string& keyB ) {
314 _SGXCALL(transientSwap, (id, keyA, keyB), false);
315}
316
319StatusCode
320StoreGateSvc::typeless_record( DataObject* obj, const std::string& key,
321 const void* const raw_ptr,
322 bool allowMods, bool resetOnly,
323 bool noHist ) {
324 _SGXCALL(typeless_record, (obj, key, raw_ptr, allowMods, resetOnly, noHist), StatusCode::FAILURE);
325}
326
327StatusCode
329 DataObject* obj, const std::string& key,
330 const void* const raw_ptr,
331 bool allowMods,
332 bool noHist,
333 const std::type_info* tinfo) {
334 _SGXCALL(typeless_overwrite, (id, obj, key, raw_ptr, allowMods, noHist, tinfo), StatusCode::FAILURE);
335}
336
338void
340{
341 m_storeID = id;
342 // FIXME: should broadcast this to all instances.
343 _SGVOIDCALL(setStoreID,(id));
344}
345
346void
347StoreGateSvc::keys(const CLID& id, std::vector<std::string>& vkeys,
348 bool includeAlias, bool onlyValid) const
349{
350 _SGVOIDCALL(keys,(id, vkeys, includeAlias, onlyValid));
351}
352
353
354
355std::string
357 std::string nullS = "\n>>>>>>>NO CURRENT STORE<<<<<<<\n";
358 _SGXCALL(dump, (), nullS);
359}
360
361int
363 _SGXCALL(typeCount, (clid), -1);
364}
365
366
367
368typename StoreGateSvc::sgkey_t
369StoreGateSvc::stringToKey (const std::string& str, CLID clid) {
370 _SGXCALL( stringToKey, (str, clid), 0 );
371}
372
373const std::string*
375 _SGXCALL( keyToString, (key), 0 );
376}
377
378const std::string*
380 _SGXCALL( keyToString, (key, clid), 0 );
381}
382
383void
385 const std::string& str,
386 CLID clidid) {
387 _SGVOIDCALL( registerKey, (key, str, clidid) );
388}
389void
391 sgkey_t target,
392 off_t index_offset) {
393 _SGVOIDCALL( remap_impl, (source, target, index_offset) );
394}
395
396bool
397StoreGateSvc::tryELRemap (sgkey_t sgkey_in, size_t index_in,
398 sgkey_t& sgkey_out, size_t& index_out) {
399 _SGXCALL( tryELRemap, (sgkey_in, index_in, sgkey_out, index_out), false );
400}
401
402StatusCode
405 SG::ConstProxyIterator& end) const {
406 _SGXCALL( proxyRange, (id, beg, end), StatusCode::FAILURE );
407}
408
409
410void
411StoreGateSvc::releaseObject(const CLID& id, const std::string& key) {
412 _SGVOIDCALL( releaseObject, (id, key) );
413}
414
415void
419
420
421StatusCode
423 this->makeCurrent();
424 _SGXCALL(loadEventProxies, (), StatusCode::FAILURE);
425}
426
428// clear store
429StatusCode
431{
432 StatusCode sc = currentStore()->clearStore(forceRemove);
433
434 // See if we want to send a ClearStore incident.
435 // If m_pruneIncidents is true then we check the first time
436 // to see if there are any listeners. If not, then we avoid
437 // sending these incidents for the rest of the job.
438 if (m_pruneIncidents) {
439 if (m_listenerState == UNCHECKED) {
440 std::vector<IIncidentListener*> l;
441 m_incSvc->getListeners (l, "StoreCleared");
443 }
445 return sc;
446 }
447 }
448
449 // Send a notification that the store was cleared.
450 if (sc.isSuccess()) {
451 m_incSvc->fireIncident(StoreClearedIncident (this, name()));
452 }
453 return sc;
454}
455
456void
458 _SGVOIDCALL( emptyTrash, () );
459}
460
465 ::currentStoreGate = this;
466 _SGVOIDCALL (makeCurrent, ());
467}
468
469StatusCode StoreGateSvc::removeProxy(SG::DataProxy* proxy, const void* pTrans,
470 bool forceRemove) {
471 _SGXCALL(removeProxy, (proxy, pTrans, forceRemove), StatusCode::FAILURE);
472}
473
474
485StatusCode
486StoreGateSvc::createObj (IConverter* cvt,
487 IOpaqueAddress* addr,
488 DataObject*& refpObject)
489{
490 _SGXCALL( createObj, (cvt, addr, refpObject), StatusCode::FAILURE );
491}
492
493
501 CLID clid, const std::string& key) const
502{
503 if (m_storeID == StoreID::EVENT_STORE && currentHiveEventSlot != nullptr) {
505 std::string algo;
506 if (m_algContextSvc.isValid()) {
507 if (IAlgorithm* alg = m_algContextSvc->currentAlg()) {
508 if (alg->type() == "AthenaOutputStream") return;
509 if (alg->type() == "AthIncFirerAlg") return;
510 algo = alg->type() + "/" + alg->name();
511 bad.insert (BadListItem (clid, key, algo));
512 }
513 }
514 }
515}
516
517
524 const std::string& what) const
525{
526 if (bad.empty()) return;
527 std::vector<std::string> lines;
528 for (const BadListItem& id : bad) {
529 lines.push_back (id.fullKey() + " [" + id.m_algo + "]");
530 }
531 std::sort (lines.begin(), lines.end());
532 warning() << "Called " << what << " on these objects in a MT store" << endmsg;
533 for (const std::string& s : lines) {
534 warning() << s << endmsg;
535 }
536}
537
538
540{
541 std::cout << sg->dump() << "\n";
542}
543
544void SG_dump (StoreGateSvc* sg, const char* fname)
545{
546 std::ofstream f (fname);
547 f << sg->dump() << "\n";
548 f.close();
549}
550
#define endmsg
Proxy for a group of Arenas. See Arena.h for an overview of the arena-based memory allocators.
Helpers for checking error return status codes and reporting errors.
#define CHECK(...)
Evaluate an expression and check for errors.
uint32_t CLID
The Class ID type.
static Double_t sc
const bool debug
Incident sent after a store is cleared.
void SG_dump(StoreGateSvc *sg)
These are intended to be easy to call from the debugger.
Simple smart pointer for Gaudi-style refcounted objects.
The Athena Transient Store API.
Definition SGImplSvc.h:109
virtual void handle(const Incident &) override final
triggered by Incident service
virtual StatusCode clearStore(bool forceRemove=false) override final
clear DataStore contents: called by the event loop mgrs
Incident sent after a store is cleared.
The Athena Transient Store API.
virtual SG::DataProxy * recordObject(SG::DataObjectSharedPtr< DataObject > obj, const std::string &key, bool allowMods, bool returnExisting) override final
Record an object in the store.
virtual StatusCode finalize() override
static SG::HiveEventSlot * currentSlot()
std::string dump() const
dump objects in store.
virtual StatusCode createObj(IConverter *cvt, IOpaqueAddress *addr, DataObject *&refpObject) override
Call converter to create an object, with locking.
virtual void handle(const Incident &) override final
virtual void registerKey(sgkey_t key, const std::string &str, CLID clidid) override final
Remember an additional mapping from key to string/CLID.
DataObject * accessData(const CLID &id) const
find proxy and access its data. Returns 0 to flag failure
StoreGateSvc(const std::string &name, ISvcLocator *svc)
Standard Constructor.
SmartIF< SGImplSvc > m_defaultStore
StatusCode loadEventProxies()
load proxies at begin event
Gaudi::Property< bool > m_pruneIncidents
StatusCode proxyRange(const CLID &id, SG::ConstProxyIterator &beg, SG::ConstProxyIterator &end) const
return a range to all proxies of a given CLID
void remap_impl(sgkey_t source, sgkey_t target, off_t index_offset)
Declare a remapping.
void rememberBad(BadItemList &bad, CLID clid, const std::string &key) const
Remember that retrieve or record was called for a MT store.
static StoreGateSvc * currentStoreGate()
get current StoreGate
std::lock_guard< mutex_t > lock_t
virtual ~StoreGateSvc() override
Standard Destructor.
SG::DataProxy * transientProxy(const CLID &id, const std::string &key) const
get proxy with given id and key.
void clearProxyPayload(SG::DataProxy *)
use to reset a proxy (clearing the data object it contains) Unlike DataProxy::reset this method corre...
Gaudi::Property< bool > m_DumpStore
void setStoreID(StoreID::type id)
set store ID. request forwarded to DataStore:
std::unordered_set< BadListItem, DataObjID_Hasher > BadItemList
IStringPool::sgkey_t sgkey_t
int typeCount() const
Return the number of instances of an object of type T int i = p_store->typeCount<T>(); Note that th...
virtual StatusCode addToStore(CLID id, SG::DataProxy *proxy) override final
Raw addition of a proxy to the store.
CLID clid(const TKEY &key) const
Retrieve the main CLID of the object recorded in StoreGate with the given "key" WARNING: slow!
virtual bool tryELRemap(sgkey_t sgkey_in, size_t index_in, sgkey_t &sgkey_out, size_t &index_out) override final
Test to see if the target of an ElementLink has moved.
StoreID::type m_storeID
Cache store type in the facade class.
virtual void commitNewDataObjects() override final
Reset handles added since the last call to commit.
void makeCurrent()
The current store is becoming the active store.
SGImplSvc * currentStore() const
returns pointer to the current SGImplSvc
void emptyTrash()
throw away bad objects
virtual StatusCode initialize() override
Service initialization.
std::vector< CLID > clids(const TKEY &key) const
Retrieve all the CLID s (including symlinks) of the object recorded in StoreGate with the given "key"...
virtual StatusCode clearStore(bool forceRemove=false) override final
clear DataStore contents: called by the event loop mgrs
void printBadList(const BadItemList &bad, const std::string &what) const
Print out a list of bad calls during finalization.
StatusCode typeless_record(DataObject *obj, const std::string &key, const void *const raw_ptr, bool allowMods, bool resetOnly=true, bool noHist=false)
type-less recording of an object with a key, allow possibility of specifying const-access and history...
ServiceHandle< IAlgContextSvc > m_algContextSvc
StatusCode recordAddress(const std::string &skey, CxxUtils::RefCountedPtr< IOpaqueAddress > pAddress, bool clearAddressFlag=true, const std::vector< CLID > &bases={})
Create a proxy object using an IOpaqueAddress and a transient key.
virtual const std::string * keyToString(sgkey_t key) const override final
Find the string corresponding to a given key.
std::atomic< ListenerState > m_listenerState
bool transientSwap(const CLID &id, const std::string &keyA, const std::string &keyB)
swap the content of 2 keys payload A indexed by keyA will now be accessed via keyB and vice versa Not...
virtual sgkey_t stringToKey(const std::string &str, CLID clid) override final
Find the key for a string/CLID pair.
virtual StatusCode stop() override
Service start.
std::vector< CLID > clids() const
Return all CLIDs in the store.
virtual std::vector< const SG::DataProxy * > proxies() const override final
return the list of all current proxies in store
mutex_t m_badMutex
virtual SG::DataProxy * proxy(const void *const pTransient) const override final
get proxy for a given data object address in memory
StatusCode setConst(const void *pointer)
prevent downstream clients from modifying the pointed-at dobj
void keys(std::vector< std::string > &vkeys, bool includeAlias=false, bool onlyValid=true) const
provide list of all StoreGate keys associated with an object.
StatusCode typeless_overwrite(const CLID &id, DataObject *obj, const std::string &key, const void *const raw_ptr, bool allowMods, bool noHist=false, const std::type_info *tinfo=0)
same as typeless_record, allows to overwrite an object in memory or on disk
void releaseObject(const CLID &id, const std::string &key)
release object held by proxy, if any.
ServiceHandle< IIncidentSvc > m_incSvc
StatusCode removeProxy(SG::DataProxy *proxy, const void *pTrans, bool forceRemove=false)
remove proxy from store, unless it is reset only.
static void setSlot(SG::HiveEventSlot *pSlot)
set the hive event slot pointer: used by the event loop mgrs
void setDefaultStore(SGImplSvc *pStore)
set pointer to default event store: used by ActiveStoreSvc
defines an enum used by address providers to decide what kind of StoreGateSvc they are providing addr...
Definition StoreID.h:18
@ EVENT_STORE
Definition StoreID.h:26
bool verbose
Definition hcg.cxx:75
Forward declaration.
CxxUtils::RefCountedPtr< T > DataObjectSharedPtr
ProxyMap::const_iterator ConstProxyIterator
Definition ProxyMap.h:24
virtual void lock() override
Lock the container.
-event-from-file
STL namespace.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.