ATLAS Offline Software
Loading...
Searching...
No Matches
SGImplSvc.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#undef DEBUG_SGIMPL
6
7#include <algorithm>
8#include <cassert>
9#include <cstdio>
10#include <iostream>
11#include <print>
12#include <functional>
13#include <format>
14#include <string>
15#include <unordered_map>
16
17#include <sstream>
18#include <fstream>
19#include <iomanip>
20
30#include "GaudiKernel/IClassIDSvc.h"
31#include "GaudiKernel/IHistorySvc.h"
32#include "GaudiKernel/ISvcLocator.h"
33#include "GaudiKernel/IConversionSvc.h"
34#include "GaudiKernel/Incident.h"
35#include "GaudiKernel/IOpaqueAddress.h"
36#include "GaudiKernel/MsgStream.h"
37#include "GaudiKernel/StatusCode.h"
38#include "GaudiKernel/DataHistory.h"
41#include "SGTools/DataProxy.h"
42#include "SGTools/DataStore.h"
43#include "SGTools/StringPool.h"
49
50// StoreGateSvc. must come before SGImplSvc.h
53#include "SGTools/DataStore.h"
54
55using std::setw;
56using std::hex;
57using std::dec;
58using std::endl;
59using std::ends;
60using std::pair;
61using std::string;
62using std::vector;
63
64using SG::DataProxy;
65using SG::DataStore;
67
68// Helpers for debug formatting
69// std::print implementation to be replaced when C++ 23 is available
70namespace dbg {
71template <class... Args> void print(std::FILE* stream, std::format_string<Args...> fmt, Args&&... args) {
72 std::fputs(std::format(fmt, std::forward<Args>(args)...), stream);
73}
74
75template <class T> void* ptr(T* p) { return static_cast<void*>(p); }
76}
77
79// Remapping implementation.
80
81
82namespace SG {
83
84
96
97
98} // namespace SG
99
100
103SGImplSvc::SGImplSvc(const string& name,ISvcLocator* svc)
104 : base_class(name, svc),
105 m_pCLIDSvc("ClassIDSvc", name),
106 m_pDataLoader("EventPersistencySvc", name),
107 m_pPPSHandle("ProxyProviderSvc", name),
108 m_pPPS(nullptr),
109 m_pHistorySvc("HistorySvc", name),
110 m_pStore(new DataStore(*this)),
111 m_pIncSvc("IncidentSvc", name),
112 m_DumpStore(false),
113 m_ActivateHistory(false),
114 m_DumpArena(false),
115 m_pIOVSvc("IOVSvc", name),
116 m_storeLoaded(false),
117 m_remap_impl (new SG::RemapImpl),
118 m_arena (name),
119 m_slotNumber(-1),
120 m_numSlots(1)
121{
122 //our properties
123 declareProperty("ProxyProviderSvc", m_pPPSHandle);
124 declareProperty("Dump", m_DumpStore);
125 declareProperty("ActivateHistory", m_ActivateHistory);
126 declareProperty("DumpArena", m_DumpArena);
127 //StoreGateSvc properties
128 declareProperty("IncidentSvc", m_pIncSvc);
129 //add handler for Service base class property
130 m_outputLevel.declareUpdateHandler(&SGImplSvc::msg_update_handler, this);
131
133 header->addArena (&m_arena);
134}
135
136
140 header->delArena (&m_arena);
141
142 delete m_pStore;
143 delete m_remap_impl;
144}
145
149
150 SG_MSG_VERBOSE ("Initializing {}", name());
151
152 CHECK( Service::initialize() );
153
154 if (!m_pStore)
155 m_pStore = new DataStore (*this);
156 if (!m_remap_impl)
158
159 //properties accessible from now on
160
162 // If this is the default event store (StoreGateSvc), then declare
163 // our arena as the default for memory allocations.
164 if (this->storeID() == StoreID::EVENT_STORE) {
165 m_arena.makeCurrent();
166 SG::CurrentEventStore::setStore (this);
168 }
169 // set up the incident service:
170 if (!(m_pIncSvc.retrieve()).isSuccess()) {
171 SG_MSG_ERROR ("Could not locate IncidentSvc ");
172 return StatusCode::FAILURE;
173 }
174
175 // We explicitly do not retrieve m_pIOVSvc and rely on retrieval
176 // on first use to avoid an initialization loop here.
177
178 CHECK( m_pDataLoader.retrieve() );
179 CHECK( m_pCLIDSvc.retrieve() );
180
181 if (!m_pPPSHandle.empty()) {
182 CHECK( m_pPPSHandle.retrieve() );
184 }
185
186 if ( m_pPPS && (m_pPPS->preLoadProxies(*m_pStore)).isFailure() )
187 {
188 SG_MSG_DEBUG(" Failed to preLoad proxies");
189 return StatusCode::FAILURE;
190 }
191
192 // Get hold of History Service
193 if (m_ActivateHistory) {
194 CHECK( m_pHistorySvc.retrieve() );
195 }
196
197 return StatusCode::SUCCESS;
198}
199
200StatusCode SGImplSvc::start() {
201
202 SG_MSG_VERBOSE ("Start {}", name());
203 /*
204 // This will need regFcn clients to be updated first.
205 if ( 0 == m_pPPS || (m_pPPS->preLoadProxies(*m_pStore)).isFailure() ) {
206 SG_MSG_DEBUG (" Failed to preLoad proxies");
207 return StatusCode::FAILURE;
208 }
209 */
210
211 return StatusCode::SUCCESS;
212}
213
214StatusCode SGImplSvc::stop() {
215
216 SG_MSG_VERBOSE ("Stop {}", name());
217 //HACK ALERT: ID event store objects refer to det store objects
218 //by setting an ad-hoc priority for event store(s) we make sure they are finalized and hence cleared first
219 // see e.g. https://savannah.cern.ch/bugs/index.php?99993
220 if (store()->storeID() == StoreID::EVENT_STORE) {
221 ISvcManager* pISM(dynamic_cast<ISvcManager*>(serviceLocator().get()));
222 if (!pISM)
223 return StatusCode::FAILURE;
224 pISM->setPriority(name(), pISM->getPriority(name())+1).ignore();
225 SG_MSG_VERBOSE ("stop: setting service priority to {} so that event stores get finalized and cleared before other stores",
226 pISM->getPriority(name()));
227 }
228 return StatusCode::SUCCESS;
229}
230
232void SGImplSvc::handle(const Incident &inc) {
233
234 if (inc.type() == "EndEvent") {
235 if (m_DumpStore) {
236 SG_MSG_DEBUG("Dumping StoreGate Contents");
237 SG_MSG_INFO ("\n{}\n", dump());
238 }
239 }
240}
241
244 StatusCode sc(StatusCode::SUCCESS);
245 //FIXME this should probably be dealt with by the providers
246 if (0 != m_pPPS && !m_storeLoaded) {
247 m_storeLoaded = true;
248 sc=m_pPPS->loadProxies(*m_pStore);
249#ifdef DEBUG_SGIMPL
250 dbg::print(stderr, "SGImplSvc::loadEventProxies() LOADED PROXIES on {}\n", name());
251 }
252 else {
253 dbg::print(stderr, "SGImplSvc::loadEventProxies() PROXIES ALREADY LOADED on {}\n", name());
254#endif
255 }
256 return sc;
257}
258
260// Create a key for a type (used if the client has not specified a key)
261string SGImplSvc::createKey(const CLID& id)
262{
263 return std::to_string(m_pStore->typeCount(id) + 1);
264}
265
266// clear store
267StatusCode SGImplSvc::clearStore(bool forceRemove)
268{
269#ifdef DEBUG_SGIMPL
270 dbg::print(stderr, "SGImplSvc::clearStore(forceRemove={}) on {}\n", forceRemove, name());
271#endif
272 {
273 if (m_DumpArena) {
274 std::ostringstream s;
275 m_arena.report(s);
276 SG_MSG_INFO ("Report for Arena: {}\n{}", m_arena.name(), s.str());
277 }
278 }
279 {
281 emptyTrash();
282 for (auto& p : m_newBoundHandles)
283 p.second.clear();
284 assert(m_pStore);
285 SG_MSG_DEBUG ("Clearing store with forceRemove={}", forceRemove);
286 bool hard_reset = (m_numSlots > 1);
287 m_pStore->clearStore(forceRemove, hard_reset, &msgStream(MSG::DEBUG));
288 m_storeLoaded=false; //FIXME hack needed by loadEventProxies
289 }
290 {
291 lock_t remap_lock (m_remapMutex);
292 m_remap_impl->m_remaps.clear();
293 m_arena.reset();
294 }
295
296 return StatusCode::SUCCESS;
297}
298
301 SG_MSG_VERBOSE ("Finalizing {}", name());
302
303 // Incident service may not work in finalize.
304 // Clear this, so that we won't try to send an incident from clearStore.
305 (m_pIncSvc.release()).ignore();
306
307 const bool FORCEREMOVE(true);
308 clearStore(FORCEREMOVE).ignore();
309
310 m_stringpool.clear();
311 delete m_pStore;
312 m_pStore = nullptr;
313 delete m_remap_impl;
314 m_remap_impl = 0;
315 m_arena.erase();
316
317 return Service::finalize();
318}
319
322 SG_MSG_VERBOSE ("Reinitializing {}", name());
323 const bool FORCEREMOVE(true);
324 clearStore(FORCEREMOVE).ignore();
325 //not in v20r2p2! return Service::reinitialize();
326 return StatusCode::SUCCESS;
327}
328
331// add proxy (with IOpaqueAddress that will later be retrieved from P)
333StatusCode SGImplSvc::recordAddress(const std::string& skey,
335 bool clearAddressFlag,
336 const std::vector<CLID>& bases)
337{
339 assert(0 != pAddress);
340 CLID dataID = pAddress->clID();
341
342 if (dataID == 0)
343 {
344 SG_MSG_WARNING ("recordAddress: Invalid Class ID found in IOpaqueAddress @{}. IOA will not be recorded",
345 static_cast<void*>(pAddress.get()));
346 return StatusCode::FAILURE;
347 }
348
349 //do not overwrite a persistent object
350 if (m_pPPS) {
351 DataProxy* dp = m_pStore->proxy (dataID, skey);
352 if (!dp) {
353 dp = m_pPPS->retrieveProxy(dataID, skey, *m_pStore);
354 }
355 if (dp && dp->provider()) {
356 std::string clidTypeName;
357 m_pCLIDSvc->getTypeNameOfID(dataID, clidTypeName).ignore();
358 SG_MSG_WARNING ("recordAddress: failed for key={}, type (CLID {})\n"
359 " there is already a persistent version of this object. Will not record a duplicate! ",
360 skey, clidTypeName, dataID);
361 return StatusCode::FAILURE;
362 }
363 }
364
365 // Check if a key already exists
366 DataProxy* dp = m_pStore->proxy_exact(dataID, skey);
367 if (0 == dp && 0 != m_pPPS) {
368 dp = m_pPPS->retrieveProxy(dataID, skey, *m_pStore);
369 }
370
371 // Now treat the various cases:
372 if (0 == dp)
373 {
374 // create the proxy object and register it
375 dp = new DataProxy (TransientAddress (dataID, skey,
376 std::move(pAddress),
377 clearAddressFlag),
378 m_pDataLoader.get(), true, true);
379 m_pStore->addToStore(dataID, dp).ignore();
380
381 addAutoSymLinks (skey, dataID, dp, 0, false);
382
383 // Add extra bases.
384 for (CLID b : bases) {
385 if (addSymLink (b, dp).isFailure()) {
386 warning() << std::format ("Can't add extra base {} for object {}/{}",
387 b, dataID, skey) << endmsg;
388 }
389 }
390 }
391 else if ((0 != dp) && (0 == dp->address()))
392 // Note: intentionally not checking dp->isValidAddress()
393 {
394 // Update proxy with IOpaqueAddress
395 dp->setAddress(std::move(pAddress));
396 }
397 else
398 {
399 string errType;
400 m_pCLIDSvc->getTypeNameOfID(dataID, errType).ignore();
401 SG_MSG_WARNING ("recordAddress: preexisting proxy @{} with non-NULL IOA found for key type {} ({}). \n"
402 "Cannot record IOpaqueAddress @{}",
403 static_cast<void*>(dp), skey, errType, dataID,
404 static_cast<void*>(pAddress.get()));
405 return StatusCode::FAILURE;
406 }
407
408 return StatusCode::SUCCESS;
409
410}
411
414// add proxy (with IOpaqueAddress that will later be retrieved from P)
417 bool clearAddressFlag,
418 const std::vector<CLID>& bases)
419{
421 assert(0 != pAddress);
422
423 CLID dataID = pAddress->clID();
424
425 string gK = (pAddress->par())[1]; // transient name by convention
426 if (gK.empty()) gK = (pAddress->par())[0]; // FIXME backward compatibility
427 if (gK.empty()) gK = createKey(dataID);
428
429 return this->recordAddress(gK, std::move(pAddress), clearAddressFlag, bases);
430}
431
433 const string& gK,
434 DataObject* pDObj,
435 bool allowMods,
436 bool resetOnly) {
437 // locate the proxy
438 DataProxy* dp = m_pStore->proxy_exact(dataID, gK);
439
440 if (0 != dp) { //proxy found
441 if (0 != dp->object())
442 {
443 // Case 0: duplicated proxy
444 SG_MSG_WARNING (" setupProxy:: error setting up proxy for key {} and clid {}\n"
445 " Pre-existing valid DataProxy @{} found in Store for key {} with clid {}",
446 gK, dataID,
447 static_cast<void*>(dp),
448 dp->object()->name(),
449 dp->object()->clID());
450 recycle(pDObj); // commit this object to trash
451 dp = 0;
452 } else {
453 // Case 1: Proxy found... if not valid, update it:
454 dp->setObject(pDObj);
455 if (!allowMods) dp->setConst();
456 }
457 } else {
458 // Case 2: No Proxy found:
459 dp = new DataProxy(pDObj,
460 TransientAddress(dataID, gK),
461 !allowMods, resetOnly);
462 if (!(m_pStore->addToStore(dataID, dp).isSuccess())) {
463 SG_MSG_WARNING (" setupProxy:: could not addToStore proxy @{}",
464 static_cast<void*>(dp));
465 recycle(pDObj); // commit this object to trash
466 delete dp;
467 dp = 0;
468 }
469 }
470 return dp;
471}
472
479
481{
483 return store()->storeID();
484}
485
486
487void
488SGImplSvc::keys(const CLID& id, std::vector<std::string>& vkeys,
489 bool includeAlias, bool onlyValid)
490
491{
493 return store()->keys(id, vkeys, includeAlias, onlyValid);
494}
495
496
497bool SGImplSvc::isSymLinked(const CLID& linkID, DataProxy* dp)
498{
499 return (0 != dp) ? dp->transientID(linkID) : false;
500}
501
503// Dump Contents in store:
504string SGImplSvc::dump() const
505{
507 auto out_buffer = std::string{};
508 auto out = std::back_inserter(out_buffer);
509 const std::string me = name();
510 std::format_to(out, "{}: <<<<<<<<<<<<<<<<< Data Store Dump >>>>>>>>>>>>>>> \n", me);
511 std::format_to(out, "{}: SGImplSvc()::dump() which is {} \n", me, m_storeLoaded ? "LOADED" : "NOT LOADED");
512
513 DataStore::ConstStoreIterator s_iter, s_end;
514 store()->tRange(s_iter, s_end).ignore();
515
516 for (; s_iter != s_end; ++s_iter)
517 {
518
519 CLID id = s_iter->first;
520 int nProxy = store()->typeCount(id);
521 std::string tname;
522 m_pCLIDSvc->getTypeNameOfID(id, tname).ignore();
523 std::format_to(out, "{}: Found {} {} for ClassID {} ({}): \n", me, nProxy, ((nProxy == 1) ? "proxy" : "proxies"), id, tname);
524
525 // loop over each type:
526 SG::ConstProxyIterator p_iter = (s_iter->second).begin();
527 SG::ConstProxyIterator p_end = (s_iter->second).end();
528
529 while (p_iter != p_end) {
530 const DataProxy& dp(*p_iter->second);
531 std::format_to(out, "{}: flags: ({:7s}, {:8s}, {:6s}) --- data: {:10p} --- key: {}\n", me,
532 (dp.isValid() ? "valid" : "INVALID"),
533 (dp.isConst() ? "locked" : "UNLOCKED"),
534 (dp.isResetOnly() ? "reset" : "DELETE"),
535 dbg::ptr(dp.object()), p_iter->first);
536 ++p_iter;
537 }
538 }
539 std::format_to(out, "{}: <<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>> \n", me);
540 return out_buffer;
541}
542
543DataStore*
545{
546 return m_pStore;
547}
548
549const DataStore*
551{
552 return m_pStore;
553}
554
555
557// Make a soft link to the object with key
559StatusCode SGImplSvc::symLink(const CLID id, const std::string& key, const CLID linkID)
560{
562 SG::DataProxy* dp(proxy(id, key, false));
563 // if symLink already exists, just return success
564 return isSymLinked(linkID,dp) ?
565 StatusCode::SUCCESS :
566 addSymLink(linkID,dp);
567}
568
569
570StatusCode
572{
573 if (0 == dp) {
574 SG_MSG_WARNING ("addSymLink: no target DataProxy found. Sorry, can't link to a non-existing data object");
575 return StatusCode::FAILURE;
576 }
577 StatusCode sc = m_pStore->addSymLink(linkid, dp);
578
579 // If the symlink is a derived->base conversion, then we may have
580 // a different transient pointer for the symlink.
581 if (sc.isSuccess() && dp->object()) {
582 void* baseptr = SG::DataProxy_cast (dp, linkid);
583 if (baseptr)
584 this->t2pRegister (baseptr, dp).ignore();
585 }
586 return sc;
587}
588
589
590StatusCode SGImplSvc::setAlias(const void* pObject, const std::string& aliasKey)
591{
593
594 SG::DataProxy* dp(0);
595 dp = proxy(pObject);
596 if (0 == dp) {
597 SG_MSG_ERROR ("setAlias: problem setting alias {}\n"
598 "DataObject does not exist, record before setting alias.",
599 aliasKey);
600 return StatusCode::FAILURE;
601 }
602
603 StatusCode sc = addAlias(aliasKey, dp);
604 if (sc.isFailure()) {
605 SG_MSG_ERROR ("setAlias: problem setting alias {}\n"
606 "DataObject does not exist, record before setting alias.",
607 aliasKey);
608 return StatusCode::FAILURE;
609 }
610
611 return StatusCode::SUCCESS;
612}
613
614
615StatusCode
616SGImplSvc::addAlias(const std::string& aliasKey, DataProxy* proxy)
617{
618 if (0 == proxy) {
619 SG_MSG_WARNING ("addAlias: no target DataProxy given, Cannot alias to a non-existing object");
620 return StatusCode::FAILURE;
621 }
622
623 // add key to proxy and to ProxyStore
624 return m_pStore->addAlias(aliasKey, proxy);
625}
626
627bool
628SGImplSvc::contains(const CLID id, const std::string& key) const
629{
630 try {
631 return (0 != proxy(id, key, true));
632 } catch(...) { return false; }
633}
634
635
636bool
637SGImplSvc::transientContains(const CLID id, const std::string& key) const
638{
639 try {
640 return (0 != transientProxy(id, key));
641 } catch(...) { return false; }
642}
643
644
645DataProxy*
646SGImplSvc::proxy(const void* const pTransient) const
647{
648 // No lock needed here --- the T2pmap held by DataStore has its own locking
649 // (and we were seeing contention here).
650 //lock_t lock (m_mutex);
651 return m_pStore->locatePersistent(pTransient);
652}
653
654DataProxy*
655SGImplSvc::proxy(const CLID& id) const
656{
657 return proxy(id, false);
658}
659
660DataProxy*
661SGImplSvc::proxy(const CLID& id, bool checkValid) const
662{
663 DataProxy* dp = nullptr;
664 {
666 dp = m_pStore->proxy(id);
667 if (0 == dp && 0 != m_pPPS) {
669 dp = m_pPPS->retrieveProxy(id, string("DEFAULT"), *pStore);
670 }
671 }
673 // Be sure to release the lock before this.
674 // isValid() may call back to the store, so we could otherwise deadlock..
675 if (checkValid && 0 != dp) {
676 // FIXME: For keyless retrieve, this checks only the first instance
677 // of the CLID in store. If that happens to be invalid, but the second
678 // is valid - this does not work (when checkValid is requested).
679 return dp->isValid() ? dp : 0;
680 }
681 return dp;
682}
683
684DataProxy*
685SGImplSvc::proxy(const CLID& id, const string& key) const
686{
687 return proxy(id, key, false);
688}
689
691SGImplSvc::proxy(const CLID& id, const string& key, bool checkValid) const
692{
693 DataProxy* dp = nullptr;
694 {
696 dp = m_pStore->proxy(id, key);
697#ifdef DEBUG_SGIMPL
698 if (!dp) dbg::print(stderr, "::SGImplSvc::proxy(name={}, key={}): data proxy is null, m_pPPS is {}\n", this->name(), key, m_pPPS == 0 ? "NULL" : "NOT NULL");
699#endif
700 if (0 == dp && 0 != m_pPPS) {
702 dp = m_pPPS->retrieveProxy(id, key, *pStore);
703#ifdef DEBUG_SGIMPL
704 if (!dp) dbg::print(stderr, "::SGImplSvc::proxy(name={}, key={}): data proxy is still null\n", this->name(), key);
705#endif
706 }
707 }
708 // Be sure to release the lock before this.
709 // isValid() may call back to the store, so we could otherwise deadlock..
710 if (checkValid && 0 != dp && !(dp->isValid())) {
711 dp = 0;
712 }
713 return dp;
714}
715
716
723{
725 return m_pStore->addToStore (id, proxy);
726}
727
728
750 const std::string& key,
751 bool allowMods,
752 bool returnExisting)
753{
755 const void* raw_ptr = obj.get();
756 const std::type_info* tinfo = nullptr;
757
758 if (DataBucketBase* bucket = dynamic_cast<DataBucketBase*> (obj.get())) {
759 raw_ptr = bucket->object();
760 tinfo = &bucket->tinfo();
761 }
762
763 if (returnExisting) {
764 SG::DataProxy* proxy = this->proxy (obj->clID(), key);
765 if (proxy && proxy->isValid()) return proxy;
766
767 // Look for the same object recorded under a different key/clid.
768 proxy = this->proxy (raw_ptr);
769 if (proxy && proxy->isValid()) {
770 if (proxy->transientID (obj->clID())) {
771 // CLID matches. Make an alias.
772 if (addAlias (key, proxy).isFailure()) {
773 CLID clid = proxy->clID();
774 std::string clidTypeName;
775 m_pCLIDSvc->getTypeNameOfID(clid, clidTypeName).ignore();
776 SG_MSG_WARNING ("SGImplSvc::recordObject: addAlias fails for object {} [{}] {} and new key {}",
777 clid, clidTypeName, proxy->name(), key);
778 proxy = nullptr;
779 }
780 }
781
782 else if (key == proxy->name() || proxy->hasAlias(key) > 0)
783 {
784 // key matches. Make a symlink.
785 if (addSymLink (obj->clID(), proxy).isFailure()) {
786 CLID clid = proxy->clID();
787 std::string clidTypeName;
788 m_pCLIDSvc->getTypeNameOfID(clid, clidTypeName).ignore();
789 CLID newclid = obj->clID();
790 std::string newclidTypeName;
791 m_pCLIDSvc->getTypeNameOfID(newclid, newclidTypeName).ignore();
792 SG_MSG_ERROR ("SGImplSvc::recordObject:"
793 " addSymLink fails for object {} [{}] {} and new clid {} [{}]",
794 clid, clidTypeName, proxy->name(),
795 newclid, newclidTypeName);
796 proxy = nullptr;
797 }
798 }
799
800 else {
801 CLID clid = proxy->clID();
802 std::string clidTypeName;
803 m_pCLIDSvc->getTypeNameOfID(clid, clidTypeName).ignore();
804 CLID newclid = obj->clID();
805 std::string newclidTypeName;
806 m_pCLIDSvc->getTypeNameOfID(newclid, newclidTypeName).ignore();
807 SG_MSG_ERROR ("SGImplSvc::recordObject:"
808 " existing object found with {} [{}] {} but neither"
809 " clid {} [{}] nor key {} match.",
810 clid, clidTypeName, proxy->name(),
811 newclid, newclidTypeName, key);
812 proxy = nullptr;
813 }
814
815 return proxy;
816 }
817 }
818
819 const bool resetOnly = true;
820 const bool noHist = false;
821 SG::DataProxy* proxy = nullptr;
822 if (this->typeless_record (obj.get(), key, raw_ptr,
823 allowMods, resetOnly, noHist, tinfo,
824 &proxy, true).isFailure())
825 {
826 return nullptr;
827 }
828 return proxy;
829}
830
831
836{
837 return m_pStore->proxy_exact_unlocked (sgkey, m_mutex);
838}
839
840
847void SGImplSvc::setSlotNumber (int slot, int numSlots)
848{
849 m_slotNumber = slot;
850 m_numSlots = numSlots;
851
853 header->setArenaForSlot (slot, &m_arena);
854}
855
856
857std::vector<const SG::DataProxy*>
859{
861 const std::vector<SG::DataProxy*>& proxies = store()->proxies();
862 std::vector<const SG::DataProxy*> ret (proxies.begin(), proxies.end());
863 return ret;
864}
865
866
867std::vector<CLID>
869{
871
872 using std::distance;
873 DataStore::ConstStoreIterator s_iter, s_end;
874 store()->tRange(s_iter, s_end).ignore();
875
876 std::vector<CLID> clids;
877 clids.reserve( distance( s_iter, s_end ) );
878
879 for (; s_iter != s_end; ++s_iter ) {
880 const CLID id = s_iter->first;
881 clids.push_back (id);
882 }
883
884 return clids;
885}
886
887
889SGImplSvc::transientProxy(const CLID& id, const string& key) const
890{
892 DataProxy* dp(m_pStore->proxy(id, key));
893 return ( (0 != dp && dp->isValidObject()) ? dp : 0 );
894}
895
896DataObject*
898{
900 DataProxy* theProxy(proxy(id, true));
901 return (0 == theProxy) ? 0 : theProxy->accessData();
902}
903
904DataObject*
905SGImplSvc::accessData(const CLID& id, const string& key) const
906{
908 DataProxy* theProxy(proxy(id, key, true));
909 return (0 == theProxy) ? 0 : theProxy->accessData();
910}
911
912StatusCode
913SGImplSvc::typeless_record( DataObject* obj, const std::string& key,
914 const void* const raw_ptr,
915 bool allowMods, bool resetOnly, bool noHist)
916{
917 return typeless_record (obj, key, raw_ptr, allowMods, resetOnly, noHist, 0,
918 nullptr, true);
919}
920
921
922StatusCode
923SGImplSvc::typeless_record( DataObject* obj, const std::string& key,
924 const void* const raw_ptr,
925 bool allowMods, bool resetOnly, bool noHist,
926 const std::type_info* tinfo)
927{
928 return typeless_record (obj, key, raw_ptr, allowMods, resetOnly, noHist,tinfo,
929 nullptr, true);
930}
931
932
933StatusCode
934SGImplSvc::typeless_record( DataObject* obj, const std::string& key,
935 const void* const raw_ptr,
936 bool allowMods, bool resetOnly, bool noHist,
937 const std::type_info* tinfo,
938 SG::DataProxy** proxy_ret,
939 bool noOverwrite)
940{
943 record_impl( obj, key, raw_ptr, allowMods, resetOnly, !noOverwrite, tinfo);
944 if ( proxy == nullptr )
945 return StatusCode::FAILURE;
946 if (proxy_ret)
947 *proxy_ret = proxy;
948
949 if ( !m_ActivateHistory || noHist ) {
950 return StatusCode::SUCCESS;
951 }
952
953 if ( store()->storeID() != StoreID::EVENT_STORE ) {
954 return StatusCode::SUCCESS;
955 } else {
956 return record_HistObj( obj->clID(), key, name(), allowMods, resetOnly );
957 }
958}
959
960StatusCode
962 DataObject* obj,
963 const std::string& key,
964 const void* const raw_ptr,
965 bool allowMods,
966 bool noHist,
967 const std::type_info* tinfo)
968{
970 StatusCode sc(StatusCode::SUCCESS);
971 SG::DataProxy* toRemove(proxy(clid, key, false));
972 if (0 != toRemove) {
973 toRemove->addRef();
974 const bool FORCEREMOVE(true);
975 sc =removeProxy(toRemove, (void*)0, FORCEREMOVE);
976 }
977 if (sc.isSuccess()) {
978 const bool ALLOWOVERWRITE(true);
979 const bool NORESET(false);
980 if (record_impl( obj, key, raw_ptr, allowMods, NORESET, ALLOWOVERWRITE, tinfo) == nullptr)
981 sc = StatusCode::FAILURE;
982 else if ( m_ActivateHistory && noHist && store()->storeID() == StoreID::EVENT_STORE ) {
983 sc = record_HistObj( obj->clID(), key, name(), allowMods, NORESET );
984 }
985 }
986 //for detector store objects managed by IIOVSvc, replace the old proxy with the new one (#104311)
987 if (toRemove && sc.isSuccess() && store()->storeID() == StoreID::DETECTOR_STORE) {
988 sc = m_pIOVSvc->replaceProxy(toRemove, proxy(clid, key));
989 }
990 if (toRemove)
991 toRemove->release();
992 return sc;
993}
994
996SGImplSvc::record_impl( DataObject* pDObj, const std::string& key,
997 const void* const raw_ptr,
998 bool allowMods, bool resetOnly, bool allowOverwrite,
999 const std::type_info* tinfo)
1000{
1001 CLID clid = pDObj->clID();
1002 std::string rawKey(key);
1003 if (!allowOverwrite && m_pPPS) {
1004 //do not overwrite a persistent object
1005 DataProxy* dp = m_pStore->proxy (clid, rawKey);
1006 if (!dp) {
1007 dp = m_pPPS->retrieveProxy(clid, rawKey, *m_pStore);
1008 }
1009 if (dp && dp->provider()) {
1010 std::string clidTypeName;
1011 m_pCLIDSvc->getTypeNameOfID(clid, clidTypeName).ignore();
1012 SG_MSG_WARNING ("record_impl: you are recording an object with key {}, type {} (CLID {})\n"
1013 " There is already a persistent version of this object."
1014 " Recording a duplicate may lead to unreproducible results and it is deprecated.",
1015 rawKey, clidTypeName, clid);
1016 }
1017 }
1018 //now check whether raw_ptr has already been recorded
1019 //We need to do this before we create the bucket, the proxy etc
1020 SG::DataProxy* dp(proxy(raw_ptr));
1021 if (0 != dp) {
1022 std::string clidTypeName;
1023 m_pCLIDSvc->getTypeNameOfID(clid, clidTypeName).ignore();
1024 SG_MSG_WARNING ("record_impl: failed for key={}, type {} (CLID {})\n"
1025 " object @{} already in store with key={}. Will not record a duplicate!",
1026 rawKey, clidTypeName, clid, raw_ptr, dp->name());
1027 if (pDObj != dp->object()) {
1028 DataBucketBase* pDBB(dynamic_cast<DataBucketBase*>(pDObj));
1029 if (!pDBB) std::abort();
1030 pDBB->relinquish(); //don't own the data obj already recorded!
1031 }
1032 this->recycle(pDObj);
1033 return nullptr;
1034 }
1035
1036
1037 // setup the proxy
1038 dp = setupProxy( clid, rawKey, pDObj, allowMods, resetOnly );
1039 if ( 0 == dp ) {
1040 std::string clidTypeName;
1041 m_pCLIDSvc->getTypeNameOfID(clid, clidTypeName).ignore();
1042 SG_MSG_WARNING ("record_impl: Problem setting up the proxy for object @{}\n"
1043 " recorded with key {} of type {} (CLID {}) in DataObject @{}",
1044 raw_ptr, rawKey, clidTypeName, clid,
1045 static_cast<void*>(pDObj));
1046
1047 return nullptr;
1048 }
1049
1050 // record in t2p:
1051 if ( !(this->t2pRegister( raw_ptr, dp )).isSuccess() ) {
1052 std::string clidTypeName;
1053 m_pCLIDSvc->getTypeNameOfID(clid, clidTypeName).ignore();
1054 SG_MSG_WARNING ("record_impl: can not add to t2p map object @{}\n"
1055 " with key {} of type {} (CLID {})",
1056 raw_ptr, rawKey, clidTypeName, clid);
1057 return nullptr;
1058 }
1059
1060 addAutoSymLinks (rawKey, clid, dp, tinfo);
1061
1062 return dp;
1063}
1064
1065DataProxy*
1067 bool checkValid) const
1068{
1069 DataProxy* dp = m_pStore->proxy(tAddr);
1070
1071 if (checkValid && 0 != dp) {
1072 return dp->isValid() ? dp : 0;
1073 } else {
1074 return dp;
1075 }
1076}
1077
1078StatusCode
1080 bool forceRemove)
1081{
1083 // check if valid proxy
1084 if (0 == proxy) return StatusCode::FAILURE;
1085
1086 if (0 == pTrans) {
1087 DataBucketBase* bucket = dynamic_cast<DataBucketBase*>(proxy->object());
1088 if (bucket) pTrans = bucket->object();
1089 }
1090
1091 // remove all entries from t2p map
1092 // --- only if the proxy actually has an object!
1093 // otherwise, we can trigger I/O.
1094 // besides being useless here, we can get deadlocks if we
1095 // call into the I/O code while holding the SG lock.
1096 if (proxy->isValidObject()) {
1097 this->t2pRemove(pTrans);
1098 SG::DataProxy::CLIDCont_t clids = proxy->transientID();
1099 for (SG::DataProxy::CLIDCont_t::const_iterator i = clids.begin();
1100 i != clids.end();
1101 ++i)
1102 {
1103 void* ptr = SG::DataProxy_cast (proxy, *i);
1104 this->t2pRemove(ptr);
1105 }
1106 }
1107
1108 // remove from store
1109 return m_pStore->removeProxy(proxy, forceRemove, true);
1110}
1111
1112StatusCode
1113SGImplSvc::t2pRegister(const void* const pTrans, DataProxy* const pPers)
1114{
1115 return m_pStore->t2pRegister(pTrans, pPers);
1116}
1117
1118
1119void
1120SGImplSvc::t2pRemove(const void* const pTrans)
1121{
1122 m_pStore->t2pRemove(pTrans);
1123}
1124
1125void
1126SGImplSvc::msg_update_handler(Gaudi::Details::PropertyBase& /*outputLevel*/)
1127{
1128 setUpMessaging();
1129 updateMsgStreamOutputLevel( outputLevel() );
1130 msgSvc()->setOutputLevel(name(), outputLevel());
1131}
1132
1133StatusCode SGImplSvc::setConst(const void* pObject)
1134{
1136 // Check if DataProxy does not exist
1137 DataProxy * dp = proxy(pObject);
1138
1139 if (0 == dp)
1140 {
1141 SG_MSG_WARNING ("setConst: NO Proxy for the dobj you want to set const");
1142 return StatusCode::FAILURE;
1143 }
1144
1145 dp->setConst();
1146 return StatusCode::SUCCESS;
1147}
1148
1149
1150// remove an object from Store, will remove its proxy if not reset only
1151StatusCode
1152SGImplSvc::remove(const void* pObject)
1153{
1155 return removeProxy(proxy(pObject), pObject);
1156}
1157
1158
1159// remove an object and its proxy from Store
1160StatusCode
1162{
1164 const bool FORCEREMOVE(true);
1165 return removeProxy(proxy(pObject), pObject, FORCEREMOVE);
1166}
1167
1168//put a bad (unrecordable) dobj away
1169void SGImplSvc::recycle(DataObject* pBadDObj) {
1170 assert(pBadDObj);
1171 pBadDObj->addRef();
1172 m_trash.push_back(pBadDObj);
1173}
1174
1175//throw away bad objects
1178 while (!m_trash.empty()) {
1179 m_trash.front()->release(); //delete the bad data object
1180 m_trash.pop_front(); //remove pointer from list
1181 }
1182}
1183
1184
1185/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1186
1187StatusCode
1188SGImplSvc::record_HistObj(const CLID& id, const std::string& key,
1189 const std::string& store,
1190 bool allowMods, bool resetOnly) {
1191
1192 DataHistory *dho;
1193 dho = m_pHistorySvc->createDataHistoryObj( id, key, store );
1194
1195 std::string idname;
1196 StatusCode sc = m_pCLIDSvc->getTypeNameOfID(id, idname);
1197 if (sc.isFailure() || idname.empty() ) {
1198 idname = std::to_string(id);
1199 }
1200 idname += '/';
1201 idname += key;
1202
1203 DataObject* obj = SG::asStorable(dho);
1204
1205 const bool ALLOWOVERWRITE(false);
1206 if (record_impl(obj, idname, dho, allowMods, resetOnly, ALLOWOVERWRITE,
1207 &typeid(DataHistory)) == nullptr)
1208 return StatusCode::FAILURE;
1209 return StatusCode::SUCCESS;
1210}
1211
1212
1223{
1225 return m_stringpool.stringToKey (str, clid);
1226}
1227
1228
1236const std::string* SGImplSvc::keyToString (sgkey_t key) const
1237{
1239 return m_stringpool.keyToString (key);
1240}
1241
1242
1251const std::string*
1253{
1255 return m_stringpool.keyToString (key, clid);
1256}
1257
1258
1272 const std::string& str,
1273 CLID clid)
1274{
1276 if (!m_stringpool.registerKey (key, str, clid)) {
1277 CLID clid2;
1278 const std::string* str2 = m_stringpool.keyToString (key, clid2);
1279 SG_MSG_WARNING ("The numeric key {} maps to multiple string key/CLID pairs: {}/{} and {}/{}",
1280 key, *str2, clid2, str, clid);
1281 }
1282}
1283
1284
1293{
1294 // We should hold m_stringPoolMutex before touching the pool.
1295 // But if we acquire the locks for both this and the other store,
1296 // we risk a deadlock. So first copy the other pool, so that we
1297 // don't need to hold both locks at the same time.
1298 SG::StringPool tmp;
1299 {
1300 lock_t lock (other.m_stringPoolMutex);
1301 tmp = other.m_stringpool;
1302 }
1304 return m_stringpool.merge (tmp);
1305}
1306
1307
1308void
1309SGImplSvc::releaseObject(const CLID& id, const std::string& key) {
1311 DataProxy *pP(0);
1312 if (0 != (pP = proxy(id, key))) {
1313 // remove all entries from t2p map
1315 SG::DataProxy::CLIDCont_t::const_iterator i(clids.begin()), e(clids.end());
1316 while (i != e) t2pRemove(SG::DataProxy_cast (pP, *i++));
1317 DataBucketBase *pDBB(dynamic_cast<DataBucketBase*>(pP->object()));
1318 //tell the bucket to let go of the data object
1319 if (0 != pDBB) pDBB->relinquish(); //somebody else better took ownership
1320 bool hard_reset = (m_numSlots > 1);
1321 pP->reset (hard_reset);
1322 }
1323}
1324
1325void
1328
1329 // Remove transient pointer entries for this proxy.
1330 // But do that only if the proxy has a valid object.
1331 // Otherwise, we could trigger I/O --- which we don't want since it's useless
1332 // (we'd just destroy the object immediately). In some cases it can also
1333 // lead to a deadlock (see ATR-24482).
1334 if (dp->isValidObject()) {
1335 SG::DataProxy::CLIDCont_t clids = dp->transientID();
1336 SG::DataProxy::CLIDCont_t::const_iterator i(clids.begin()), e(clids.end());
1337 while (i != e) {
1338 t2pRemove(SG::DataProxy_cast (dp, *i++));
1339 }
1340 }
1341
1342 bool hard_reset = (m_numSlots > 1);
1343 dp->reset (hard_reset);
1344}
1345
1346
1355 sgkey_t target,
1356 off_t index_offset)
1357{
1359 SG::RemapImpl::remap_t payload;
1360 payload.target = target;
1361 payload.index_offset = index_offset;
1362 m_remap_impl->m_remaps[source] = payload;
1363}
1364
1365
1374bool SGImplSvc::tryELRemap (sgkey_t sgkey_in, size_t index_in,
1375 sgkey_t& sgkey_out, size_t& index_out)
1376{
1378 SG::RemapImpl::remap_map_t::iterator i =
1379 m_remap_impl->m_remaps.find (sgkey_in);
1380 if (i == m_remap_impl->m_remaps.end())
1381 return false;
1382 const SG::RemapImpl::remap_t& payload = i->second;
1383 sgkey_out = payload.target;
1384 index_out = index_in + payload.index_offset;
1385 return true;
1386}
1387
1388
1389CLID SGImplSvc::clid( const std::string& key ) const
1390{
1393 store()->tRange(s_iter, s_end).ignore();
1394
1395 for ( ; s_iter != s_end; ++s_iter ) {
1396 if ( s_iter->second.find( key ) != s_iter->second.end() ) {
1397 return s_iter->first;
1398 }
1399 }
1400
1401 return CLID_NULL;
1402}
1403
1404
1406void SGImplSvc::addAutoSymLinks (const std::string& key,
1407 CLID clid,
1408 DataProxy* dp,
1409 const std::type_info* tinfo,
1410 bool warn_nobib /*= true*/)
1411{
1412 // Automatically make all legal base class symlinks
1413 if (!tinfo) {
1415 }
1416 const SG::BaseInfoBase* bib = nullptr;
1417 if (tinfo) {
1418 bib = SG::BaseInfoBase::find (*tinfo);
1419 }
1420 if (!bib) {
1421 // Could succeed where the previous fails if clid for DataVector<T>
1422 // but tinfo is for ConstDataVector<DataVector<T> >.
1424 }
1425 if ( bib ) {
1426 const std::vector<CLID>& bases = bib->get_bases();
1427 for ( std::size_t i = 0, iMax = bases.size(); i < iMax; ++i ) {
1428 if ( bases[i] != clid ) {
1429 if ( addSymLink( bases[i], dp ).isSuccess() ) {
1430 // register with t2p
1431 if (dp->object())
1432 this->t2pRegister( SG::DataProxy_cast( dp, bases[i] ), dp ).ignore();
1433 }
1434 else {
1435 SG_MSG_WARNING ("record_impl: Doing auto-symlinks for object"
1436 " with CLID {} and SG key {}:"
1437 " Proxy already set for base CLID {}; not making auto-symlink.",
1438 clid, key, bases[i]);
1439 }
1440 }
1441 }
1442
1443 // Handle copy conversions.
1444 {
1445 for (CLID copy_clid : bib->get_copy_conversions()) {
1446 if (m_pStore->addSymLink (copy_clid, dp).isFailure()) {
1447 SG_MSG_WARNING ("record_impl: Doing auto-symlinks for object"
1448 " with CLID {} and SG key {}:"
1449 " Proxy already set for copy-conversion CLID {}; not making auto-symlink.",
1450 clid, key, copy_clid);
1451 }
1452 }
1453 }
1454 }
1455 else {
1456 if (warn_nobib) {
1457 SG_MSG_WARNING ("record_impl: Could not find suitable SG::BaseInfoBase for CLID [{}] ({}) !\t"
1458 "No auto-symlink established !",
1459 clid, key);
1460 }
1461 }
1462}
1463
1464void
1467
1468 // Reset handles added since the last call to commit.
1469 bool hard_reset = (m_numSlots > 1);
1470 std::vector<IResetable*> handles;
1471 m_newBoundHandles[std::this_thread::get_id()].swap (handles);
1472 for (IResetable* h : handles)
1473 h->reset (hard_reset);
1474}
1475
1476
1482void
1484{
1485 m_newBoundHandles[std::this_thread::get_id()].push_back (handle);
1486}
1487
1488
1494void
1496{
1497 std::vector<IResetable*>& v = m_newBoundHandles[std::this_thread::get_id()];
1498 std::vector<IResetable*>::iterator it =
1499 std::find (v.begin(), v.end(), handle);
1500 if (it != v.end())
1501 v.erase (it);
1502}
1503
1504
1508{
1510 m_arena.makeCurrent();
1511 SG::CurrentEventStore::setStore (this);
1512}
1513
1514
1525StatusCode
1526SGImplSvc::createObj (IConverter* cvt,
1527 IOpaqueAddress* addr,
1528 DataObject*& refpObject)
1529{
1530 // This lock was here originally, but is probably not really needed ---
1531 // both DataProxy and the I/O components have their own locks.
1532 // Further, this was observed to cause deadlocks for the detector store,
1533 // and would in general be expected to be a contention issue.
1534 //lock_t lock (m_mutex);
1535 return cvt->createObj (addr, refpObject);
1536}
1537
1538
1539// This is intended to be called from the debugger.
1541{
1542 std::println ("{}", sg->dump());
1543}
1544void SG_dump (SGImplSvc* sg, const char* fname)
1545{
1546 std::ofstream f (fname);
1547 std::println (f, "{}", sg->dump());
1548 f.close();
1549}
1550
1551
1558SG::SourceID SGImplSvc::sourceID (const std::string& key /*= "EventSelector"*/) const
1559{
1562 if (dp) {
1564 if (dh) {
1565 return dh->begin()->getToken()->dbID().toString();
1566 }
1567 }
1568 return "";
1569}
1570
1571
1573// Retrieve a list of collections from Transient Store with no Key.
1574// const version
1577 SG::detail::IteratorBase& cibegin,
1578 SG::detail::IteratorBase& ciend) const
1579{
1583
1584 if (!(m_pStore->pRange(clid,first,end)).isSuccess()) {
1585 std::string typnam;
1586 m_pCLIDSvc->getTypeNameOfID(clid, typnam).ignore();
1587 SG_MSG_DEBUG("retrieve(range): no object found of type {} (CLID {})",
1588 typnam, clid);
1589 }
1590
1591 (ciend.setState(end, end, true)).ignore();
1592
1593 if (!(cibegin.setState(first, end, true)).isSuccess()) {
1594 std::string typnam;
1595 m_pCLIDSvc->getTypeNameOfID(clid, typnam).ignore();
1596 SG_MSG_DEBUG("retrieve(range): Can't initialize iterator for object range "
1597 " of type {} (CLID {})",
1598 typnam, clid);
1599 return StatusCode::FAILURE;
1600 }
1601
1602 return StatusCode::SUCCESS;
1603}
1604
1605
1607 const std::string& key,
1608 CLID auxclid) const
1609{
1610 // If we already have the aux store (as should usually be the case), return
1611 // without taking out the SG lock. Otherwise, we can deadlock
1612 // if another thread is also trying to dereference a link to the aux store.
1613 // (Should _not_ be holding the SG lock when dereferencing the link!)
1614 if (ptr->hasStore()) return true;
1615
1617 SG_MSG_VERBOSE("called associateAux_impl for key " + key);
1618 // no Aux store set yet
1619 if (!ptr->hasStore()) {
1620 SG::DataProxy* dp = proxy (auxclid, key + "Aux.", true);
1621 if (dp) {
1622 if (!dp->isConst()) {
1624 if (pAux) {
1625 ptr->setStore (pAux);
1626 return true;
1627 }
1628 }
1629
1630 const SG::IConstAuxStore* pAux = SG::DataProxy_cast<SG::IConstAuxStore> (dp);
1631 if (pAux) {
1632 ptr->setStore (pAux);
1633 return true;
1634 }
1635 }
1636 }
1637 return false;
1638}
1639
1640
1642 const std::string& key,
1643 CLID auxclid) const
1644{
1646 SG_MSG_VERBOSE("called associateAux_impl for key " + key);
1647 // no Aux store set yet
1648 if (!ptr->hasStore()) {
1649 SG::DataProxy* dp = proxy (auxclid, key + "Aux.", true);
1650 if (dp) {
1651 if (!dp->isConst()) {
1653 if (pAux) {
1654 ptr->setStore (pAux);
1655 return true;
1656 }
1657 }
1658
1659 const SG::IConstAuxStore* pAux = SG::DataProxy_cast<SG::IConstAuxStore> (dp);
1660 if (pAux) {
1661 ptr->setStore (pAux);
1662 return true;
1663 }
1664 }
1665 }
1666 return false;
1667}
#define endmsg
Proxy for a group of Arenas. See Arena.h for an overview of the arena-based memory allocators.
Manage index tracking and synchronization of auxiliary data.
a static registry of CLID->typeName entries.
Helpers for checking error return status codes and reporting errors.
#define CHECK(...)
Evaluate an expression and check for errors.
Hold a pointer to the current event store.
This file contains the class definition for the DataHeader and DataHeaderElement classes.
uint32_t CLID
The Class ID type.
Interface for non-const operations on an auxiliary store.
Interface for const operations on an auxiliary store.
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
static Double_t sc
void SG_dump(SGImplSvc *sg)
These are intended to be easy to call from the debugger.
#define SG_MSG_WARNING(x,...)
#define SG_MSG_DEBUG(x,...)
#define SG_MSG_VERBOSE(x,...)
#define SG_MSG_INFO(x,...)
#define SG_MSG_ERROR(x,...)
Incident sent after a store is cleared.
Maintain a mapping of strings to 64-bit ints.
const char *const fmt
Define macros for attributes used to control the static checker.
#define ATLAS_THREAD_SAFE
Header file for AthHistogramAlgorithm.
static const std::type_info * CLIDToTypeinfo(CLID clid)
Translate between CLID and type_info.
Simple smart pointer for Gaudi-style refcounted objects.
T * get()
Get the pointer.
A non-templated base class for DataBucket, allows to access the transient object address as a void*.
virtual void * object()=0
virtual void relinquish()=0
Give up ownership of the DataBucket contents.
This class provides the layout for summary information stored for data written to POOL.
Definition DataHeader.h:123
std::vector< DataHeaderElement >::const_iterator begin() const
a resetable object (e.g.
Definition IResetable.h:15
SG::sgkey_t sgkey_t
Type of the keys.
Definition IStringPool.h:34
The Athena Transient Store API.
Definition SGImplSvc.h:107
virtual SG::DataProxy * proxy(const void *const pTransient) const override final
get proxy for a given data object address in memory
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.
void addAutoSymLinks(const std::string &key, CLID clid, SG::DataProxy *dp, const std::type_info *tinfo, bool warn_nobib=true)
Add automatically-made symlinks for DP.
void setStoreID(StoreID::type id)
set store ID. request forwarded to DataStore:
StatusCode t2pRegister(const void *const pTrans, SG::DataProxy *const pPers)
forwarded to DataStore
virtual ~SGImplSvc() override final
Standard Destructor.
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...
virtual void boundHandle(IResetable *handle) override final
Tell the store that a proxy has been bound to a handle.
virtual sgkey_t stringToKey(const std::string &str, CLID clid) override final
Find the key for a string/CLID pair.
virtual StoreID::type storeID() const override
get store ID. request forwarded to DataStore:
StatusCode remove(const void *pObject)
Remove pObject, will remove its proxy if not reset only.
virtual void handle(const Incident &) override final
triggered by Incident service
SG::DataProxy * locatePersistent(const SG::TransientAddress *tAddr, bool checkValid=false) const
virtual std::vector< const SG::DataProxy * > proxies() const override final
return the list of all current proxies in store
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 loadEventProxies()
load proxies at begin event
void keys(const CLID &id, std::vector< std::string > &vkeys, bool includeAlias=false, bool onlyValid=true)
provide list of all StoreGate keys associated with an object.
SG::DataStore * store()
SG::RemapImpl * m_remap_impl
Definition SGImplSvc.h:639
int m_slotNumber
The Hive slot number for this store, or -1 if this isn't a Hive store.
Definition SGImplSvc.h:645
ServiceHandle< IProxyProviderSvc > m_pPPSHandle
Definition SGImplSvc.h:614
virtual StatusCode finalize() override final
Service finalization.
std::map< std::thread::id, std::vector< IResetable * > > m_newBoundHandles
Keep track of proxies bound since the last call to commitNewDataObjects or clearStore.
Definition SGImplSvc.h:654
virtual SG::SourceID sourceID(const std::string &key="EventSelector") const override
Return the metadata source ID for the current event slot.
StatusCode setConst(const void *pointer)
prevent downstream clients from modifying the pointed-at dobj
virtual StatusCode createObj(IConverter *cvt, IOpaqueAddress *addr, DataObject *&refpObject) override
Call converter to create an object, with locking.
bool m_DumpStore
Dump Property flag: triggers dump() at EndEvent.
Definition SGImplSvc.h:625
bool m_ActivateHistory
Activate the history service.
Definition SGImplSvc.h:626
CLID clid(const std::string &key) const
Retrieve the main CLID of the object recorded in StoreGate with the given "key" WARNING: slow!
void msg_update_handler(Gaudi::Details::PropertyBase &outputLevel)
callback for output level property
SG::StringPool m_stringpool
Definition SGImplSvc.h:637
virtual StatusCode start() override final
Service start.
mutex_t m_mutex
Definition SGImplSvc.h:658
std::string createKey(const CLID &dataID)
creates a key internally if none specified by client
StatusCode setAlias(const void *p2BAliased, const std::string &aliasKey)
make an alias to a DataObject (provide only valid pointer)
bool m_DumpArena
DumpArena Property flag : trigger m_arena->report() at clearStore.
Definition SGImplSvc.h:627
StatusCode removeProxy(SG::DataProxy *proxy, const void *pTrans, bool forceRemove=false)
remove proxy from store, unless it is reset only.
void remap_impl(sgkey_t source, sgkey_t target, off_t index_offset)
Declare a remapping.
virtual void registerKey(sgkey_t key, const std::string &str, CLID clidid) override final
Remember an additional mapping from key to string/CLID.
StatusCode addSymLink(const CLID &linkid, SG::DataProxy *dp)
SG::Arena m_arena
Allocation arena to associate with this store.
Definition SGImplSvc.h:642
virtual StatusCode clearStore(bool forceRemove=false) override final
clear DataStore contents: called by the event loop mgrs
bool isSymLinked(const CLID &linkID, SG::DataProxy *dp)
std::lock_guard< mutex_t > lock_t
Definition SGImplSvc.h:657
IProxyProviderSvc * m_pPPS
Definition SGImplSvc.h:617
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 void commitNewDataObjects() override final
Reset handles added since the last call to commit.
virtual StatusCode stop() override final
Service stop.
void t2pRemove(const void *const pTrans)
forwarded to DataStore
virtual StatusCode addToStore(CLID id, SG::DataProxy *proxy) override final
Raw addition of a proxy to the store.
SG::DataStore * m_pStore
Definition SGImplSvc.h:621
StatusCode record_HistObj(const CLID &id, const std::string &key, const std::string &store, bool allowMods, bool resetOnly=true)
virtual const std::string * keyToString(sgkey_t key) const override final
Find the string corresponding to a given key.
void clearProxyPayload(SG::DataProxy *)
use to reset a proxy (clearing the data object it contains) Unlike DataProxy::reset this method corre...
StatusCode removeDataAndProxy(const void *pObject)
Remove pObject and its proxy no matter what.
mutex_t m_stringPoolMutex
Definition SGImplSvc.h:660
SG::DataProxy * setupProxy(const CLID &dataID, const std::string &gK, DataObject *pDObj, bool allowMods, bool resetOnly)
try to locate a proxy or create it if needed
std::vector< CLID > clids() const
Return all CLIDs in the store.
std::list< DataObject * > m_trash
The Recycle Bin.
Definition SGImplSvc.h:622
ServiceHandle< IHistorySvc > m_pHistorySvc
Definition SGImplSvc.h:619
StatusCode symLink(const CLID id, const std::string &key, const CLID linkid)
make a soft link to the object pointed by id/key
void releaseObject(const CLID &id, const std::string &key)
release object held by proxy, if any.
IStringPool::sgkey_t sgkey_t
Definition SGImplSvc.h:307
ServiceHandle< IIOVSvc > m_pIOVSvc
get the IOVSvc "just in time" (breaks recursion at initialize)
Definition SGImplSvc.h:633
void makeCurrent()
The current store is becoming the active store.
SGImplSvc(const SGImplSvc &)=delete
int m_numSlots
The total number of slots. 1 if this isn't a Hive store.
Definition SGImplSvc.h:648
bool mergeStringPool(const SGImplSvc &other)
Merge the string pool from another store into this one.
DataObject * accessData(const CLID &id) const
find proxy and access its data. Returns 0 to flag failure
void recycle(DataObject *pBadDObj)
put a bad (unrecordable) dobj away
virtual StatusCode reinitialize() override final
Service reinitialization.
bool m_storeLoaded
FIXME hack needed by loadEventProxies.
Definition SGImplSvc.h:635
virtual SG::DataProxy * proxy_exact(SG::sgkey_t sgkey) const override final
Get proxy given a hashed key+clid.
ServiceHandle< IClassIDSvc > m_pCLIDSvc
Definition SGImplSvc.h:611
bool transientContains(const CLID id, const std::string &key) const
Look up a transient data object in TDS only by CLID.
ServiceHandle< IIncidentSvc > m_pIncSvc
property
Definition SGImplSvc.h:624
std::string dump() const
dump objects in store.
StatusCode addAlias(const std::string &aliasKey, SG::DataProxy *dp)
bool contains(const CLID id, const std::string &key) const
Look up a keyed object in TDS by CLID.
mutex_t m_remapMutex
Definition SGImplSvc.h:659
void setSlotNumber(int slot, int numSlots)
Set the Hive slot number for this store.
StatusCode retrieve(CLID clid, SG::detail::IteratorBase &cibegin, SG::detail::IteratorBase &ciend) const
Retrieve all objects of type T: returns an SG::ConstIterator range.
virtual void unboundHandle(IResetable *handle) override final
Tell the store that a handle has been unbound from a proxy.
SG::DataProxy * transientProxy(const CLID &id, const std::string &key) const
get proxy with given id and key.
bool associateAux_impl(SG::AuxVectorBase *ptr, const std::string &key, CLID auxclid) const
virtual StatusCode initialize() override final
Service initialization.
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
SG::DataProxy * record_impl(DataObject *obj, const std::string &key, const void *const raw_ptr, bool allowMods, bool resetOnly, bool allowOverwrite, const std::type_info *tinfo)
real recording of an object with a key, allow possibility of specifying const-access
void emptyTrash()
throw away bad objects
ServiceHandle< IConversionSvc > m_pDataLoader
Definition SGImplSvc.h:612
Proxy for a group of Arenas.
Definition ArenaHeader.h:54
static ArenaHeader * defaultHeader()
Return the global default Header instance.
Manage index tracking and synchronization of auxiliary data.
The non-template portion of the BaseInfo implementation.
static const BaseInfoBase * find(CLID clid)
Find the BaseInfoBase instance for clid.
Definition BaseInfo.cxx:587
const std::vector< CLID > & get_bases() const
Return the class IDs of all known bases of T (that have class IDs).
Definition BaseInfo.cxx:307
std::vector< CLID > get_copy_conversions() const
Return known copy conversions.
Definition BaseInfo.cxx:470
bool transientID(CLID id) const
return the list of transient IDs (primary or symLinked):
void reset(bool hard=false)
Other methods of DataProxy (not in Interface IRegistry):
DataObject * accessData()
Access DataObject on-demand using conversion service.
TransientAddress::TransientClidSet CLIDCont_t
Definition DataProxy.h:54
Hold DataProxy instances associated with a store.
int typeCount(const CLID &id) const
Count number of object of a given type in store.
virtual StoreID::type storeID() const override
void keys(const CLID &id, std::vector< std::string > &vkeys, bool includeAlias, bool onlyValid)
StoreMap::const_iterator ConstStoreIterator
void setStoreID(StoreID::type id)
const std::vector< DataProxy * > & proxies() const
All proxies managed by this store.
StatusCode tRange(ConstStoreIterator &f, ConstStoreIterator &e) const
Return an iterator over the StoreMap:
Interface for non-const operations on an auxiliary store.
Definition IAuxStore.h:51
Implementation class, not to be used directly Iterates over valid proxies in the range.
Definition SGIterator.h:42
StatusCode setState(SG::ConstProxyIterator itr, SG::ConstProxyIterator itrEnd, bool isConst)
Reset state of the iterator.
@ EVENT_STORE
Definition StoreID.h:26
@ DETECTOR_STORE
Definition StoreID.h:27
static StoreID::type findStoreID(const std::string &storeName)
Definition StoreID.cxx:21
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:132
void setProxyDictInEventContext(IProxyDict *sg)
Update the IProxyDict in the current EventContext.
Forward declaration.
DATA * DataProxy_cast(DataProxy *proxy)
cast the proxy into the concrete data object it proxies
AuxElement(SG::AuxVectorData *container, size_t index)
Base class for elements of a container that can have aux data.
CxxUtils::RefCountedPtr< T > DataObjectSharedPtr
uint32_t sgkey_t
Type used for hashed StoreGate key+CLID pairs.
Definition sgkey_t.h:32
ProxyMap::const_iterator ConstProxyIterator
Definition ProxyMap.h:24
DataObject * asStorable(SG::DataObjectSharedPtr< T > pObject)
std::unordered_map< sgkey_t, T > SGKeyMap
A map using sgkey_t as a key.
Definition sgkey_t.h:93
void * ptr(T *p)
Definition SGImplSvc.cxx:75
void print(std::FILE *stream, std::format_string< Args... > fmt, Args &&... args)
Definition SGImplSvc.cxx:71
Some out-of-line helpers for ExtendedEventContext.
SGKeyMap< remap_t > remap_map_t
Definition SGImplSvc.cxx:93
remap_map_t m_remaps
Definition SGImplSvc.cxx:94
IStringPool::sgkey_t sgkey_t
Definition SGImplSvc.cxx:87