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 _SGXCALL(recordAddress, (skey, std::move(pAddress), clearAddressFlag), StatusCode::FAILURE);
86}
87
88StatusCode
90 bool clearAddressFlag) {
91 _SGXCALL(recordAddress, (std::move(pAddress), clearAddressFlag), StatusCode::FAILURE);
92}
93
94
95StatusCode
96StoreGateSvc::setConst(const void* pObject) {
97 _SGXCALL(setConst, (pObject), StatusCode::FAILURE);
98}
99
100
104
105 // Initialize service:
106 CHECK( Service::initialize() );
107
108 verbose() << "Initializing " << name() << endmsg;
109
110 SmartIF<Gaudi::Interfaces::IOptionsSvc> pJOSvc{serviceLocator()->service("JobOptionsSvc")};
111 if ( !pJOSvc.isValid() ) {
112 error() << "Failed to retrieve JobOptionsSvc" << endmsg;
113 }
114 //copy our properties to the prototype (default) SGImplSvc
115 const std::string implStoreName = name() + "_Impl";
116 for (const Gaudi::Details::PropertyBase* p : getProperties()) {
117 pJOSvc->set( implStoreName + "." + p->name(), p->toString() );
118 }
119
120 //HACK ALERT: using createService rather then the customary service(...,CREATEIF=true) we set our pointer
121 // to SGImplSvc early (even before it is initialized). This should help take care of some initialize loops
122 // for example when we try to record an address from one of the address providers initialize methods
123
124 std::string implStoreFullName = "SGImplSvc/" + implStoreName;
125 debug() << "trying to create store " << implStoreFullName << endmsg;
126
127 m_defaultStore = serviceLocator().as<ISvcManager>()->createService(implStoreFullName);
128
129 if (!m_defaultStore) {
130 error() << "Could not create store " << implStoreFullName << endmsg;
131 return StatusCode::FAILURE;
132 }
133
134 if ( m_defaultStore->sysInitialize().isSuccess() ) {
135 // If this is the default event store (StoreGateSvc), then declare
136 // our arena as the default for memory allocations.
137 if (name() == "StoreGateSvc") {
138 m_defaultStore->makeCurrent();
139 }
140 } else {
141 error() << "Could not initialize default store " << implStoreFullName
142 << endmsg;
143 return StatusCode::FAILURE;
144 }
145 if ( !m_incSvc.retrieve().isSuccess() ) {
146 error() << "Could not locate IncidentSvc" << endmsg;
147 return StatusCode::FAILURE;
148 }
149
150 // Don't retrieve m_activeStoreSvc here to prevent a possible
151 // initialization loop.
152
153 if (m_DumpStore) {
154 const int PRIORITY=100;
155 m_incSvc->addListener(this, "EndEvent",PRIORITY);
156 }
157
158 return StatusCode::SUCCESS;
159}
160
162StatusCode StoreGateSvc::stop() {
163 verbose() << "Stop " << name() << endmsg;
164 //HACK ALERT: ID event store objects refer to det store objects
165 //by setting an ad-hoc priority for event store(s) we make sure they are finalized and hence cleared first
166 // see e.g. https://savannah.cern.ch/bugs/index.php?99993
167 if (m_defaultStore->store()->storeID() == StoreID::EVENT_STORE) {
168 auto pISM = serviceLocator().as<ISvcManager>();
169 pISM->setPriority(name(), pISM->getPriority(name())+1).ignore();
170 verbose() << "stop: setting service priority to " << pISM->getPriority(name())
171 << " so that event stores get finalized and cleared before other stores" <<endmsg;
172 }
173 return StatusCode::SUCCESS;
174}
175
176void StoreGateSvc::handle(const Incident &inc) {
177 currentStore()->handle(inc);
178}
179
181
182StatusCode
184 CHECK( Service::finalize() );
185 verbose() << "Finalizing " << name() << endmsg;
186 if (m_defaultStore) {
187 // m_defaultStore is not active, so ServiceManager won't finalize it!
188 CHECK( m_defaultStore->finalize());
189 }
190
191 printBadList (m_badRetrieves, "retrieve()");
192 printBadList (m_badRecords, "record()");
193 return StatusCode::SUCCESS;
194}
195
196
198DataProxy*
199StoreGateSvc::proxy(const void* const pTransient) const {
200 _SGXCALL(proxy, (pTransient), 0);
201}
202
204DataProxy*
205StoreGateSvc::proxy(const CLID& id) const {
206 _SGXCALL(proxy, (id), 0);
207}
208
210DataProxy*
211StoreGateSvc::proxy(const CLID& id, const std::string& key) const {
212 _SGXCALL(proxy, (id, key), 0);
213}
214
215
219StoreGateSvc::proxy(const CLID& id, bool checkValid) const {
220 _SGXCALL(proxy, (id, checkValid), 0);
221}
222
226StoreGateSvc::proxy(const CLID& id, const std::string& key, bool checkValid) const {
227 _SGXCALL(proxy, (id, key, checkValid), 0);
228}
229
230
237{
238 _SGXCALL(addToStore, (id, proxy), StatusCode::FAILURE);
239}
240
241
264 const std::string& key,
265 bool allowMods,
266 bool returnExisting)
267{
268 _SGXCALL(recordObject, (std::move(obj), key, allowMods, returnExisting), nullptr);
269}
270
271
273vector<const SG::DataProxy*>
275 vector<const SG::DataProxy*> nullV;
276 _SGXCALL(proxies, (), nullV);
277}
278
280vector<CLID>
282{
283 vector<CLID> nullV;
284 _SGXCALL(clids, (), nullV);
285}
286
290StoreGateSvc::transientProxy(const CLID& id, const std::string& key) const {
291 _SGXCALL(transientProxy, (id, key), 0);
292}
293
294
296DataObject*
298 _SGXCALL(accessData, (id), 0);
299}
300
302DataObject*
303StoreGateSvc::accessData(const CLID& id, const std::string& key) const {
304 _SGXCALL(accessData, (id, key), 0);
305}
306
307bool
309 const std::string& keyA, const std::string& keyB ) {
310 _SGXCALL(transientSwap, (id, keyA, keyB), false);
311}
312
315StatusCode
316StoreGateSvc::typeless_record( DataObject* obj, const std::string& key,
317 const void* const raw_ptr,
318 bool allowMods, bool resetOnly,
319 bool noHist ) {
320 _SGXCALL(typeless_record, (obj, key, raw_ptr, allowMods, resetOnly, noHist), StatusCode::FAILURE);
321}
322
323StatusCode
325 DataObject* obj, const std::string& key,
326 const void* const raw_ptr,
327 bool allowMods,
328 bool noHist,
329 const std::type_info* tinfo) {
330 _SGXCALL(typeless_overwrite, (id, obj, key, raw_ptr, allowMods, noHist, tinfo), StatusCode::FAILURE);
331}
332
334void
336{
337 m_storeID = id;
338 // FIXME: should broadcast this to all instances.
339 _SGVOIDCALL(setStoreID,(id));
340}
341
342void
343StoreGateSvc::keys(const CLID& id, std::vector<std::string>& vkeys,
344 bool includeAlias, bool onlyValid) const
345{
346 _SGVOIDCALL(keys,(id, vkeys, includeAlias, onlyValid));
347}
348
349
350
351std::string
353 std::string nullS = "\n>>>>>>>NO CURRENT STORE<<<<<<<\n";
354 _SGXCALL(dump, (), nullS);
355}
356
357int
359 _SGXCALL(typeCount, (clid), -1);
360}
361
362
363
364typename StoreGateSvc::sgkey_t
365StoreGateSvc::stringToKey (const std::string& str, CLID clid) {
366 _SGXCALL( stringToKey, (str, clid), 0 );
367}
368
369const std::string*
371 _SGXCALL( keyToString, (key), 0 );
372}
373
374const std::string*
376 _SGXCALL( keyToString, (key, clid), 0 );
377}
378
379void
381 const std::string& str,
382 CLID clidid) {
383 _SGVOIDCALL( registerKey, (key, str, clidid) );
384}
385void
387 sgkey_t target,
388 off_t index_offset) {
389 _SGVOIDCALL( remap_impl, (source, target, index_offset) );
390}
391
392bool
393StoreGateSvc::tryELRemap (sgkey_t sgkey_in, size_t index_in,
394 sgkey_t& sgkey_out, size_t& index_out) {
395 _SGXCALL( tryELRemap, (sgkey_in, index_in, sgkey_out, index_out), false );
396}
397
398StatusCode
401 SG::ConstProxyIterator& end) const {
402 _SGXCALL( proxyRange, (id, beg, end), StatusCode::FAILURE );
403}
404
405
406void
407StoreGateSvc::releaseObject(const CLID& id, const std::string& key) {
408 _SGVOIDCALL( releaseObject, (id, key) );
409}
410
411void
415
416
417StatusCode
419 this->makeCurrent();
420 _SGXCALL(loadEventProxies, (), StatusCode::FAILURE);
421}
422
424// clear store
425StatusCode
427{
428 StatusCode sc = currentStore()->clearStore(forceRemove);
429
430 // See if we want to send a ClearStore incident.
431 // If m_pruneIncidents is true then we check the first time
432 // to see if there are any listeners. If not, then we avoid
433 // sending these incidents for the rest of the job.
434 if (m_pruneIncidents) {
435 if (m_listenerState == UNCHECKED) {
436 std::vector<IIncidentListener*> l;
437 m_incSvc->getListeners (l, "StoreCleared");
439 }
441 return sc;
442 }
443 }
444
445 // Send a notification that the store was cleared.
446 if (sc.isSuccess()) {
447 m_incSvc->fireIncident(StoreClearedIncident (this, name()));
448 }
449 return sc;
450}
451
452void
454 _SGVOIDCALL( emptyTrash, () );
455}
456
461 ::currentStoreGate = this;
462 _SGVOIDCALL (makeCurrent, ());
463}
464
465StatusCode StoreGateSvc::removeProxy(SG::DataProxy* proxy, const void* pTrans,
466 bool forceRemove) {
467 _SGXCALL(removeProxy, (proxy, pTrans, forceRemove), StatusCode::FAILURE);
468}
469
470
481StatusCode
482StoreGateSvc::createObj (IConverter* cvt,
483 IOpaqueAddress* addr,
484 DataObject*& refpObject)
485{
486 _SGXCALL( createObj, (cvt, addr, refpObject), StatusCode::FAILURE );
487}
488
489
497 CLID clid, const std::string& key) const
498{
499 if (m_storeID == StoreID::EVENT_STORE && currentHiveEventSlot != nullptr) {
501 std::string algo;
502 if (m_algContextSvc.isValid()) {
503 if (IAlgorithm* alg = m_algContextSvc->currentAlg()) {
504 if (alg->type() == "AthenaOutputStream") return;
505 if (alg->type() == "AthIncFirerAlg") return;
506 algo = alg->type() + "/" + alg->name();
507 bad.insert (BadListItem (clid, key, algo));
508 }
509 }
510 }
511}
512
513
520 const std::string& what) const
521{
522 if (bad.empty()) return;
523 std::vector<std::string> lines;
524 for (const BadListItem& id : bad) {
525 lines.push_back (id.fullKey() + " [" + id.m_algo + "]");
526 }
527 std::sort (lines.begin(), lines.end());
528 warning() << "Called " << what << " on these objects in a MT store" << endmsg;
529 for (const std::string& s : lines) {
530 warning() << s << endmsg;
531 }
532}
533
534
536{
537 std::cout << sg->dump() << "\n";
538}
539
540void SG_dump (StoreGateSvc* sg, const char* fname)
541{
542 std::ofstream f (fname);
543 f << sg->dump() << "\n";
544 f.close();
545}
546
#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.
StatusCode recordAddress(const std::string &skey, CxxUtils::RefCountedPtr< IOpaqueAddress > pAddress, bool clearAddressFlag=true)
Create a proxy object using an IOpaqueAddress and a transient key.
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
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.