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;