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 <print>
18#include <algorithm>
19
20using namespace SG;
21using namespace std;
22
23namespace {
24 thread_local HiveEventSlot* currentHiveEventSlot = nullptr;
25 thread_local StoreGateSvc* currentStoreGate = nullptr;
26}
27
29StoreGateSvc::StoreGateSvc(const std::string& name,ISvcLocator* svc) :
30 base_class(name,svc),
31 m_storeID (StoreID::findStoreID(name))
32{
33}
34
38
40StatusCode
43 SG::TypelessIterator& end) const {
44 if (m_storeID == StoreID::EVENT_STORE && currentSlot() != nullptr) {
45 rememberBadRetrieve (id, "(iterator)");
46 }
47 _SGXCALL(retrieve, (id, begin, end), StatusCode::FAILURE);
48}
49
50void
54
55void
57 currentHiveEventSlot=pSlot;
58 if ( 0 != currentHiveEventSlot) {
59 currentHiveEventSlot->pEvtStore->makeCurrent();
60 }
61}
62
64 if (!::currentStoreGate) {
65 // this is a static function so we don't have many conveniences
66 ISvcLocator *svcLocator = Gaudi::svcLocator();
67 SmartIF<StoreGateSvc> sg{svcLocator->service("StoreGateSvc/StoreGateSvc")};
68 if ( !sg.isValid() ) {
69 throw GaudiException(
70 "Could not get \"StoreGateSvc\" to initialize currentStoreGate",
71 "StoreGateSvc", StatusCode::FAILURE);
72 }
73 sg->makeCurrent();
74 return sg;
75 }
76 return ::currentStoreGate;
77}
78
81 return currentHiveEventSlot;
82}
83
85
86
87void
91
93StatusCode
94StoreGateSvc::recordAddress(const std::string& skey,
96 bool clearAddressFlag,
97 const std::vector<CLID>& bases)
98{
99 _SGXCALL(recordAddress, (skey, std::move(pAddress), clearAddressFlag, bases), StatusCode::FAILURE);
100}
101
102StatusCode
104 bool clearAddressFlag,
105 const std::vector<CLID>& bases)
106{
107 _SGXCALL(recordAddress, (std::move(pAddress), clearAddressFlag, bases), StatusCode::FAILURE);
108}
109
110
111StatusCode
112StoreGateSvc::setConst(const void* pObject) {
113 _SGXCALL(setConst, (pObject), StatusCode::FAILURE);
114}
115
116
120
121 // Initialize service:
122 CHECK( Service::initialize() );
123
124 SG_MSG_VERBOSE ("Initializing {}", name());
125
126 SmartIF<Gaudi::Interfaces::IOptionsSvc> pJOSvc{serviceLocator()->service("JobOptionsSvc")};
127 if ( !pJOSvc.isValid() ) {
128 SG_MSG_ERROR ("Failed to retrieve JobOptionsSvc");
129 }
130 //copy our properties to the prototype (default) SGImplSvc
131 const std::string implStoreName = name() + "_Impl";
132 for (const Gaudi::Details::PropertyBase* p : getProperties()) {
133 pJOSvc->set( implStoreName + "." + p->name(), p->toString() );
134 }
135
136 //HACK ALERT: using createService rather then the customary service(...,CREATEIF=true) we set our pointer
137 // to SGImplSvc early (even before it is initialized). This should help take care of some initialize loops
138 // for example when we try to record an address from one of the address providers initialize methods
139
140 std::string implStoreFullName = "SGImplSvc/" + implStoreName;
141 SG_MSG_DEBUG ("trying to create store {}", implStoreFullName);
142
143 m_defaultStore = serviceLocator().as<ISvcManager>()->createService(implStoreFullName);
144
145 if (!m_defaultStore) {
146 SG_MSG_ERROR ("Could not create store {}", implStoreFullName);
147 return StatusCode::FAILURE;
148 }
149
150 if ( m_defaultStore->sysInitialize().isSuccess() ) {
151 // If this is the default event store (StoreGateSvc), then declare
152 // our arena as the default for memory allocations.
153 if (name() == "StoreGateSvc") {
154 m_defaultStore->makeCurrent();
155 }
156 } else {
157 SG_MSG_ERROR ("Could not initialize default store {}", implStoreFullName);
158 return StatusCode::FAILURE;
159 }
160 if ( !m_incSvc.retrieve().isSuccess() ) {
161 SG_MSG_ERROR ("Could not locate IncidentSvc");
162 return StatusCode::FAILURE;
163 }
164
165 // Don't retrieve m_activeStoreSvc here to prevent a possible
166 // initialization loop.
167
168 if (m_DumpStore) {
169 const int PRIORITY=100;
170 m_incSvc->addListener(this, "EndEvent",PRIORITY);
171 }
172
173 return StatusCode::SUCCESS;
174}
175
177StatusCode StoreGateSvc::stop() {
178 SG_MSG_VERBOSE ("Stop {}", name());
179 //HACK ALERT: ID event store objects refer to det store objects
180 //by setting an ad-hoc priority for event store(s) we make sure they are finalized and hence cleared first
181 // see e.g. https://savannah.cern.ch/bugs/index.php?99993
182 if (m_defaultStore->store()->storeID() == StoreID::EVENT_STORE) {
183 auto pISM = serviceLocator().as<ISvcManager>();
184 pISM->setPriority(name(), pISM->getPriority(name())+1).ignore();
185 SG_MSG_VERBOSE ("stop: setting service priority to {} so that event stores get finalized and cleared before other stores",
186 pISM->getPriority(name()));
187 }
188 return StatusCode::SUCCESS;
189}
190
191void StoreGateSvc::handle(const Incident &inc) {
192 currentStore()->handle(inc);
193}
194
196
197StatusCode
199 CHECK( Service::finalize() );
200 SG_MSG_VERBOSE ("Finalizing {}", name());
201 if (m_defaultStore) {
202 // m_defaultStore is not active, so ServiceManager won't finalize it!
203 CHECK( m_defaultStore->finalize());
204 }
205
206 printBadList (m_badRetrieves, "retrieve()");
207 printBadList (m_badRecords, "record()");
208 return StatusCode::SUCCESS;
209}
210
211
213DataProxy*
214StoreGateSvc::proxy(const void* const pTransient) const {
215 _SGXCALL(proxy, (pTransient), 0);
216}
217
219DataProxy*
220StoreGateSvc::proxy(const CLID& id) const {
221 _SGXCALL(proxy, (id), 0);
222}
223
225DataProxy*
226StoreGateSvc::proxy(const CLID& id, const std::string& key) const {
227 _SGXCALL(proxy, (id, key), 0);
228}
229
230
234StoreGateSvc::proxy(const CLID& id, bool checkValid) const {
235 _SGXCALL(proxy, (id, checkValid), 0);
236}
237
241StoreGateSvc::proxy(const CLID& id, const std::string& key, bool checkValid) const {
242 _SGXCALL(proxy, (id, key, checkValid), 0);
243}
244
245
252{
253 _SGXCALL(addToStore, (id, proxy), StatusCode::FAILURE);
254}
255
256
279 const std::string& key,
280 bool allowMods,
281 bool returnExisting)
282{
283 _SGXCALL(recordObject, (std::move(obj), key, allowMods, returnExisting), nullptr);
284}
285
286
288vector<const SG::DataProxy*>
290 vector<const SG::DataProxy*> nullV;
291 _SGXCALL(proxies, (), nullV);
292}
293
295vector<CLID>
297{
298 vector<CLID> nullV;
299 _SGXCALL(clids, (), nullV);
300}
301
305StoreGateSvc::transientProxy(const CLID& id, const std::string& key) const {
306 _SGXCALL(transientProxy, (id, key), 0);
307}
308
309
311DataObject*
313 _SGXCALL(accessData, (id), 0);
314}
315
317DataObject*
318StoreGateSvc::accessData(const CLID& id, const std::string& key) const {
319 _SGXCALL(accessData, (id, key), 0);
320}
321
322bool
324 const std::string& keyA, const std::string& keyB ) {
325 _SGXCALL(transientSwap, (id, keyA, keyB), false);
326}
327
330StatusCode
331StoreGateSvc::typeless_record( DataObject* obj, const std::string& key,
332 const void* const raw_ptr,
333 bool allowMods, bool resetOnly,
334 bool noHist ) {
335 _SGXCALL(typeless_record, (obj, key, raw_ptr, allowMods, resetOnly, noHist), StatusCode::FAILURE);
336}
337
338StatusCode
340 DataObject* obj, const std::string& key,
341 const void* const raw_ptr,
342 bool allowMods,
343 bool noHist,
344 const std::type_info* tinfo) {
345 _SGXCALL(typeless_overwrite, (id, obj, key, raw_ptr, allowMods, noHist, tinfo), StatusCode::FAILURE);
346}
347
349void
351{
352 m_storeID = id;
353 // FIXME: should broadcast this to all instances.
354 _SGVOIDCALL(setStoreID,(id));
355}
356
357void
358StoreGateSvc::keys(const CLID& id, std::vector<std::string>& vkeys,
359 bool includeAlias, bool onlyValid) const
360{
361 _SGVOIDCALL(keys,(id, vkeys, includeAlias, onlyValid));
362}
363
364
365
366std::string
368 std::string nullS = "\n>>>>>>>NO CURRENT STORE<<<<<<<\n";
369 _SGXCALL(dump, (), nullS);
370}
371
372int
374 _SGXCALL(typeCount, (clid), -1);
375}
376
377
378
379typename StoreGateSvc::sgkey_t
380StoreGateSvc::stringToKey (const std::string& str, CLID clid) {
381 _SGXCALL( stringToKey, (str, clid), 0 );
382}
383
384const std::string*
386 _SGXCALL( keyToString, (key), 0 );
387}
388
389const std::string*
391 _SGXCALL( keyToString, (key, clid), 0 );
392}
393
394void
396 const std::string& str,
397 CLID clidid) {
398 _SGVOIDCALL( registerKey, (key, str, clidid) );
399}
400void
402 sgkey_t target,
403 off_t index_offset) {
404 _SGVOIDCALL( remap_impl, (source, target, index_offset) );
405}
406
407bool
408StoreGateSvc::tryELRemap (sgkey_t sgkey_in, size_t index_in,
409 sgkey_t& sgkey_out, size_t& index_out) {
410 _SGXCALL( tryELRemap, (sgkey_in, index_in, sgkey_out, index_out), false );
411}
412
413void
414StoreGateSvc::releaseObject(const CLID& id, const std::string& key) {
415 _SGVOIDCALL( releaseObject, (id, key) );
416}
417
418void
422
423
424StatusCode
426 this->makeCurrent();
427 _SGXCALL(loadEventProxies, (), StatusCode::FAILURE);
428}
429
431// clear store
432StatusCode
434{
435 StatusCode sc = currentStore()->clearStore(forceRemove);
436
437 // See if we want to send a ClearStore incident.
438 // If m_pruneIncidents is true then we check the first time
439 // to see if there are any listeners. If not, then we avoid
440 // sending these incidents for the rest of the job.
441 if (m_pruneIncidents) {
442 if (m_listenerState == UNCHECKED) {
443 std::vector<IIncidentListener*> l;
444 m_incSvc->getListeners (l, "StoreCleared");
446 }
448 return sc;
449 }
450 }
451
452 // Send a notification that the store was cleared.
453 if (sc.isSuccess()) {
454 m_incSvc->fireIncident(StoreClearedIncident (this, name()));
455 }
456 return sc;
457}
458
459void
461 _SGVOIDCALL( emptyTrash, () );
462}
463
468 ::currentStoreGate = this;
469 _SGVOIDCALL (makeCurrent, ());
470}
471
472StatusCode StoreGateSvc::removeProxy(SG::DataProxy* proxy, const void* pTrans,
473 bool forceRemove) {
474 _SGXCALL(removeProxy, (proxy, pTrans, forceRemove), StatusCode::FAILURE);
475}
476
477
488StatusCode
489StoreGateSvc::createObj (IConverter* cvt,
490 IOpaqueAddress* addr,
491 DataObject*& refpObject)
492{
493 _SGXCALL( createObj, (cvt, addr, refpObject), StatusCode::FAILURE );
494}
495
496
504 CLID clid, const std::string& key) const
505{
506 if (m_storeID == StoreID::EVENT_STORE && currentHiveEventSlot != nullptr) {
508 std::string algo;
509 if (m_algContextSvc.isValid()) {
510 if (IAlgorithm* alg = m_algContextSvc->currentAlg()) {
511 if (alg->type() == "AthenaOutputStream") return;
512 if (alg->type() == "AthIncFirerAlg") return;
513 algo = alg->type() + "/" + alg->name();
514 bad.insert (BadListItem (clid, key, algo));
515 }
516 }
517 }
518}
519
520
527 const std::string& what) const
528{
529 if (bad.empty()) return;
530 std::vector<std::string> lines;
531 for (const BadListItem& id : bad) {
532 lines.push_back (id.fullKey() + " [" + id.m_algo + "]");
533 }
534 std::sort (lines.begin(), lines.end());
535 SG_MSG_WARNING ("Called {} on these objects in a MT store", what);
536 for (const std::string& s : lines) {
537 SG_MSG_WARNING (s);
538 }
539}
540
541
543{
544 std::println ("{}", sg->dump());
545}
546
547void SG_dump (StoreGateSvc* sg, const char* fname)
548{
549 std::ofstream f (fname);
550 std::println (f, "{}", sg->dump());
551 f.close();
552}
553
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
#define SG_MSG_WARNING(x,...)
#define SG_MSG_DEBUG(x,...)
#define SG_MSG_VERBOSE(x,...)
#define SG_MSG_ERROR(x,...)
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
an iterator facade to DataProxy*.
Definition SGIterator.h:194
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
T * retrieve() const
Variant of the above which doesn't return a status code.
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...
StatusCode retrieve(const T *&ptr) const
Retrieve the default object into a const T*.
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
void rememberBadRetrieve(CLID clid, const std::string &key) const
Remember that retrieve() was called for a MT store.
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
Forward declaration.
CxxUtils::RefCountedPtr< T > DataObjectSharedPtr
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.