2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
5 /** @file ElementLinkCnv_p2.icc
6 * @brief This file contains the implementation for the ElementLinkCnv_p2 template methods.
7 * @author R.D.Schaffer@cern.ch
12 #include "AthLinks/ElementLink.h"
13 #include "ElementLinkContNames_p2.h"
14 #include "AthenaKernel/ThinningCache.h"
15 #include "AthenaKernel/ThinningDecisionBase.h"
16 #include "AthenaKernel/getThinningCache.h"
18 //#define ELLINK_DEBUG
21 template <typename LINK_TYPE>
23 ElementLinkCnv_p2<LINK_TYPE>::State::State()
25 // Init both last names
26 m_lastNameFound = defaultLastName();
27 m_lastNameAdded = *m_lastNameFound;
31 template <typename LINK_TYPE>
33 ElementLinkCnv_p2<LINK_TYPE>::State::State (ElementLinkContNames_p2& lookupTable)
39 template <typename LINK_TYPE>
41 ElementLinkCnv_p2<LINK_TYPE>::State::State (const ElementLinkContNames_p2& lookupTable)
47 template <typename LINK_TYPE>
50 ElementLinkCnv_p2<LINK_TYPE>::State::defaultLastName () const
52 static const std::string lastName = "NO LAST NAME";
57 template <typename LINK_TYPE>
60 ElementLinkCnv_p2<LINK_TYPE>::State::reset(ElementLinkContNames_p2& lookupTable)
62 // Save lookup table and reset element link index and map
63 m_lookupTable = &lookupTable;
65 m_nameIndexMap.clear();
66 m_lastNameFound = defaultLastName();
67 m_lastNameAdded = *m_lastNameFound;
72 template <typename LINK_TYPE>
75 ElementLinkCnv_p2<LINK_TYPE>::State::reset(const ElementLinkContNames_p2& lookupTable)
77 // Save lookup table and reset element link index and map
79 m_clookupTable = &lookupTable;
80 m_nameIndexMap.clear();
81 m_lastNameFound = defaultLastName();
82 m_lastNameAdded = *m_lastNameFound;
83 m_lastNameIndex = 0xFFFFFFFF;
87 //********************************************************************
90 template <typename LINK_TYPE>
92 ElementLinkCnv_p2<LINK_TYPE>::
94 : m_isPersistible (false)
99 template <typename LINK_TYPE>
101 ElementLinkCnv_p2<LINK_TYPE>::
102 ElementLinkCnv_p2(bool isPersistible)
103 : m_isPersistible (isPersistible)
108 template <typename LINK_TYPE>
109 void ElementLinkCnv_p2<LINK_TYPE>::
110 transToPers (State& state,
113 const SG::ThinningCache* cache,
114 [[maybe_unused]] MsgStream& msg) const
117 // trans.printState();
120 static const std::string s_empty = "";
121 if( trans.isDefault() ) {
122 pers.m_contIndex = getNameIndex(state, s_empty); // Must save empty string for default EL
123 pers.m_elementIndex = 0; // value not used, but 0 compresses better
127 // Check for thinning.
129 const SG::ThinningDecisionBase* dec = cache->thinning (trans.key());
131 // here is the problem: in case the ElementLink was directly created w/
132 // only a pointer to the element, _and_ if the the pointed-at element
133 // has been thinned away, EL::index() will throw b/c
134 // IndexingPolicy::setIndex will fail.
135 std::size_t idx = SG::ThinningDecisionBase::RemovedIdx;
138 } catch ( const SG::maybe_thinning_error& err ) {
139 // ok. that's the corner case we talked about above.
141 msg << MSG::DEBUG << "caught a maybe_thinning_error: ["
144 << "(this is an expected case of the EL-state-phase-space "
145 << "when thinning is active)"
149 // Get the updated index:
150 const std::size_t persIdx = dec->index( idx );
151 if (SG::ThinningDecisionBase::RemovedIdx == persIdx) {
152 // this element has been thinned away. So the persistent equivalent
153 // of a null pointer is a default persistent pointer.
155 // Must save empty string for default EL
156 pers.m_contIndex = getNameIndex(state, s_empty);
157 // Index value not used, but 0 compresses better
158 pers.m_elementIndex = 0;
162 if (!m_isPersistible) {
165 if (!state.m_lookupTable) {
168 << "Empty link name table ptr - must use resetForCnv "
173 // Save container name index and element link index
174 pers.m_contIndex = getNameIndex(state, tmp.dataID());
175 pers.m_elementIndex = persIdx;
179 msg << MSG::INFO << "ElementLinkCnv_p3::transToPer(): SG Container="
180 << ", Key Hash=" << pers.m_SGKeyHash
181 << ", IDX=" << pers.m_elementIndex << endmsg;
188 if (!m_isPersistible) {
191 // convert string to index
192 if (!state.m_lookupTable) {
195 << "Empty link name table ptr - must use resetForCnv "
200 // Save container name index and element link index
201 pers.m_contIndex = getNameIndex(state, tmp.dataID());
202 pers.m_elementIndex = SG::sgkeyShort (tmp.index());
205 msg << MSG::DEBUG << "ElementLinkCnv_p2::transToPer(): KEY= "
206 << trans.dataID() << ", IDX= " << trans.index()
207 << ", pers cont index= " << pers.m_contIndex
208 << ", ele index= " << pers.m_elementIndex
214 template <typename LINK_TYPE>
215 void ElementLinkCnv_p2<LINK_TYPE>::
216 transToPers (State& state,
219 MsgStream& msg) const
221 transToPers (state, trans, pers,
222 SG::getThinningCache(),
227 template <typename LINK_TYPE >
229 void ElementLinkCnv_p2< LINK_TYPE >
230 ::persToTrans(State& state,
231 const PersLink_t& pers,
233 MsgStream& log) const
235 // convert index to string
236 const std::string* contName = 0;
237 // Get container name from name index
238 getContName(state, pers.m_contIndex, contName, log);
241 log << MSG::DEBUG << "ElementLinkCnv_p2::PersToTrans(): container name" <<
242 (*contName) << endmsg;
245 log << MSG::ERROR << "ElementLinkCnv_p2::PersToTrans(): container name EMPTY"
249 if( contName->empty() ) {
250 // If container name is empty, this is a default ElementLink
251 // To be safe, reset to the default state, e.g. may be reusing
252 // existing EL from DataPool
255 log << MSG::DEBUG << "ElementLinkCnv_p2::PersToTrans(): reading EL in Default state" << endmsg;
258 // reset trans ELink with key and index - changeds to identified state
259 trans.resetWithKeyAndIndex((*contName), pers.m_elementIndex);
262 log << MSG::DEBUG << "ElementLinkCnv_p2::PersToTrans(): KEY="
263 << (*contName) << ", IDX=" << pers.m_elementIndex << endmsg;
264 if ((*contName) == "NO LAST NAME") {
265 log << MSG::ERROR << "ElementLinkCnv_p2::PersToTrans(): INCORRECT KEY KEY="
266 << (*contName) << ", IDX=" << pers.m_elementIndex << endmsg;
273 template <typename LINK_TYPE>
276 ElementLinkCnv_p2<LINK_TYPE>::resetForCnv(ElementLinkContNames_p2& lookupTable)
278 // Save lookup table and reset element link index and map
279 m_state.reset (lookupTable);
282 template <typename LINK_TYPE>
285 ElementLinkCnv_p2<LINK_TYPE>::resetForCnv(const ElementLinkContNames_p2& lookupTable)
287 // Save lookup table and reset element link index and map
288 m_state.reset (lookupTable);
291 template <typename LINK_TYPE>
293 void ElementLinkCnv_p2<LINK_TYPE>::
294 transToPers(const Link_t* trans, PersLink_t* pers,
295 [[maybe_unused]] MsgStream& log)
297 transToPers (m_state, *trans, *pers, log);
301 template <typename LINK_TYPE >
303 void ElementLinkCnv_p2< LINK_TYPE >
304 ::persToTrans(const PersLink_t* pers, Link_t* trans, MsgStream& log)
306 persToTrans (m_state, *pers, *trans, log);
312 template <typename LINK_TYPE >
314 void ElementLinkCnv_p2< LINK_TYPE >::
315 persToTrans(const PersLink_t& pers, Link_t& trans, MsgStream& log) {
316 persToTrans( m_state, pers, trans, log);
320 template <typename LINK_TYPE >
322 void ElementLinkCnv_p2< LINK_TYPE >::
323 transToPers(const Link_t& trans, PersLink_t& pers, MsgStream& log) {
324 transToPers( m_state, trans, pers, log);
328 template <typename LINK_TYPE >
331 ElementLinkCnv_p2< LINK_TYPE >::getNameIndex (State& state,
332 const std::string& name) const
334 // Add this name to the lookup table, retrieving and index.
336 unsigned int nameIndex;
338 // Only need to save name if container name has
339 // changed for this element link
340 if (name == state.m_lastNameAdded) return (state.m_lastNameIndex);
342 // check if name has already been added, if so use the index
343 // found, other make a new entry
345 // NOTE: the map is part of this converter object and not the
346 // lookup table itself
348 typename State::IndexMap::const_iterator it =
349 state.m_nameIndexMap.find(name);
350 if (it != state.m_nameIndexMap.end()) {
351 nameIndex = (it->second);
354 // Add new name to lookup table and map
355 nameIndex = state.m_lookupTable->m_names.size();
356 state.m_lookupTable->m_names.push_back(name);
357 state.m_nameIndexMap[name] = nameIndex;
360 // Save last name and index
362 // Note: state.m_lastNameAdded is a copy of a string and not a ptr into
363 // the lookup table. This is required because the lookup table may
364 // be extended/reallocated elsewhere in memory and thus invalidate
366 state.m_lastNameIndex = nameIndex;
367 state.m_lastNameAdded = state.m_lookupTable->m_names[nameIndex];
371 template <typename LINK_TYPE >
374 ElementLinkCnv_p2< LINK_TYPE >::getContName (State& state,
375 unsigned int nameIndex,
376 std::string const *& name,
377 MsgStream& log) const
380 // Only need to get new name if index has changed for this element
382 if (nameIndex == state.m_lastNameIndex) {
383 name = state.m_lastNameFound;
387 // Get the container name with the name index from the lookup table
388 if (!state.m_clookupTable ||
389 state.m_clookupTable->m_names.size() < nameIndex + 1)
391 if (!state.m_clookupTable) {
392 log << MSG::ERROR << "Empty link name table ptr" << endmsg;
395 log << MSG::ERROR << "Empty name vector in lookup table - looking for index "
396 << nameIndex << " size " << state.m_clookupTable->m_names.size() << endmsg;
400 name = &(state.m_clookupTable->m_names[nameIndex]);
402 // Save last name and index
403 state.m_lastNameFound = name;
404 state.m_lastNameIndex = nameIndex;