ATLAS Offline Software
AthenaPoolConverter.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
12 
13 #include "SGTools/DataProxy.h"
14 
19 #include "StorageSvc/DbType.h"
20 #include "RootUtils/APRDefaults.h"
21 #include <format>
22 
23 //__________________________________________________________________________
25  delete m_i_poolToken; m_i_poolToken = nullptr;
26 }
27 //__________________________________________________________________________
30 
31  // We do not retrieve m_detStore as that store may not always be available!
32 
33  ATH_CHECK( m_athenaPoolCnvSvc.retrieve() );
34 
35  IProperty* propertyServer(dynamic_cast<IProperty*>(m_athenaPoolCnvSvc.get()));
36  StringProperty containerPrefixProp("PoolContainerPrefix", "CollectionTree");
37  StringProperty containerNameHintProp("TopLevelContainerName", "");
38  StringProperty branchNameHintProp("SubLevelBranchName", "<type>/<key>");
39  if (propertyServer) {
40  propertyServer->getProperty(&containerPrefixProp).ignore();
41  propertyServer->getProperty(&containerNameHintProp).ignore();
42  propertyServer->getProperty(&branchNameHintProp).ignore();
43  }
44  m_containerPrefix = containerPrefixProp.value();
45  m_containerNameHint = containerNameHintProp.value();
46  m_branchNameHint = branchNameHintProp.value();
47  return StatusCode::SUCCESS;
48 }
49 //__________________________________________________________________________
51  // Release AthenaPoolCnvSvc
52  if (!m_athenaPoolCnvSvc.release().isSuccess()) {
53  ATH_MSG_WARNING("Cannot release AthenaPoolCnvSvc.");
54  }
55  return(::Converter::finalize());
56 }
57 //__________________________________________________________________________
59  return pool::POOL_StorageType.type();
60 }
61 //__________________________________________________________________________
62 StatusCode AthenaPoolConverter::createObj(IOpaqueAddress* pAddr, DataObject*& pObj) {
63  TokenAddress* tokAddr = dynamic_cast<TokenAddress*>(pAddr);
64 
65  bool ownTokAddr = false;
66  if (tokAddr == nullptr || tokAddr->getToken() == nullptr) {
67  ownTokAddr = true;
68  auto token = std::make_unique<Token>();
69  token->fromString(*(pAddr->par()));
70  GenericAddress* genAddr = dynamic_cast<GenericAddress*>(pAddr);
71  if (not genAddr){
72  ATH_MSG_ERROR("Dynamic cast failed in AthenaPoolConverter::createObj");
73  //clean up
74  return StatusCode::FAILURE;
75  }
76  tokAddr = new TokenAddress(*genAddr, std::move(token));
77  }
78  if( tokAddr->ipar()[0] > 0 and tokAddr->getToken()->auxString().empty() ) {
79  char text[32];
80  const std::string contextStr = std::format("[CTXT={:08X}]", static_cast<int>(*(pAddr->ipar())));
81  std::strncpy(text, contextStr.c_str(), sizeof(text) - 1);
82  text[sizeof(text) - 1] = '\0';
83  tokAddr->getToken()->setAuxString(text);
84  }
85  ATH_MSG_VERBOSE("createObj: " << tokAddr->getToken()->toString() << ", CTX=" << tokAddr->ipar()[0]
86  << ", auxStr=" << tokAddr->getToken()->auxString() );
87  std::lock_guard<CallMutex> lock(m_conv_mut);
88  m_i_poolToken = tokAddr->getToken();
89  try {
90  std::string key = pAddr->par()[1];
91  if (!PoolToDataObject(pObj, tokAddr->getToken(), key).isSuccess()) {
92  ATH_MSG_ERROR("createObj PoolToDataObject() failed, Token = " << (tokAddr->getToken() ? tokAddr->getToken()->toString() : "NULL"));
93  pObj = nullptr;
94  }
95  } catch (std::exception& e) {
96  ATH_MSG_ERROR("createObj - caught exception: " << e.what());
97  pObj = nullptr;
98  }
99  if (pObj == nullptr) {
100  ATH_MSG_ERROR("createObj failed to get DataObject, Token = " << (tokAddr->getToken() ? tokAddr->getToken()->toString() : "NULL"));
101  }
102  if (ownTokAddr) {
103  delete tokAddr; tokAddr = nullptr;
104  }
105  m_i_poolToken = nullptr;
106  if (pObj == nullptr) {
107  return StatusCode::FAILURE;
108  }
109  return StatusCode::SUCCESS;
110 }
111 //__________________________________________________________________________
112 StatusCode AthenaPoolConverter::createRep(DataObject* pObj, IOpaqueAddress*& pAddr) {
113  const SG::DataProxy* proxy = dynamic_cast<SG::DataProxy*>(pObj->registry());
114  if (proxy == nullptr) {
115  ATH_MSG_ERROR("AthenaPoolConverter CreateRep failed to cast DataProxy, key = " << pObj->name());
116  return StatusCode::FAILURE;
117  }
118  try {
119  std::lock_guard<CallMutex> lock(m_conv_mut);
120  if (!DataObjectToPers(pObj, pAddr).isSuccess()) {
121  ATH_MSG_ERROR("CreateRep failed, key = " << pObj->name());
122  return StatusCode::FAILURE;
123  }
124  } catch (std::exception& e) {
125  ATH_MSG_ERROR("createRep - caught exception: " << e.what());
126  return StatusCode::FAILURE;
127  }
128  const CLID clid = proxy->clID();
129  if (pAddr == nullptr) {
130  // Create a IOpaqueAddress for this object.
131  pAddr = new TokenAddress(this->storageType(), clid, "", "", 0, 0);
132  } else {
133  GenericAddress* gAddr = dynamic_cast<GenericAddress*>(pAddr);
134  if (gAddr != nullptr) {
135  gAddr->setSvcType(this->storageType());
136  }
137  }
138  return StatusCode::SUCCESS;
139 }
140 //__________________________________________________________________________
141 StatusCode AthenaPoolConverter::fillRepRefs(IOpaqueAddress* pAddr, DataObject* pObj) {
142  std::lock_guard<CallMutex> lock(m_conv_mut);
143  try {
144  if (!DataObjectToPool(pAddr, pObj).isSuccess()) {
145  ATH_MSG_ERROR("FillRepRefs failed, key = " << pObj->name());
146  return StatusCode::FAILURE;
147  }
148  } catch (std::exception& e) {
149  ATH_MSG_ERROR("fillRepRefs - caught exception: " << e.what());
150  return StatusCode::FAILURE;
151  }
152  return StatusCode::SUCCESS;
153 }
154 //__________________________________________________________________________
156  return pool::POOL_StorageType.type();
157 }
158 //__________________________________________________________________________
159 AthenaPoolConverter::AthenaPoolConverter(const CLID& myCLID, ISvcLocator* pSvcLocator,
160  const char* name /*= nullptr*/) :
161  ::Converter(storageType(), myCLID, pSvcLocator),
162  ::AthMessaging((pSvcLocator != nullptr ? msgSvc() : nullptr),
163  name ? name : "AthenaPoolConverter"),
164  m_detStore("DetectorStore", name ? name : "AthenaPoolConverter"),
165  m_athenaPoolCnvSvc(pSvcLocator && pSvcLocator->existsService("AthenaPoolSharedIOCnvSvc") ? "AthenaPoolSharedIOCnvSvc" : "AthenaPoolCnvSvc", name ? name : "AthenaPoolConverter"),
166  m_classDesc(),
167  m_className(),
168  m_classDescs(),
169  m_containerPrefix(""),
170  m_containerNameHint(""),
171  m_branchNameHint(""),
172  m_dataObject(nullptr),
173  m_i_poolToken(nullptr) {
174 }
175 //__________________________________________________________________________
176 Placement AthenaPoolConverter::setPlacementWithType(const std::string& tname, const std::string& key, const std::string& output) {
177  Placement placement;
178  // Override streaming parameters from StreamTool if requested.
179  std::string::size_type pos1 = output.find('[');
180  std::string outputConnectionSpec = output.substr(0, pos1);
181  int tech = 0;
182  m_athenaPoolCnvSvc->decodeOutputSpec(outputConnectionSpec, tech).ignore();
183  // Set DB and Container names
184  placement.setFileName(outputConnectionSpec);
185 
186  std::string containerPrefix = m_containerPrefix;
187  if( containerPrefix == "Default" ) {
188  containerPrefix = pool::ROOTRNTUPLE_StorageType.exactMatch(tech) ? APRDefaults::RNTupleNames::EventData : APRDefaults::TTreeNames::EventData;
189  }
190  std::string dhContainerPrefix = pool::ROOTRNTUPLE_StorageType.exactMatch(tech) ? APRDefaults::RNTupleNames::DataHeader : APRDefaults::TTreeNames::DataHeader;
191  std::string containerName;
192 
193  // Get Technology from containerPrefix
194  std::size_t colonPos = containerPrefix.find(':');
195  if (colonPos != std::string::npos) {
196  dhContainerPrefix = containerPrefix.substr(0, colonPos + 1) + dhContainerPrefix;
197  }
198 
199  // Override streaming parameters from StreamTool if requested.
200  std::string containerNameHint = m_containerNameHint;
201  std::string branchNameHint = m_branchNameHint;
202  std::string containerFriendPostfix;
203  while (pos1 != std::string::npos) {
204  const std::string::size_type pos2 = output.find('=', pos1);
205  const std::string thisKey = output.substr(pos1 + 1, pos2 - pos1 - 1);
206  const std::string::size_type pos3 = output.find(']', pos2);
207  const std::string value = output.substr(pos2 + 1, pos3 - pos2 - 1);
208  if (thisKey == "OutputCollection") {
209  dhContainerPrefix = std::move(value);
210  } else if (thisKey == "PoolContainerPrefix") {
211  containerPrefix = std::move(value);
212  } else if (thisKey == "TopLevelContainerName") {
213  containerNameHint = std::move(value);
214  } else if (thisKey == "SubLevelBranchName") {
215  branchNameHint = std::move(value);
216  } else if (thisKey == "PoolContainerFriendPostfix") {
217  containerFriendPostfix = std::move(value);
218  }
219  pos1 = output.find('[', pos3);
220  }
221 
222  // --- Special types: DataHeader & Form
223  if( tname.compare(0, 10, "DataHeader") == 0 ) {
224  if( tname.compare(10, 4, "Form") == 0 ) {
225  containerName = dhContainerPrefix + "Form" + "(" + tname + ")";
226  } else {
227  if (key[key.size() - 1] == '/') {
228  containerName = dhContainerPrefix + "(" + key + tname + ")";
229  } else {
230  containerName = dhContainerPrefix + "(" + tname + ")";
231  }
232  }
233  }
234  // AttributeList - writing attributes separately to EventTag container group
235  else if (tname.compare(0, 13, "AttributeList") == 0) {
236  // Find the right storage type and name for EventTag values
237  if( pool::ROOTRNTUPLE_StorageType.exactMatch(tech) ) {
238  containerName = std::string(APRDefaults::RNTupleNames::EventTag) + "(" + key + ")";
239  } else {
240  // no indexing needed (nothing points to Tags)
241  // safe to set tech here - it will not be overwritten by decodeOutput
242  tech = pool::ROOTTREE_StorageType.type();
243  containerName = std::string(APRDefaults::TTreeNames::EventTag) + "(" + key + ")";
244  }
245  }
246  // all other object types
247  else {
248  const std::string typeTok = "<type>", keyTok = "<key>";
249  containerName = containerPrefix + containerFriendPostfix + containerNameHint;
250  if (!branchNameHint.empty()) {
251  containerName += "(" + branchNameHint + ")";
252  }
253  const std::size_t pos1 = containerName.find(typeTok);
254  if (pos1 != std::string::npos) {
255  containerName.replace(pos1, typeTok.size(), tname);
256  }
257  const std::size_t pos2 = containerName.find(keyTok);
258  if (pos2 != std::string::npos) {
259  if (key.empty()) {
260  containerName.replace(pos2, keyTok.size(), tname);
261  } else {
262  containerName.replace(pos2, keyTok.size(), key);
263  }
264  }
265  }
266  m_athenaPoolCnvSvc->decodeOutputSpec(containerName, tech).ignore();
267  placement.setContainerName(containerName);
268  placement.setTechnology(tech);
269  return(placement);
270 }
271 //__________________________________________________________________________
272 const DataObject* AthenaPoolConverter::getDataObject() const {
273  return(m_dataObject);
274 }
275 //__________________________________________________________________________
277  return(m_i_poolToken ? (guid == m_i_poolToken->classID()) : false);
278 }
279 //__________________________________________________________________________
280 StatusCode AthenaPoolConverter::cleanUp(const std::string& /*output*/) {
281  ATH_MSG_DEBUG("AthenaPoolConverter cleanUp called for base class.");
282  return StatusCode::SUCCESS;
283 }
AthenaPoolConverter::setPlacementWithType
virtual Placement setPlacementWithType(const std::string &tname, const std::string &key, const std::string &output)
Set POOL placement hint for a given type.
Definition: AthenaPoolConverter.cxx:176
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
AthenaPoolConverter::m_dataObject
const DataObject * m_dataObject
Definition: AthenaPoolConverter.h:129
python.tests.PyTestsLib.finalize
def finalize(self)
_info( "content of StoreGate..." ) self.sg.dump()
Definition: PyTestsLib.py:50
Placement
This class holds all the necessary information to guide the writing of an object in a physical place.
Definition: Placement.h:19
AthenaPoolConverter.h
This file contains the class definition for the AthenaPoolConverter class.
IAthenaPoolCnvSvc.h
This file contains the class definition for the IAthenaPoolCnvSvc interface class.
AthenaPoolConverter::DataObjectToPool
virtual StatusCode DataObjectToPool(IOpaqueAddress *pAddr, DataObject *pObj)=0
Write an object into POOL.
StateLessPT_NewConfig.proxy
proxy
Definition: StateLessPT_NewConfig.py:407
vtune_athena.format
format
Definition: vtune_athena.py:14
APRDefaults::RNTupleNames::DataHeader
static constexpr const char * DataHeader
Definition: APRDefaults.h:20
AthenaPoolConverter::m_athenaPoolCnvSvc
ServiceHandle< IAthenaPoolCnvSvc > m_athenaPoolCnvSvc
Definition: AthenaPoolConverter.h:117
AthenaPoolConverter::~AthenaPoolConverter
virtual ~AthenaPoolConverter()
Destructor.
Definition: AthenaPoolConverter.cxx:24
initialize
void initialize()
Definition: run_EoverP.cxx:894
Token::auxString
const std::string & auxString() const
Access auxiliary string.
Definition: Token.h:91
AthenaPoolConverter::compareClassGuid
bool compareClassGuid(const Guid &guid) const
Definition: AthenaPoolConverter.cxx:276
AthenaPoolConverter::storageType
static long storageType()
Definition: AthenaPoolConverter.cxx:155
APRDefaults::TTreeNames::EventTag
static constexpr const char * EventTag
Definition: APRDefaults.h:13
athena.value
value
Definition: athena.py:124
python.RatesEmulationExample.lock
lock
Definition: RatesEmulationExample.py:148
DbType.h
Token::classID
const Guid & classID() const
Access database identifier.
Definition: Token.h:73
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Placement::setContainerName
Placement & setContainerName(const std::string &containerName)
Set container name.
Definition: Placement.h:34
AthenaPoolConverter::repSvcType
virtual long repSvcType() const override
Definition: AthenaPoolConverter.cxx:58
AthenaPoolConverter::initialize
virtual StatusCode initialize() override
Gaudi Service Interface method implementations:
Definition: AthenaPoolConverter.cxx:28
pool::DbType::type
int type() const
Access to full type.
Definition: DbType.h:66
AthenaPoolConverter::m_conv_mut
CallMutex m_conv_mut
Definition: AthenaPoolConverter.h:133
TokenAddress
This class provides a Generic Transient Address for POOL tokens.
Definition: TokenAddress.h:23
APRDefaults::RNTupleNames::EventData
static constexpr const char * EventData
Definition: APRDefaults.h:18
AthenaPoolConverter::cleanUp
virtual StatusCode cleanUp(const std::string &output) override
Implement cleanUp for AthenaPoolConverter to do nothing.
Definition: AthenaPoolConverter.cxx:280
APRDefaults.h
AthenaPoolConverter::m_i_poolToken
const Token * m_i_poolToken
Definition: AthenaPoolConverter.h:130
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
StdJOSetup.msgSvc
msgSvc
Provide convenience handles for various services.
Definition: StdJOSetup.py:36
AthenaPoolConverter::AthenaPoolConverter
AthenaPoolConverter(const CLID &id, ISvcLocator *pSvcLocator, const char *name=nullptr)
Standard Service Constructor.
Definition: AthenaPoolConverter.cxx:159
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
AthenaPoolConverter::m_containerPrefix
std::string m_containerPrefix
Definition: AthenaPoolConverter.h:125
calibdata.exception
exception
Definition: calibdata.py:495
AthenaPoolConverter::m_containerNameHint
std::string m_containerNameHint
Definition: AthenaPoolConverter.h:126
AthMessaging
Class to provide easy MsgStream access and capabilities.
Definition: AthMessaging.h:55
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
TokenAddress::getToken
Token * getToken()
Definition: TokenAddress.cxx:15
Placement::setFileName
Placement & setFileName(const std::string &fileName)
Set file name.
Definition: Placement.h:30
CLID
uint32_t CLID
The Class ID type.
Definition: Event/xAOD/xAODCore/xAODCore/ClassID_traits.h:47
APRDefaults::RNTupleNames::EventTag
static constexpr const char * EventTag
Definition: APRDefaults.h:19
AthenaPoolConverter::fillRepRefs
virtual StatusCode fillRepRefs(IOpaqueAddress *pAddr, DataObject *pObj) override
Create a POOL persistent representation for a transient object.
Definition: AthenaPoolConverter.cxx:141
pool_uuid.guid
guid
Definition: pool_uuid.py:112
merge.output
output
Definition: merge.py:16
APRDefaults::TTreeNames::DataHeader
static constexpr const char * DataHeader
Definition: APRDefaults.h:14
Converter
Definition: Converter.h:27
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
AthenaPoolConverter::PoolToDataObject
virtual StatusCode PoolToDataObject(DataObject *&pObj, const Token *token, const std::string &key)=0
Read an object from POOL.
Token::toString
virtual const std::string toString() const
Retrieve the string representation of the token.
Definition: Token.cxx:134
AthenaPoolConverter::DataObjectToPers
virtual StatusCode DataObjectToPers(DataObject *pObj, IOpaqueAddress *&pAddr)=0
Convert an object into Persistent.
TokenAddress.h
This file contains the class definition for the TokenAddress class.
Guid
This class provides a encapsulation of a GUID/UUID/CLSID/IID data structure (128 bit number).
Definition: Guid.h:25
pool::DbType::exactMatch
bool exactMatch(const DbType &typ) const
Definition: DbType.h:73
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
AthenaPoolConverter::createRep
virtual StatusCode createRep(DataObject *pObj, IOpaqueAddress *&pAddr) override
Create a POOL persistent representation for a transient object.
Definition: AthenaPoolConverter.cxx:112
AthenaPoolConverter::m_branchNameHint
std::string m_branchNameHint
Definition: AthenaPoolConverter.h:127
Token::setAuxString
Token & setAuxString(const std::string &auxString)
Set auxiliary string.
Definition: Token.h:93
Placement::setTechnology
Placement & setTechnology(int technology)
Set technology type.
Definition: Placement.h:38
AthenaPoolConverter::getDataObject
virtual const DataObject * getDataObject() const
Definition: AthenaPoolConverter.cxx:272
makeTransCanvas.text
text
Definition: makeTransCanvas.py:11
AthenaPoolConverter::finalize
virtual StatusCode finalize() override
Definition: AthenaPoolConverter.cxx:50
Guid.h
This file contains the class definition for the Guid class (migrated from POOL).
Placement.h
This file contains the class definition for the Placement class (migrated from POOL).
APRDefaults::TTreeNames::EventData
static constexpr const char * EventData
Definition: APRDefaults.h:12
SG::DataProxy
Definition: DataProxy.h:45
Token.h
This file contains the class definition for the Token class (migrated from POOL).
AthenaPoolConverter::createObj
virtual StatusCode createObj(IOpaqueAddress *pAddr, DataObject *&pObj) override
Create a transient object from a POOL persistent representation.
Definition: AthenaPoolConverter.cxx:62
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
DataProxy.h