ATLAS Offline Software
Loading...
Searching...
No Matches
ElementLinkCnv_p2.icc
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
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
8 **/
9
10#include <stdexcept>
11
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"
17
18//#define ELLINK_DEBUG
19
20
21template <typename LINK_TYPE>
22inline
23ElementLinkCnv_p2<LINK_TYPE>::State::State()
24{
25 // Init both last names
26 m_lastNameFound = defaultLastName();
27 m_lastNameAdded = *m_lastNameFound;
28}
29
30
31template <typename LINK_TYPE>
32inline
33ElementLinkCnv_p2<LINK_TYPE>::State::State (ElementLinkContNames_p2& lookupTable)
34{
35 reset (lookupTable);
36}
37
38
39template <typename LINK_TYPE>
40inline
41ElementLinkCnv_p2<LINK_TYPE>::State::State (const ElementLinkContNames_p2& lookupTable)
42{
43 reset (lookupTable);
44}
45
46
47template <typename LINK_TYPE>
48inline
49const std::string*
50ElementLinkCnv_p2<LINK_TYPE>::State::defaultLastName () const
51{
52 static const std::string lastName = "NO LAST NAME";
53 return &lastName;
54}
55
56
57template <typename LINK_TYPE>
58inline
59void
60ElementLinkCnv_p2<LINK_TYPE>::State::reset(ElementLinkContNames_p2& lookupTable)
61{
62 // Save lookup table and reset element link index and map
63 m_lookupTable = &lookupTable;
64 m_clookupTable = 0;
65 m_nameIndexMap.clear();
66 m_lastNameFound = defaultLastName();
67 m_lastNameAdded = *m_lastNameFound;
68 m_lastNameIndex = 0;
69}
70
71
72template <typename LINK_TYPE>
73inline
74void
75ElementLinkCnv_p2<LINK_TYPE>::State::reset(const ElementLinkContNames_p2& lookupTable)
76{
77 // Save lookup table and reset element link index and map
78 m_lookupTable = 0;
79 m_clookupTable = &lookupTable;
80 m_nameIndexMap.clear();
81 m_lastNameFound = defaultLastName();
82 m_lastNameAdded = *m_lastNameFound;
83 m_lastNameIndex = 0xFFFFFFFF;
84}
85
86
87//********************************************************************
88
89
90template <typename LINK_TYPE>
91inline
92ElementLinkCnv_p2<LINK_TYPE>::
93ElementLinkCnv_p2()
94 : m_isPersistible (false)
95{
96}
97
98
99template <typename LINK_TYPE>
100inline
101ElementLinkCnv_p2<LINK_TYPE>::
102ElementLinkCnv_p2(bool isPersistible)
103 : m_isPersistible (isPersistible)
104{
105}
106
107
108template <typename LINK_TYPE>
109void ElementLinkCnv_p2<LINK_TYPE>::
110transToPers (State& state,
111 const Link_t& trans,
112 PersLink_t& pers,
113 const SG::ThinningCache* cache,
114 [[maybe_unused]] MsgStream& msg) const
115{
116#ifdef ELLINK_DEBUG
117// trans.printState();
118#endif
119
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
124 return;
125 }
126
127 // Check for thinning.
128 if (cache) {
129 const SG::ThinningDecisionBase* dec = cache->thinning (trans.key());
130 if (dec) {
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;
136 try {
137 idx = trans.index();
138 } catch ( const SG::maybe_thinning_error& err ) {
139 // ok. that's the corner case we talked about above.
140#ifdef ELLINK_DEBUG
141 msg << MSG::DEBUG << "caught a maybe_thinning_error: ["
142 << err.what() << "]"
143 << endmsg
144 << "(this is an expected case of the EL-state-phase-space "
145 << "when thinning is active)"
146 << endmsg;
147#endif
148 }
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.
154
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;
159 }
160 else {
161 Link_t tmp = trans;
162 if (!m_isPersistible) {
163 tmp.toPersistent();
164 }
165 if (!state.m_lookupTable) {
166#ifdef ELLINK_DEBUG
167 msg << MSG::ERROR
168 << "Empty link name table ptr - must use resetForCnv "
169 << endmsg;
170#endif
171 }
172 else {
173 // Save container name index and element link index
174 pers.m_contIndex = getNameIndex(state, tmp.dataID());
175 pers.m_elementIndex = persIdx;
176 }
177 }
178#ifdef ELLINK_DEBUG
179 msg << MSG::INFO << "ElementLinkCnv_p3::transToPer(): SG Container="
180 << ", Key Hash=" << pers.m_SGKeyHash
181 << ", IDX=" << pers.m_elementIndex << endmsg;
182#endif
183 return;
184 }
185 }
186
187 Link_t tmp = trans;
188 if (!m_isPersistible) {
189 tmp.toPersistent();
190 }
191 // convert string to index
192 if (!state.m_lookupTable) {
193#ifdef ELLINK_DEBUG
194 msg << MSG::ERROR
195 << "Empty link name table ptr - must use resetForCnv "
196 << endmsg;
197#endif
198 }
199 else {
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());
203 }
204#ifdef ELLINK_DEBUG
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
209 << endmsg;
210#endif
211}
212
213
214template <typename LINK_TYPE>
215void ElementLinkCnv_p2<LINK_TYPE>::
216transToPers (State& state,
217 const Link_t& trans,
218 PersLink_t& pers,
219 MsgStream& msg) const
220{
221 transToPers (state, trans, pers,
222 SG::getThinningCache(),
223 msg);
224}
225
226
227template <typename LINK_TYPE >
228inline
229void ElementLinkCnv_p2< LINK_TYPE >
230::persToTrans(State& state,
231 const PersLink_t& pers,
232 Link_t& trans,
233 MsgStream& log) const
234{
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);
239#ifdef ELLINK_DEBUG
240 if (contName) {
241 log << MSG::DEBUG << "ElementLinkCnv_p2::PersToTrans(): container name" <<
242 (*contName) << endmsg;
243 }
244 else {
245 log << MSG::ERROR << "ElementLinkCnv_p2::PersToTrans(): container name EMPTY"
246 << endmsg;
247 }
248#endif
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
253 trans.reset();
254#ifdef ELLINK_DEBUG
255 log << MSG::DEBUG << "ElementLinkCnv_p2::PersToTrans(): reading EL in Default state" << endmsg;
256#endif
257 } else {
258 // reset trans ELink with key and index - changeds to identified state
259 trans.resetWithKeyAndIndex((*contName), pers.m_elementIndex);
260
261#ifdef ELLINK_DEBUG
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;
267 }
268#endif
269 }
270}
271
272
273template <typename LINK_TYPE>
274inline
275void
276ElementLinkCnv_p2<LINK_TYPE>::resetForCnv(ElementLinkContNames_p2& lookupTable)
277{
278 // Save lookup table and reset element link index and map
279 m_state.reset (lookupTable);
280}
281
282template <typename LINK_TYPE>
283inline
284void
285ElementLinkCnv_p2<LINK_TYPE>::resetForCnv(const ElementLinkContNames_p2& lookupTable)
286{
287 // Save lookup table and reset element link index and map
288 m_state.reset (lookupTable);
289}
290
291template <typename LINK_TYPE>
292inline
293void ElementLinkCnv_p2<LINK_TYPE>::
294transToPers(const Link_t* trans, PersLink_t* pers,
295 [[maybe_unused]] MsgStream& log)
296{
297 transToPers (m_state, *trans, *pers, log);
298}
299
300
301template <typename LINK_TYPE >
302inline
303void ElementLinkCnv_p2< LINK_TYPE >
304::persToTrans(const PersLink_t* pers, Link_t* trans, MsgStream& log)
305{
306 persToTrans (m_state, *pers, *trans, log);
307}
308
309
310
311
312template <typename LINK_TYPE >
313inline
314void ElementLinkCnv_p2< LINK_TYPE >::
315persToTrans(const PersLink_t& pers, Link_t& trans, MsgStream& log) {
316 persToTrans( m_state, pers, trans, log);
317}
318
319
320template <typename LINK_TYPE >
321inline
322void ElementLinkCnv_p2< LINK_TYPE >::
323transToPers(const Link_t& trans, PersLink_t& pers, MsgStream& log) {
324 transToPers( m_state, trans, pers, log);
325}
326
327
328template <typename LINK_TYPE >
329inline
330unsigned int
331ElementLinkCnv_p2< LINK_TYPE >::getNameIndex (State& state,
332 const std::string& name) const
333{
334 // Add this name to the lookup table, retrieving and index.
335
336 unsigned int nameIndex;
337
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);
341
342 // check if name has already been added, if so use the index
343 // found, other make a new entry
344
345 // NOTE: the map is part of this converter object and not the
346 // lookup table itself
347
348 typename State::IndexMap::const_iterator it =
349 state.m_nameIndexMap.find(name);
350 if (it != state.m_nameIndexMap.end()) {
351 nameIndex = (it->second);
352 }
353 else {
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;
358 }
359
360 // Save last name and index
361
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
365 // ptrs into it.
366 state.m_lastNameIndex = nameIndex;
367 state.m_lastNameAdded = state.m_lookupTable->m_names[nameIndex];
368 return (nameIndex);
369}
370
371template <typename LINK_TYPE >
372inline
373void
374ElementLinkCnv_p2< LINK_TYPE >::getContName (State& state,
375 unsigned int nameIndex,
376 std::string const *& name,
377 MsgStream& log) const
378{
379
380 // Only need to get new name if index has changed for this element
381 // link
382 if (nameIndex == state.m_lastNameIndex) {
383 name = state.m_lastNameFound;
384 return;
385 }
386
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)
390 {
391 if (!state.m_clookupTable) {
392 log << MSG::ERROR << "Empty link name table ptr" << endmsg;
393 }
394 else {
395 log << MSG::ERROR << "Empty name vector in lookup table - looking for index "
396 << nameIndex << " size " << state.m_clookupTable->m_names.size() << endmsg;
397 }
398 return;
399 }
400 name = &(state.m_clookupTable->m_names[nameIndex]);
401
402 // Save last name and index
403 state.m_lastNameFound = name;
404 state.m_lastNameIndex = nameIndex;
405 return;
406}