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"
50
51// StoreGateSvc. must come before SGImplSvc.h
54#include "SGTools/DataStore.h"
55
56using std::setw;
57using std::hex;
58using std::dec;
59using std::endl;
60using std::ends;
61using std::pair;
62using std::string;
63using std::vector;
64
65using SG::DataProxy;
66using SG::DataStore;
68
69// Helpers for debug formatting
70// std::print implementation to be replaced when C++ 23 is available
71namespace dbg {
72template <class... Args> void print(std::FILE* stream, std::format_string<Args...> fmt, Args&&... args) {
73 std::fputs(std::format(fmt, std::forward<Args>(args)...), stream);
74}
75
76template <class T> void* ptr(T* p) { return static_cast<void*>(p); }
77}
78
80// Remapping implementation.
81
82
83namespace SG {
84
85
97
98
99} // namespace SG
100
101
104SGImplSvc::SGImplSvc(const string& name,ISvcLocator* svc)
105 : base_class(name, svc),
106 m_pCLIDSvc("ClassIDSvc", name),
107 m_pDataLoader("EventPersistencySvc", name),
108 m_pPPSHandle("ProxyProviderSvc", name),
109 m_pPPS(nullptr),
110 m_pHistorySvc("HistorySvc", name),
111 m_pStore(new DataStore(*this)),
112 m_pIncSvc("IncidentSvc", name),
113 m_DumpStore(false),
114 m_ActivateHistory(false),
115 m_DumpArena(false),
116 m_pIOVSvc("IOVSvc", name),
117 m_storeLoaded(false),
118 m_remap_impl (new SG::RemapImpl),
119 m_arena (name),
120 m_slotNumber(-1),
121 m_numSlots(1)
122{
123 //our properties
124 declareProperty("ProxyProviderSvc", m_pPPSHandle);
125 declareProperty("Dump", m_DumpStore);
126 declareProperty("ActivateHistory", m_ActivateHistory);
127 declareProperty("DumpArena", m_DumpArena);
128 //StoreGateSvc properties
129 declareProperty("IncidentSvc", m_pIncSvc);
130 //add handler for Service base class property
131 m_outputLevel.declareUpdateHandler(&SGImplSvc::msg_update_handler, this);
132
134 header->addArena (&m_arena);
135}
136
137
141 header->delArena (&m_arena);
142
143 delete m_pStore;
144 delete m_remap_impl;
145}
146
150
151 SG_MSG_VERBOSE ("Initializing {}", name());
152
153 CHECK( Service::initialize() );
154
155 if (!m_pStore)
156 m_pStore = new DataStore (*this);
157 if (!m_remap_impl)
159
160 //properties accessible from now on
161
163 // If this is the default event store (StoreGateSvc), then declare
164 // our arena as the default for memory allocations.
165 if (this->storeID() == StoreID::EVENT_STORE) {
166 m_arena.makeCurrent();
167 SG::CurrentEventStore::setStore (this);
169 }
170 // set up the incident service:
171 if (!(m_pIncSvc.retrieve()).isSuccess()) {
172 SG_MSG_ERROR ("Could not locate IncidentSvc ");
173 return StatusCode::FAILURE;
174 }
175
176 // We explicitly do not retrieve m_pIOVSvc and rely on retrieval
177 // on first use to avoid an initialization loop here.
178
179 CHECK( m_pDataLoader.retrieve() );
180 CHECK( m_pCLIDSvc.retrieve() );
181
182 if (!m_pPPSHandle.empty()) {
183 CHECK( m_pPPSHandle.retrieve() );
185 }
186
187 if ( m_pPPS && (m_pPPS->preLoadProxies(*m_pStore)).isFailure() )
188 {
189 SG_MSG_DEBUG(" Failed to preLoad proxies");
190 return StatusCode::FAILURE;
191 }
192
193 // Get hold of History Service
194 if (m_ActivateHistory) {
195 CHECK( m_pHistorySvc.retrieve() );
196 }
197
198 return StatusCode::SUCCESS;
199}
200
201StatusCode SGImplSvc::start() {
202
203 SG_MSG_VERBOSE ("Start {}", name());
204 /*
205 // This will need regFcn clients to be updated first.
206 if ( 0 == m_pPPS || (m_pPPS->preLoadProxies(*m_pStore)).isFailure() ) {
207 SG_MSG_DEBUG (" Failed to preLoad proxies");
208 return StatusCode::FAILURE;
209 }
210 */
211
212 return StatusCode::SUCCESS;
213}
214
215StatusCode SGImplSvc::stop() {
216
217 SG_MSG_VERBOSE ("Stop {}", name());
218 //HACK ALERT: ID event store objects refer to det store objects
219 //by setting an ad-hoc priority for event store(s) we make sure they are finalized and hence cleared first
220 // see e.g. https://savannah.cern.ch/bugs/index.php?99993
221 if (store()->storeID() == StoreID::EVENT_STORE) {
222 ISvcManager* pISM(dynamic_cast<ISvcManager*>(serviceLocator().get()));
223 if (!pISM)
224 return StatusCode::FAILURE;
225 pISM->setPriority(name(), pISM->getPriority(name())+1).ignore();
226 SG_MSG_VERBOSE ("stop: setting service priority to {} so that event stores get finalized and cleared before other stores",
227 pISM->getPriority(name()));
228 }
229 return StatusCode::SUCCESS;
230}
231
233void SGImplSvc::handle(const Incident &inc) {
234
235 if (inc.type() == "EndEvent") {
236 if (m_DumpStore) {
237 SG_MSG_DEBUG("Dumping StoreGate Contents");
238 SG_MSG_INFO ("\n{}\n", dump());
239 }
240 }
241}
242
245 StatusCode sc(StatusCode::SUCCESS);
246 //FIXME this should probably be dealt with by the providers
247 if (0 != m_pPPS && !m_storeLoaded) {
248 m_storeLoaded = true;
249 sc=m_pPPS->loadProxies(*m_pStore);
250#ifdef DEBUG_SGIMPL
251 dbg::print(stderr, "SGImplSvc::loadEventProxies() LOADED PROXIES on {}\n", name());
252 }
253 else {
254 dbg::print(stderr, "SGImplSvc::loadEventProxies() PROXIES ALREADY LOADED on {}\n", name());
255#endif
256 }
257 return sc;
258}
259
261// Create a key for a type (used if the client has not specified a key)
262string SGImplSvc::createKey(const CLID& id)
263{
264 return std::to_string(m_pStore->typeCount(id) + 1);
265}
266
267// clear store
268StatusCode SGImplSvc::clearStore(bool forceRemove)
269{
270#ifdef DEBUG_SGIMPL
271 dbg::print(stderr, "SGImplSvc::clearStore(forceRemove={}) on {}\n", forceRemove, name());
272#endif
273 {
274 if (m_DumpArena) {
275 std::ostringstream s;
276 m_arena.report(s);
277 SG_MSG_INFO ("Report for Arena: {}\n{}", m_arena.name(), s.str());
278 }
279 }
280 {
282 emptyTrash();
283 for (auto& p : m_newBoundHandles)
284 p.second.clear();
285 assert(m_pStore);
286 SG_MSG_DEBUG ("Clearing store with forceRemove={}", forceRemove);
287 bool hard_reset = (m_numSlots > 1);
288 m_pStore->clearStore(forceRemove, hard_reset, &msgStream(MSG::DEBUG));
289 m_storeLoaded=false; //FIXME hack needed by loadEventProxies
290 }
291 {
292 lock_t remap_lock (m_remapMutex);
293 m_remap_impl->m_remaps.clear();
294 m_arena.reset();
295 }
296
297 return StatusCode::SUCCESS;
298}
299
302 SG_MSG_VERBOSE ("Finalizing {}", name());
303
304 // Incident service may not work in finalize.
305 // Clear this, so that we won't try to send an incident from clearStore.
306 (m_pIncSvc.release()).ignore();
307
308 const bool FORCEREMOVE(true);
309 clearStore(FORCEREMOVE).ignore();
310
311 m_stringpool.clear();
312 delete m_pStore;
313 m_pStore = nullptr;
314 delete m_remap_impl;
315 m_remap_impl = 0;
316 m_arena.erase();
317
318 return Service::finalize();
319}
320
323 SG_MSG_VERBOSE ("Reinitializing {}", name());
324 const bool FORCEREMOVE(true);
325 clearStore(FORCEREMOVE).ignore();
326 //not in v20r2p2! return Service::reinitialize();
327 return StatusCode::SUCCESS;
328}
329
332// add proxy (with IOpaqueAddress that will later be retrieved from P)
334StatusCode SGImplSvc::recordAddress(const std::string& skey,
336 bool clearAddressFlag,
337 const std::vector<CLID>& bases)
338{
340 assert(0 != pAddress);
341 CLID dataID = pAddress->clID();
342
343 if (dataID == 0)
344 {
345 SG_MSG_WARNING ("recordAddress: Invalid Class ID found in IOpaqueAddress @{}. IOA will not be recorded",
346 static_cast<void*>(pAddress.get()));
347 return StatusCode::FAILURE;
348 }
349
350 //do not overwrite a persistent object
351 if (m_pPPS) {
352 DataProxy* dp = m_pStore->proxy (dataID, skey);
353 if (!dp) {
354 dp = m_pPPS->retrieveProxy(dataID, skey, *m_pStore);
355 }
356 if (dp && dp->provider()) {
357 std::string clidTypeName;
358 m_pCLIDSvc->getTypeNameOfID(dataID, clidTypeName).ignore();
359 SG_MSG_WARNING ("recordAddress: failed for key={}, type (CLID {})\n"
360 " there is already a persistent version of this object. Will not record a duplicate! ",
361 skey, clidTypeName, dataID);
362 return StatusCode::FAILURE;
363 }
364 }
365
366 // Check if a key already exists
367 DataProxy* dp = m_pStore->proxy_exact(dataID, skey);
368 if (0 == dp && 0 != m_pPPS) {
369 dp = m_pPPS->retrieveProxy(dataID, skey, *m_pStore);
370 }
371
372 // Now treat the various cases:
373 if (0 == dp)
374 {
375 // create the proxy object and register it
376 dp = new DataProxy (TransientAddress (dataID, skey,
377 std::move(pAddress),
378 clearAddressFlag),
379 m_pDataLoader.get(), true, true);
380 m_pStore->addToStore(dataID, dp).ignore();
381
382 addAutoSymLinks (skey, dataID, dp, 0, false);
383
384 // Add extra bases.
385 for (CLID b : bases) {
386 if (addSymLink (b, dp).isFailure()) {
387 warning() << std::format ("Can't add extra base {} for object {}/{}",
388 b, dataID, skey) << endmsg;
389 }
390 }
391 }
392 else if ((0 != dp) && (0 == dp->address()))
393 // Note: intentionally not checking dp->isValidAddress()
394 {
395 // Update proxy with IOpaqueAddress
396 dp->setAddress(std::move(pAddress));
397 }
398 else
399 {
400 string errType;
401 m_pCLIDSvc->getTypeNameOfID(dataID, errType).ignore();
402 SG_MSG_WARNING ("recordAddress: preexisting proxy @{} with non-NULL IOA found for key type {} ({}). \n"
403 "Cannot record IOpaqueAddress @{}",
404 static_cast<void*>(dp), skey, errType, dataID,
405 static_cast<void*>(pAddress.get()));
406 return StatusCode::FAILURE;
407 }
408
409 return StatusCode::SUCCESS;
410
411}
412
415// add proxy (with IOpaqueAddress that will later be retrieved from P)
418 bool clearAddressFlag,
419 const std::vector<CLID>& bases)
420{
422 assert(0 != pAddress);
423
424 CLID dataID = pAddress->clID();
425
426 string gK = (pAddress->par())[1]; // transient name by convention
427 if (gK.empty()) gK = (pAddress->par())[0]; // FIXME backward compatibility
428 if (gK.empty()) gK = createKey(dataID);
429
430 return this->recordAddress(gK, std::move(pAddress), clearAddressFlag, bases);
431}
432
434 const string& gK,
435 DataObject* pDObj,
436 bool allowMods,
437 bool resetOnly) {
438 // locate the proxy
439 DataProxy* dp = m_pStore->proxy_exact(dataID, gK);
440
441 if (0 != dp) { //proxy found
442 if (0 != dp->object())
443 {
444 // Case 0: duplicated proxy
445 SG_MSG_WARNING (" setupProxy:: error setting up proxy for key {} and clid {}\n"
446 " Pre-existing valid DataProxy @{} found in Store for key {} with clid {}",
447 gK, dataID,
448 static_cast<void*>(dp),
449 dp->object()->name(),
450 dp->object()->clID());
451 recycle(pDObj); // commit this object to trash
452 dp = 0;
453 } else {
454 // Case 1: Proxy found... if not valid, update it:
455 dp->setObject(pDObj);
456 if (!allowMods) dp->setConst();
457 }
458 } else {
459 // Case 2: No Proxy found:
460 dp = new DataProxy(pDObj,
461 TransientAddress(dataID, gK),
462 !allowMods, resetOnly);
463 if (!(m_pStore->addToStore(dataID, dp).isSuccess())) {
464 SG_MSG_WARNING (" setupProxy:: could not addToStore proxy @{}",
465 static_cast<void*>(dp));
466 recycle(pDObj); // commit this object to trash
467 delete dp;
468 dp = 0;
469 }
470 }
471 return dp;
472}
473
480
482{
484 return store()->storeID();
485}
486
487
488void
489SGImplSvc::keys(const CLID& id, std::vector<std::string>& vkeys,
490 bool includeAlias, bool onlyValid)
491
492{
494 return store()->keys(id, vkeys, includeAlias, onlyValid);
495}
496
497
498bool SGImplSvc::isSymLinked(const CLID& linkID, DataProxy* dp)
499{
500 return (0 != dp) ? dp->transientID(linkID) : false;
501}
502
504// Dump Contents in store:
505string SGImplSvc::dump() const
506{
508 auto out_buffer = std::string{};
509 auto out = std::back_inserter(out_buffer);
510 const std::string me = name();
511 std::format_to(out, "{}: <<<<<<<<<<<<<<<<< Data Store Dump >>>>>>>>>>>>>>> \n", me);
512 std::format_to(out, "{}: SGImplSvc()::dump() which is {} \n", me, m_storeLoaded ? "LOADED" : "NOT LOADED");
513
514 DataStore::ConstStoreIterator s_iter, s_end;
515 store()->tRange(s_iter, s_end).ignore();
516
517 for (; s_iter != s_end; ++s_iter)
518 {
519
520 CLID id = s_iter->first;
521 int nProxy = store()->typeCount(id);
522 std::string tname;
523 m_pCLIDSvc->getTypeNameOfID(id, tname).ignore();
524 std::format_to(out, "{}: Found {} {} for ClassID {} ({}): \n", me, nProxy, ((nProxy == 1) ? "proxy" : "proxies"), id, tname);
525
526 // loop over each type:
527 SG::ConstProxyIterator p_iter = (s_iter->second).begin();
528 SG::ConstProxyIterator p_end = (s_iter->second).end();
529
530 while (p_iter != p_end) {
531 const DataProxy& dp(*p_iter->second);
532 std::format_to(out, "{}: flags: ({:7s}, {:8s}, {:6s}) --- data: {:10p} --- key: {}\n", me,
533 (dp.isValid() ? "valid" : "INVALID"),
534 (dp.isConst() ? "locked" : "UNLOCKED"),
535 (dp.isResetOnly() ? "reset" : "DELETE"),
536 dbg::ptr(dp.object()), p_iter->first);
537 ++p_iter;
538 }
539 }
540 std::format_to(out, "{}: <<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>> \n", me);
541 return out_buffer;
542}
543
544DataStore*
546{
547 return m_pStore;
548}
549
550const DataStore*
552{
553 return m_pStore;
554}
555
556
558// Make a soft link to the object with key
560StatusCode SGImplSvc::symLink(const void* pObject, CLID linkID)
561{
563 SG::DataProxy* dp(proxy(pObject));
564
565 // if symLink already exists, just return success
566 return isSymLinked(linkID,dp) ?
567 StatusCode::SUCCESS :
568 addSymLink(linkID,dp);
569}
570
571StatusCode SGImplSvc::symLink(const CLID id, const std::string& key, const CLID linkID)
572{
574 SG::DataProxy* dp(proxy(id, key, false));
575 // if symLink already exists, just return success
576 return isSymLinked(linkID,dp) ?
577 StatusCode::SUCCESS :
578 addSymLink(linkID,dp);
579}
580
581
582StatusCode
584{
585 if (0 == dp) {
586 SG_MSG_WARNING ("addSymLink: no target DataProxy found. Sorry, can't link to a non-existing data object");
587 return StatusCode::FAILURE;
588 }
589 StatusCode sc = m_pStore->addSymLink(linkid, dp);
590
591 // If the symlink is a derived->base conversion, then we may have
592 // a different transient pointer for the symlink.
593 if (sc.isSuccess() && dp->object()) {
594 void* baseptr = SG::DataProxy_cast (dp, linkid);
595 if (baseptr)
596 this->t2pRegister (baseptr, dp).ignore();
597 }
598 return sc;
599}
600
601
602StatusCode SGImplSvc::setAlias(const void* pObject, const std::string& aliasKey)
603{
605
606 SG::DataProxy* dp(0);
607 dp = proxy(pObject);
608 if (0 == dp) {
609 SG_MSG_ERROR ("setAlias: problem setting alias {}\n"
610 "DataObject does not exist, record before setting alias.",
611 aliasKey);
612 return StatusCode::FAILURE;
613 }
614
615 StatusCode sc = addAlias(aliasKey, dp);
616 if (sc.isFailure()) {
617 SG_MSG_ERROR ("setAlias: problem setting alias {}\n"
618 "DataObject does not exist, record before setting alias.",
619 aliasKey);
620 return StatusCode::FAILURE;
621 }
622
623 return StatusCode::SUCCESS;
624}
625
626
628 const std::string& key, const std::string& aKey)
629{
631
632 SG::DataProxy* dp(0);
633 dp = proxy(clid, key);
634 if (0 == dp) {
635 error() << "setAlias: problem setting alias "
636 << std::string(aKey) << '\n'
637 << "DataObject does not exist, record before setting alias."
638 << endmsg;
639 return StatusCode::FAILURE;
640 }
641
642 StatusCode sc = addAlias(aKey, dp);
643 if (sc.isFailure()) {
644 error() << "setAlias: problem setting alias "
645 << (std::string)aKey << '\n'
646 << "DataObject does not exist, record before setting alias."
647 << endmsg;
648 return StatusCode::FAILURE;
649 }
650
651 return StatusCode::SUCCESS;
652}
653
654StatusCode SGImplSvc::setAlias(SG::DataProxy* proxy, const std::string& aliasKey)
655{
656 return addAlias( aliasKey, proxy );
657}
658
659StatusCode
660SGImplSvc::addAlias(const std::string& aliasKey, DataProxy* proxy)
661{
662 if (0 == proxy) {
663 SG_MSG_WARNING ("addAlias: no target DataProxy given, Cannot alias to a non-existing object");
664 return StatusCode::FAILURE;
665 }
666
667 // add key to proxy and to ProxyStore
668 return m_pStore->addAlias(aliasKey, proxy);
669}
670
671int SGImplSvc::typeCount(const CLID& id) const
672{
674 return m_pStore->typeCount(id);
675}
676
677
678bool
679SGImplSvc::contains(const CLID id, const std::string& key) const
680{
681 try {
682 return (0 != proxy(id, key, true));
683 } catch(...) { return false; }
684}
685
686
687bool
688SGImplSvc::transientContains(const CLID id, const std::string& key) const
689{
690 try {
691 return (0 != transientProxy(id, key));
692 } catch(...) { return false; }
693}
694
695
696DataProxy*
697SGImplSvc::proxy(const void* const pTransient) const
698{
699 // No lock needed here --- the T2pmap held by DataStore has its own locking
700 // (and we were seeing contention here).
701 //lock_t lock (m_mutex);
702 return m_pStore->locatePersistent(pTransient);
703}
704
705DataProxy*
706SGImplSvc::proxy(const CLID& id) const
707{
708 return proxy(id, false);
709}
710
711DataProxy*
712SGImplSvc::proxy(const CLID& id, bool checkValid) const
713{
714 DataProxy* dp = nullptr;
715 {
717 dp = m_pStore->proxy(id);
718 if (0 == dp && 0 != m_pPPS) {
720 dp = m_pPPS->retrieveProxy(id, string("DEFAULT"), *pStore);
721 }
722 }
724 // Be sure to release the lock before this.
725 // isValid() may call back to the store, so we could otherwise deadlock..
726 if (checkValid && 0 != dp) {
727 // FIXME: For keyless retrieve, this checks only the first instance
728 // of the CLID in store. If that happens to be invalid, but the second
729 // is valid - this does not work (when checkValid is requested).
730 return dp->isValid() ? dp : 0;
731 }
732 return dp;
733}
734
735DataProxy*
736SGImplSvc::proxy(const CLID& id, const string& key) const
737{
738 return proxy(id, key, false);
739}
740
742SGImplSvc::proxy(const CLID& id, const string& key, bool checkValid) const
743{
744 DataProxy* dp = nullptr;
745 {
747 dp = m_pStore->proxy(id, key);
748#ifdef DEBUG_SGIMPL
749 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");
750#endif
751 if (0 == dp && 0 != m_pPPS) {
753 dp = m_pPPS->retrieveProxy(id, key, *pStore);
754#ifdef DEBUG_SGIMPL
755 if (!dp) dbg::print(stderr, "::SGImplSvc::proxy(name={}, key={}): data proxy is still null\n", this->name(), key);
756#endif
757 }
758 }
759 // Be sure to release the lock before this.
760 // isValid() may call back to the store, so we could otherwise deadlock..
761 if (checkValid && 0 != dp && !(dp->isValid())) {
762 dp = 0;
763 }
764 return dp;
765}
766
767
774{
776 return m_pStore->addToStore (id, proxy);
777}
778
779
801 const std::string& key,
802 bool allowMods,
803 bool returnExisting)
804{
806 const void* raw_ptr = obj.get();
807 const std::type_info* tinfo = nullptr;
808
809 if (DataBucketBase* bucket = dynamic_cast<DataBucketBase*> (obj.get())) {
810 raw_ptr = bucket->object();
811 tinfo = &bucket->tinfo();
812 }
813
814 if (returnExisting) {
815 SG::DataProxy* proxy = this->proxy (obj->clID(), key);
816 if (proxy && proxy->isValid()) return proxy;
817
818 // Look for the same object recorded under a different key/clid.
819 proxy = this->proxy (raw_ptr);
820 if (proxy && proxy->isValid()) {
821 if (proxy->transientID (obj->clID())) {
822 // CLID matches. Make an alias.
823 if (addAlias (key, proxy).isFailure()) {
824 CLID clid = proxy->clID();
825 std::string clidTypeName;
826 m_pCLIDSvc->getTypeNameOfID(clid, clidTypeName).ignore();
827 SG_MSG_WARNING ("SGImplSvc::recordObject: addAlias fails for object {} [{}] {} and new key {}",
828 clid, clidTypeName, proxy->name(), key);
829 proxy = nullptr;
830 }
831 }
832
833 else if (key == proxy->name() || proxy->hasAlias(key) > 0)
834 {
835 // key matches. Make a symlink.
836 if (addSymLink (obj->clID(), proxy).isFailure()) {
837 CLID clid = proxy->clID();
838 std::string clidTypeName;
839 m_pCLIDSvc->getTypeNameOfID(clid, clidTypeName).ignore();
840 CLID newclid = obj->clID();
841 std::string newclidTypeName;
842 m_pCLIDSvc->getTypeNameOfID(newclid, newclidTypeName).ignore();
843 SG_MSG_ERROR ("SGImplSvc::recordObject:"
844 " addSymLink fails for object {} [{}] {} and new clid {} [{}]",
845 clid, clidTypeName, proxy->name(),
846 newclid, newclidTypeName);
847 proxy = nullptr;
848 }
849 }
850
851 else {
852 CLID clid = proxy->clID();
853 std::string clidTypeName;
854 m_pCLIDSvc->getTypeNameOfID(clid, clidTypeName).ignore();
855 CLID newclid = obj->clID();
856 std::string newclidTypeName;
857 m_pCLIDSvc->getTypeNameOfID(newclid, newclidTypeName).ignore();
858 SG_MSG_ERROR ("SGImplSvc::recordObject:"
859 " existing object found with {} [{}] {} but neither"
860 " clid {} [{}] nor key {} match.",
861 clid, clidTypeName, proxy->name(),
862 newclid, newclidTypeName, key);
863 proxy = nullptr;
864 }
865
866 return proxy;
867 }
868 }
869
870 const bool resetOnly = true;
871 const bool noHist = false;
872 SG::DataProxy* proxy = nullptr;
873 if (this->typeless_record (obj.get(), key, raw_ptr,
874 allowMods, resetOnly, noHist, tinfo,
875 &proxy, true).isFailure())
876 {
877 return nullptr;
878 }
879 return proxy;
880}
881
882
887{
888 return m_pStore->proxy_exact_unlocked (sgkey, m_mutex);
889}
890
891
898void SGImplSvc::setSlotNumber (int slot, int numSlots)
899{
900 m_slotNumber = slot;
901 m_numSlots = numSlots;
902
904 header->setArenaForSlot (slot, &m_arena);
905}
906
907
908std::vector<const SG::DataProxy*>
910{
912 const std::vector<SG::DataProxy*>& proxies = store()->proxies();
913 std::vector<const SG::DataProxy*> ret (proxies.begin(), proxies.end());
914 return ret;
915}
916
917
918std::vector<CLID>
920{
922
923 using std::distance;
924 DataStore::ConstStoreIterator s_iter, s_end;
925 store()->tRange(s_iter, s_end).ignore();
926
927 std::vector<CLID> clids;
928 clids.reserve( distance( s_iter, s_end ) );
929
930 for (; s_iter != s_end; ++s_iter ) {
931 const CLID id = s_iter->first;
932 clids.push_back (id);
933 }
934
935 return clids;
936}
937
938
940SGImplSvc::transientProxy(const CLID& id, const string& key) const
941{
943 DataProxy* dp(m_pStore->proxy(id, key));
944 return ( (0 != dp && dp->isValidObject()) ? dp : 0 );
945}
946
947DataObject*
949{
951 DataProxy* theProxy(proxy(id, true));
952 return (0 == theProxy) ? 0 : theProxy->accessData();
953}
954
955DataObject*
956SGImplSvc::accessData(const CLID& id, const string& key) const
957{
959 DataProxy* theProxy(proxy(id, key, true));
960 return (0 == theProxy) ? 0 : theProxy->accessData();
961}
962
963bool
965 const std::string& keyA, const std::string& keyB )
966{
968 const bool checkValid = true;
969 DataProxy* a = proxy( id, keyA, checkValid );
970 DataProxy* b = proxy( id, keyB, checkValid );
971 if ( 0 == a || 0 == b ) { return false; }
972 DataObject* objA = a->accessData();
973 DataObject* objB = b->accessData();
974
975 if ( 0 == objA || 0 == objB ) { return false; }
976 // prevent 'accidental' release of DataObjects...
977 const unsigned int refCntA = objA->addRef();
978 const unsigned int refCntB = objB->addRef();
979 // in case swap is being specialized for DataObjects
980 using std::swap;
981 swap( objA, objB );
982 a->setObject( objA );
983 b->setObject( objB );
984 // and then restore old ref-count;
985 return ( (refCntA-1) == objA->release() &&
986 (refCntB-1) == objB->release() );
987}
988
989StatusCode
990SGImplSvc::typeless_record( DataObject* obj, const std::string& key,
991 const void* const raw_ptr,
992 bool allowMods, bool resetOnly, bool noHist)
993{
994 return typeless_record (obj, key, raw_ptr, allowMods, resetOnly, noHist, 0,
995 nullptr, true);
996}
997
998
999StatusCode
1000SGImplSvc::typeless_record( DataObject* obj, const std::string& key,
1001 const void* const raw_ptr,
1002 bool allowMods, bool resetOnly, bool noHist,
1003 const std::type_info* tinfo)
1004{
1005 return typeless_record (obj, key, raw_ptr, allowMods, resetOnly, noHist,tinfo,
1006 nullptr, true);
1007}
1008
1009
1010StatusCode
1011SGImplSvc::typeless_record( DataObject* obj, const std::string& key,
1012 const void* const raw_ptr,
1013 bool allowMods, bool resetOnly, bool noHist,
1014 const std::type_info* tinfo,
1015 SG::DataProxy** proxy_ret,
1016 bool noOverwrite)
1017{
1020 record_impl( obj, key, raw_ptr, allowMods, resetOnly, !noOverwrite, tinfo);
1021 if ( proxy == nullptr )
1022 return StatusCode::FAILURE;
1023 if (proxy_ret)
1024 *proxy_ret = proxy;
1025
1026 if ( !m_ActivateHistory || noHist ) {
1027 return StatusCode::SUCCESS;
1028 }
1029
1030 if ( store()->storeID() != StoreID::EVENT_STORE ) {
1031 return StatusCode::SUCCESS;
1032 } else {
1033 return record_HistObj( obj->clID(), key, name(), allowMods, resetOnly );
1034 }
1035}
1036
1037StatusCode
1039 DataObject* obj,
1040 const std::string& key,
1041 const void* const raw_ptr,
1042 bool allowMods,
1043 bool noHist,
1044 const std::type_info* tinfo)
1045{
1047 StatusCode sc(StatusCode::SUCCESS);
1048 SG::DataProxy* toRemove(proxy(clid, key, false));
1049 if (0 != toRemove) {
1050 toRemove->addRef();
1051 const bool FORCEREMOVE(true);
1052 sc =removeProxy(toRemove, (void*)0, FORCEREMOVE);
1053 }
1054 if (sc.isSuccess()) {
1055 const bool ALLOWOVERWRITE(true);
1056 const bool NORESET(false);
1057 if (record_impl( obj, key, raw_ptr, allowMods, NORESET, ALLOWOVERWRITE, tinfo) == nullptr)
1058 sc = StatusCode::FAILURE;
1059 else if ( m_ActivateHistory && noHist && store()->storeID() == StoreID::EVENT_STORE ) {
1060 sc = record_HistObj( obj->clID(), key, name(), allowMods, NORESET );
1061 }
1062 }
1063 //for detector store objects managed by IIOVSvc, replace the old proxy with the new one (#104311)
1064 if (toRemove && sc.isSuccess() && store()->storeID() == StoreID::DETECTOR_STORE) {
1065 sc = m_pIOVSvc->replaceProxy(toRemove, proxy(clid, key));
1066 }
1067 if (toRemove)
1068 toRemove->release();
1069 return sc;
1070}
1071
1073SGImplSvc::record_impl( DataObject* pDObj, const std::string& key,
1074 const void* const raw_ptr,
1075 bool allowMods, bool resetOnly, bool allowOverwrite,
1076 const std::type_info* tinfo)
1077{
1078 CLID clid = pDObj->clID();
1079 std::string rawKey(key);
1080 bool isVKey(SG::VersionedKey::isVersionedKey(key));
1081 if (isVKey) {
1082 //FIXME VersionedKeys will need to be handled more efficiently
1083 SG::VersionedKey vk(rawKey);
1084 DataProxy *dp(proxy(clid, vk.key()));
1085 if (dp) {
1086 //proxies primary key
1087 const std::string& pTAName(dp->name());
1088 //original key as versioned
1089 SG::VersionedKey primaryVK(pTAName);
1090
1091 //if the existing matching object has no version
1092 //create a versioned alias for the original unversioned key
1093 //so it will remain accessible
1094 if (!SG::VersionedKey::isVersionedKey(pTAName)) {
1095 if (!(this->addAlias(primaryVK.rawVersionKey(), dp)).isSuccess()) {
1096 SG_MSG_WARNING ("record_impl: Could not setup alias key {} for unversioned object {}",
1097 primaryVK.rawVersionKey(), pTAName);
1098 return nullptr;
1099 }
1100 }
1101 if (vk.isAuto()) {
1102 //make a new versioned key incrementing the existing version
1103 SG::VersionedKey newVK(primaryVK.key(), primaryVK.version()+1);
1104 //FIXME this will fail in a confusing way if version+1 is in use
1105 //FIXME need a better error message below, probably looking at all
1106 //FIXME aliases
1107 rawKey = newVK.rawVersionKey();
1108 }
1109 }
1110 }
1111 if (!allowOverwrite && m_pPPS) {
1112 //do not overwrite a persistent object
1113 DataProxy* dp = m_pStore->proxy (clid, rawKey);
1114 if (!dp) {
1115 dp = m_pPPS->retrieveProxy(clid, rawKey, *m_pStore);
1116 }
1117 if (dp && dp->provider()) {
1118 std::string clidTypeName;
1119 m_pCLIDSvc->getTypeNameOfID(clid, clidTypeName).ignore();
1120 SG_MSG_WARNING ("record_impl: you are recording an object with key {}, type {} (CLID {})\n"
1121 " There is already a persistent version of this object."
1122 " Recording a duplicate may lead to unreproducible results and it is deprecated.",
1123 rawKey, clidTypeName, clid);
1124 }
1125 }
1126 //now check whether raw_ptr has already been recorded
1127 //We need to do this before we create the bucket, the proxy etc
1128 SG::DataProxy* dp(proxy(raw_ptr));
1129 if (0 != dp) {
1130 std::string clidTypeName;
1131 m_pCLIDSvc->getTypeNameOfID(clid, clidTypeName).ignore();
1132 SG_MSG_WARNING ("record_impl: failed for key={}, type {} (CLID {})\n"
1133 " object @{} already in store with key={}. Will not record a duplicate!",
1134 rawKey, clidTypeName, clid, raw_ptr, dp->name());
1135 if (pDObj != dp->object()) {
1136 DataBucketBase* pDBB(dynamic_cast<DataBucketBase*>(pDObj));
1137 if (!pDBB) std::abort();
1138 pDBB->relinquish(); //don't own the data obj already recorded!
1139 }
1140 this->recycle(pDObj);
1141 return nullptr;
1142 }
1143
1144
1145 // setup the proxy
1146 dp = setupProxy( clid, rawKey, pDObj, allowMods, resetOnly );
1147 if ( 0 == dp ) {
1148 std::string clidTypeName;
1149 m_pCLIDSvc->getTypeNameOfID(clid, clidTypeName).ignore();
1150 SG_MSG_WARNING ("record_impl: Problem setting up the proxy for object @{}\n"
1151 " recorded with key {} of type {} (CLID {}) in DataObject @{}",
1152 raw_ptr, rawKey, clidTypeName, clid,
1153 static_cast<void*>(pDObj));
1154
1155 return nullptr;
1156 }
1157
1158 // record in t2p:
1159 if ( !(this->t2pRegister( raw_ptr, dp )).isSuccess() ) {
1160 std::string clidTypeName;
1161 m_pCLIDSvc->getTypeNameOfID(clid, clidTypeName).ignore();
1162 SG_MSG_WARNING ("record_impl: can not add to t2p map object @{}\n"
1163 " with key {} of type {} (CLID {})",
1164 raw_ptr, rawKey, clidTypeName, clid);
1165 return nullptr;
1166 }
1167
1168 addAutoSymLinks (rawKey, clid, dp, tinfo);
1169
1170 //handle versionedKeys: we register an alias with the "true" key
1171 //unless an object as already been recorded with that key.
1172 //Notice that addAlias overwrites any existing alias, so a generic
1173 //retrieve will always return the last version added
1174 //FIXME not the one with the highest version
1175 if (isVKey) {
1176 SG::VersionedKey vk(rawKey);
1177 if (!(this->addAlias(vk.key(), dp)).isSuccess()) {
1178 SG_MSG_WARNING ("record_impl: Could not setup alias key {} for"
1179 " VersionedKey {}. Generic access to this object with clid {} will not work",
1180 vk.key(), rawKey, clid);
1181 }
1182 }
1183
1184 return dp;
1185}
1186
1187DataProxy*
1189 bool checkValid) const
1190{
1191 DataProxy* dp = m_pStore->proxy(tAddr);
1192
1193 if (checkValid && 0 != dp) {
1194 return dp->isValid() ? dp : 0;
1195 } else {
1196 return dp;
1197 }
1198}
1199
1200StatusCode
1202 bool forceRemove)
1203{
1205 // check if valid proxy
1206 if (0 == proxy) return StatusCode::FAILURE;
1207
1208 if (0 == pTrans) {
1209 DataBucketBase* bucket = dynamic_cast<DataBucketBase*>(proxy->object());
1210 if (bucket) pTrans = bucket->object();
1211 }
1212
1213 // remove all entries from t2p map
1214 // --- only if the proxy actually has an object!
1215 // otherwise, we can trigger I/O.
1216 // besides being useless here, we can get deadlocks if we
1217 // call into the I/O code while holding the SG lock.
1218 if (proxy->isValidObject()) {
1219 this->t2pRemove(pTrans);
1220 SG::DataProxy::CLIDCont_t clids = proxy->transientID();
1221 for (SG::DataProxy::CLIDCont_t::const_iterator i = clids.begin();
1222 i != clids.end();
1223 ++i)
1224 {
1225 void* ptr = SG::DataProxy_cast (proxy, *i);
1226 this->t2pRemove(ptr);
1227 }
1228 }
1229
1230 // remove from store
1231 return m_pStore->removeProxy(proxy, forceRemove, true);
1232}
1233
1234StatusCode
1235SGImplSvc::t2pRegister(const void* const pTrans, DataProxy* const pPers)
1236{
1237 return m_pStore->t2pRegister(pTrans, pPers);
1238}
1239
1240
1241void
1242SGImplSvc::t2pRemove(const void* const pTrans)
1243{
1244 m_pStore->t2pRemove(pTrans);
1245}
1246
1247void
1248SGImplSvc::msg_update_handler(Gaudi::Details::PropertyBase& /*outputLevel*/)
1249{
1250 setUpMessaging();
1251 updateMsgStreamOutputLevel( outputLevel() );
1252 msgSvc()->setOutputLevel(name(), outputLevel());
1253}
1254
1255StatusCode
1258 SG::ConstProxyIterator& end) const {
1260 return m_pStore->pRange(id,begin,end);
1261}
1262
1263StatusCode SGImplSvc::setConst(const void* pObject)
1264{
1266 // Check if DataProxy does not exist
1267 DataProxy * dp = proxy(pObject);
1268
1269 if (0 == dp)
1270 {
1271 SG_MSG_WARNING ("setConst: NO Proxy for the dobj you want to set const");
1272 return StatusCode::FAILURE;
1273 }
1274
1275 dp->setConst();
1276 return StatusCode::SUCCESS;
1277}
1278
1279
1280// remove an object from Store, will remove its proxy if not reset only
1281StatusCode
1282SGImplSvc::remove(const void* pObject)
1283{
1285 return removeProxy(proxy(pObject), pObject);
1286}
1287
1288
1289// remove an object and its proxy from Store
1290StatusCode
1292{
1294 const bool FORCEREMOVE(true);
1295 return removeProxy(proxy(pObject), pObject, FORCEREMOVE);
1296}
1297
1298//put a bad (unrecordable) dobj away
1299void SGImplSvc::recycle(DataObject* pBadDObj) {
1300 assert(pBadDObj);
1301 pBadDObj->addRef();
1302 m_trash.push_back(pBadDObj);
1303}
1304
1305//throw away bad objects
1308 while (!m_trash.empty()) {
1309 m_trash.front()->release(); //delete the bad data object
1310 m_trash.pop_front(); //remove pointer from list
1311 }
1312}
1313
1314
1315/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1316
1317StatusCode
1318SGImplSvc::record_HistObj(const CLID& id, const std::string& key,
1319 const std::string& store,
1320 bool allowMods, bool resetOnly) {
1321
1322 DataHistory *dho;
1323 dho = m_pHistorySvc->createDataHistoryObj( id, key, store );
1324
1325 std::string idname;
1326 StatusCode sc = m_pCLIDSvc->getTypeNameOfID(id, idname);
1327 if (sc.isFailure() || idname.empty() ) {
1328 idname = std::to_string(id);
1329 }
1330 idname += '/';
1331 idname += key;
1332
1333 DataObject* obj = SG::asStorable(dho);
1334
1335 const bool ALLOWOVERWRITE(false);
1336 if (record_impl(obj, idname, dho, allowMods, resetOnly, ALLOWOVERWRITE,
1337 &typeid(DataHistory)) == nullptr)
1338 return StatusCode::FAILURE;
1339 return StatusCode::SUCCESS;
1340}
1341
1342
1353{
1355 return m_stringpool.stringToKey (str, clid);
1356}
1357
1358
1366const std::string* SGImplSvc::keyToString (sgkey_t key) const
1367{
1369 return m_stringpool.keyToString (key);
1370}
1371
1372
1381const std::string*
1383{
1385 return m_stringpool.keyToString (key, clid);
1386}
1387
1388
1402 const std::string& str,
1403 CLID clid)
1404{
1406 if (!m_stringpool.registerKey (key, str, clid)) {
1407 CLID clid2;
1408 const std::string* str2 = m_stringpool.keyToString (key, clid2);
1409 SG_MSG_WARNING ("The numeric key {} maps to multiple string key/CLID pairs: {}/{} and {}/{}",
1410 key, *str2, clid2, str, clid);
1411 }
1412}
1413
1414
1423{
1424 // We should hold m_stringPoolMutex before touching the pool.
1425 // But if we acquire the locks for both this and the other store,
1426 // we risk a deadlock. So first copy the other pool, so that we
1427 // don't need to hold both locks at the same time.
1428 SG::StringPool tmp;
1429 {
1430 lock_t lock (other.m_stringPoolMutex);
1431 tmp = other.m_stringpool;
1432 }
1434 return m_stringpool.merge (tmp);
1435}
1436
1437
1438void
1439SGImplSvc::releaseObject(const CLID& id, const std::string& key) {
1441 DataProxy *pP(0);
1442 if (0 != (pP = proxy(id, key))) {
1443 // remove all entries from t2p map
1445 SG::DataProxy::CLIDCont_t::const_iterator i(clids.begin()), e(clids.end());
1446 while (i != e) t2pRemove(SG::DataProxy_cast (pP, *i++));
1447 DataBucketBase *pDBB(dynamic_cast<DataBucketBase*>(pP->object()));
1448 //tell the bucket to let go of the data object
1449 if (0 != pDBB) pDBB->relinquish(); //somebody else better took ownership
1450 bool hard_reset = (m_numSlots > 1);
1451 pP->reset (hard_reset);
1452 }
1453}
1454
1455void
1458
1459 // Remove transient pointer entries for this proxy.
1460 // But do that only if the proxy has a valid object.
1461 // Otherwise, we could trigger I/O --- which we don't want since it's useless
1462 // (we'd just destroy the object immediately). In some cases it can also
1463 // lead to a deadlock (see ATR-24482).
1464 if (dp->isValidObject()) {
1465 SG::DataProxy::CLIDCont_t clids = dp->transientID();
1466 SG::DataProxy::CLIDCont_t::const_iterator i(clids.begin()), e(clids.end());
1467 while (i != e) {
1468 t2pRemove(SG::DataProxy_cast (dp, *i++));
1469 }
1470 }
1471
1472 bool hard_reset = (m_numSlots > 1);
1473 dp->reset (hard_reset);
1474}
1475
1476
1485 sgkey_t target,
1486 off_t index_offset)
1487{
1489 SG::RemapImpl::remap_t payload;
1490 payload.target = target;
1491 payload.index_offset = index_offset;
1492 m_remap_impl->m_remaps[source] = payload;
1493}
1494
1495
1504bool SGImplSvc::tryELRemap (sgkey_t sgkey_in, size_t index_in,
1505 sgkey_t& sgkey_out, size_t& index_out)
1506{
1508 SG::RemapImpl::remap_map_t::iterator i =
1509 m_remap_impl->m_remaps.find (sgkey_in);
1510 if (i == m_remap_impl->m_remaps.end())
1511 return false;
1512 const SG::RemapImpl::remap_t& payload = i->second;
1513 sgkey_out = payload.target;
1514 index_out = index_in + payload.index_offset;
1515 return true;
1516}
1517
1518
1520 const std::string& key)
1521{
1523 DataObject* obj = nullptr;
1524 SG::DataProxy* dp = proxy (clid, key);
1525 //we do not want anyone to mess up with our copy hence we release it immediately.
1526 if (dp && dp->isValid()) {
1527 obj = dp->object();
1528 obj->addRef();
1529 clearProxyPayload (dp);
1530 }
1531 return obj;
1532}
1533
1534
1535CLID SGImplSvc::clid( const std::string& key ) const
1536{
1539 store()->tRange(s_iter, s_end).ignore();
1540
1541 for ( ; s_iter != s_end; ++s_iter ) {
1542 if ( s_iter->second.find( key ) != s_iter->second.end() ) {
1543 return s_iter->first;
1544 }
1545 }
1546
1547 return CLID_NULL;
1548}
1549
1550
1551std::vector<CLID> SGImplSvc::clids( const std::string& key ) const
1552{
1554 std::vector<CLID> clids;
1556 store()->tRange(s_iter, s_end).ignore();
1557
1558 for ( ; s_iter != s_end; ++s_iter ) {
1559 if ( s_iter->second.find( key ) != s_iter->second.end() ) {
1560 clids.push_back(s_iter->first);
1561 }
1562 }
1563
1564 return clids;
1565}
1566
1567
1569void SGImplSvc::addAutoSymLinks (const std::string& key,
1570 CLID clid,
1571 DataProxy* dp,
1572 const std::type_info* tinfo,
1573 bool warn_nobib /*= true*/)
1574{
1575 // Automatically make all legal base class symlinks
1576 if (!tinfo) {
1578 }
1579 const SG::BaseInfoBase* bib = nullptr;
1580 if (tinfo) {
1581 bib = SG::BaseInfoBase::find (*tinfo);
1582 }
1583 if (!bib) {
1584 // Could succeed where the previous fails if clid for DataVector<T>
1585 // but tinfo is for ConstDataVector<DataVector<T> >.
1587 }
1588 if ( bib ) {
1589 const std::vector<CLID>& bases = bib->get_bases();
1590 for ( std::size_t i = 0, iMax = bases.size(); i < iMax; ++i ) {
1591 if ( bases[i] != clid ) {
1592 if ( addSymLink( bases[i], dp ).isSuccess() ) {
1593 // register with t2p
1594 if (dp->object())
1595 this->t2pRegister( SG::DataProxy_cast( dp, bases[i] ), dp ).ignore();
1596 }
1597 else {
1598 SG_MSG_WARNING ("record_impl: Doing auto-symlinks for object"
1599 " with CLID {} and SG key {}:"
1600 " Proxy already set for base CLID {}; not making auto-symlink.",
1601 clid, key, bases[i]);
1602 }
1603 }
1604 }
1605
1606 // Handle copy conversions.
1607 {
1608 for (CLID copy_clid : bib->get_copy_conversions()) {
1609 if (m_pStore->addSymLink (copy_clid, dp).isFailure()) {
1610 SG_MSG_WARNING ("record_impl: Doing auto-symlinks for object"
1611 " with CLID {} and SG key {}:"
1612 " Proxy already set for copy-conversion CLID {}; not making auto-symlink.",
1613 clid, key, copy_clid);
1614 }
1615 }
1616 }
1617 }
1618 else {
1619 if (warn_nobib) {
1620 SG_MSG_WARNING ("record_impl: Could not find suitable SG::BaseInfoBase for CLID [{}] ({}) !\t"
1621 "No auto-symlink established !",
1622 clid, key);
1623 }
1624 }
1625}
1626
1627void
1630
1631 // Reset handles added since the last call to commit.
1632 bool hard_reset = (m_numSlots > 1);
1633 std::vector<IResetable*> handles;
1634 m_newBoundHandles[std::this_thread::get_id()].swap (handles);
1635 for (IResetable* h : handles)
1636 h->reset (hard_reset);
1637}
1638
1639
1645void
1647{
1648 m_newBoundHandles[std::this_thread::get_id()].push_back (handle);
1649}
1650
1651
1657void
1659{
1660 std::vector<IResetable*>& v = m_newBoundHandles[std::this_thread::get_id()];
1661 std::vector<IResetable*>::iterator it =
1662 std::find (v.begin(), v.end(), handle);
1663 if (it != v.end())
1664 v.erase (it);
1665}
1666
1667
1671{
1673 m_arena.makeCurrent();
1674 SG::CurrentEventStore::setStore (this);
1675}
1676
1677
1688StatusCode
1689SGImplSvc::createObj (IConverter* cvt,
1690 IOpaqueAddress* addr,
1691 DataObject*& refpObject)
1692{
1693 // This lock was here originally, but is probably not really needed ---
1694 // both DataProxy and the I/O components have their own locks.
1695 // Further, this was observed to cause deadlocks for the detector store,
1696 // and would in general be expected to be a contention issue.
1697 //lock_t lock (m_mutex);
1698 return cvt->createObj (addr, refpObject);
1699}
1700
1701
1702// This is intended to be called from the debugger.
1704{
1705 std::println ("{}", sg->dump());
1706}
1707void SG_dump (SGImplSvc* sg, const char* fname)
1708{
1709 std::ofstream f (fname);
1710 std::println (f, "{}", sg->dump());
1711 f.close();
1712}
1713
1714
1721SG::SourceID SGImplSvc::sourceID (const std::string& key /*= "EventSelector"*/) const
1722{
1725 if (dp) {
1727 if (dh) {
1728 return dh->begin()->getToken()->dbID().toString();
1729 }
1730 }
1731 return "";
1732}
1733
1734
1736// Retrieve a list of collections from Transient Store with no Key.
1737// const version
1740 SG::detail::IteratorBase& cibegin,
1741 SG::detail::IteratorBase& ciend) const
1742{
1746
1747 if (!(proxyRange(clid,first,end)).isSuccess()) {
1748 std::string typnam;
1749 m_pCLIDSvc->getTypeNameOfID(clid, typnam).ignore();
1750 SG_MSG_DEBUG("retrieve(range): no object found of type {} (CLID {})",
1751 typnam, clid);
1752 }
1753
1754 (ciend.setState(end, end, true)).ignore();
1755
1756 if (!(cibegin.setState(first, end, true)).isSuccess()) {
1757 std::string typnam;
1758 m_pCLIDSvc->getTypeNameOfID(clid, typnam).ignore();
1759 SG_MSG_DEBUG("retrieve(range): Can't initialize iterator for object range "
1760 " of type {} (CLID {})",
1761 typnam, clid);
1762 return StatusCode::FAILURE;
1763 }
1764
1765 return StatusCode::SUCCESS;
1766}
1767
1768
1770 const std::string& key,
1771 CLID auxclid) const
1772{
1773 // If we already have the aux store (as should usually be the case), return
1774 // without taking out the SG lock. Otherwise, we can deadlock
1775 // if another thread is also trying to dereference a link to the aux store.
1776 // (Should _not_ be holding the SG lock when dereferencing the link!)
1777 if (ptr->hasStore()) return true;
1778
1780 SG_MSG_VERBOSE("called associateAux_impl for key " + key);
1781 // no Aux store set yet
1782 if (!ptr->hasStore()) {
1783 SG::DataProxy* dp = proxy (auxclid, key + "Aux.", true);
1784 if (dp) {
1785 if (!dp->isConst()) {
1787 if (pAux) {
1788 ptr->setStore (pAux);
1789 return true;
1790 }
1791 }
1792
1793 const SG::IConstAuxStore* pAux = SG::DataProxy_cast<SG::IConstAuxStore> (dp);
1794 if (pAux) {
1795 ptr->setStore (pAux);
1796 return true;
1797 }
1798 }
1799 }
1800 return false;
1801}
1802
1803
1805 const std::string& key,
1806 CLID auxclid) const
1807{
1809 SG_MSG_VERBOSE("called associateAux_impl for key " + key);
1810 // no Aux store set yet
1811 if (!ptr->hasStore()) {
1812 SG::DataProxy* dp = proxy (auxclid, key + "Aux.", true);
1813 if (dp) {
1814 if (!dp->isConst()) {
1816 if (pAux) {
1817 ptr->setStore (pAux);
1818 return true;
1819 }
1820 }
1821
1822 const SG::IConstAuxStore* pAux = SG::DataProxy_cast<SG::IConstAuxStore> (dp);
1823 if (pAux) {
1824 ptr->setStore (pAux);
1825 return true;
1826 }
1827 }
1828 }
1829 return false;
1830}
#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.
This file contains the class definition for the DataHeader and DataHeaderElement classes.
void swap(DataVector< T > &a, DataVector< T > &b)
See DataVector<T, BASE>::swap().
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 a
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,...)
Hold a pointer to the current event store.
defines a StoreGateSvc key with a version number
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:109
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 symLink(const void *p2BRegistered, CLID linkID)
make a soft link to the object T* already registered
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.
DataObject * typeless_retrievePrivateCopy(const CLID clid, const std::string &key)
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
StatusCode setAlias(CLID clid, const std::string &key, const std::string &aliasKey)
make an alias to a DataObject (provide data type and old key)
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:677
int m_slotNumber
The Hive slot number for this store, or -1 if this isn't a Hive store.
Definition SGImplSvc.h:683
ServiceHandle< IProxyProviderSvc > m_pPPSHandle
Definition SGImplSvc.h:652
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:692
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.
std::vector< CLID > clids(const std::string &key) const
Retrieve all the CLID s (including symlinks) of the object recorded in StoreGate with the given "key"...
bool m_DumpStore
Dump Property flag: triggers dump() at EndEvent.
Definition SGImplSvc.h:663
bool m_ActivateHistory
Activate the history service.
Definition SGImplSvc.h:664
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:675
virtual StatusCode start() override final
Service start.
mutex_t m_mutex
Definition SGImplSvc.h:696
std::string createKey(const CLID &dataID)
creates a key internally if none specified by client
bool m_DumpArena
DumpArena Property flag : trigger m_arena->report() at clearStore.
Definition SGImplSvc.h:665
StatusCode removeProxy(SG::DataProxy *proxy, const void *pTrans, bool forceRemove=false)
remove proxy from store, unless it is reset only.
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.
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:680
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:695
IProxyProviderSvc * m_pPPS
Definition SGImplSvc.h:655
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.
int typeCount(const CLID &id) const
Return the number of instances of type T (input CLID).
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:659
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:698
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:660
ServiceHandle< IHistorySvc > m_pHistorySvc
Definition SGImplSvc.h:657
void releaseObject(const CLID &id, const std::string &key)
release object held by proxy, if any.
IStringPool::sgkey_t sgkey_t
Definition SGImplSvc.h:338
ServiceHandle< IIOVSvc > m_pIOVSvc
get the IOVSvc "just in time" (breaks recursion at initialize)
Definition SGImplSvc.h:671
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:686
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:673
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:649
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:662
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.
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...
mutex_t m_remapMutex
Definition SGImplSvc.h:697
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:650
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
a StoreGateSvc key with a version number.
unsigned char version() const
static bool isVersionedKey(const char *)
quickly determine whether a string has the right format to be a VK
const std::string & rawVersionKey() const
static bool isAuto(const std::string &)
quickly determine whether a string has the right format to be a VK with auto-generated version #
const std::string & key() const
Implementation class, not to be used directly Iterates over valid proxies it the range.
Definition SGIterator.h:37
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:76
void print(std::FILE *stream, std::format_string< Args... > fmt, Args &&... args)
Definition SGImplSvc.cxx:72
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)
Some out-of-line helpers for ExtendedEventContext.
SGKeyMap< remap_t > remap_map_t
Definition SGImplSvc.cxx:94
remap_map_t m_remaps
Definition SGImplSvc.cxx:95
IStringPool::sgkey_t sgkey_t
Definition SGImplSvc.cxx:88