2   Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 
    5  * @file AthenaPoolCnvSvc/T_AthenaPoolViewVectorCnv.icc
 
    6  * @author scott snyder <snyder@bnl.gov>
 
    8  * @brief Athena pool converter for a ViewVector class.
 
   12 #include "CxxUtils/no_sanitize_undefined.h"
 
   17  * @param svcloc The Gaudi service locator.
 
   20 T_AthenaPoolViewVectorCnv<DV>::T_AthenaPoolViewVectorCnv (ISvcLocator* svcloc)
 
   27 std::vector<pool::Guid>
 
   28 T_AthenaPoolViewVectorCnv<DV>::initGuids (const std::type_info& ti) const
 
   30   std::vector<Guid> guids;
 
   32   // Make a list of all the guids that this converter can read.
 
   33   // First, add the entry for pers_t.
 
   34   pool::TypeH typ = pool::DbReflex::forTypeInfo (ti);
 
   36     AthenaPoolCnvSvc::throwExcNoDictForClass (ti);
 
   37   guids.push_back (pool::DbReflex::guid (typ));
 
   39   // Now look for entries for previous versions.
 
   40   // Look for a version tag in the type name and try replacing it with
 
   41   // previous versions.  Eg, if the name for pers_t contains `_v3',
 
   42   // then we also look for guids for the same name with `_v3' replaced
 
   43   // by `_v2' and `_v1'.
 
   45   std::string name = typ.Name();
 
   46   std::string::size_type vpos = 0;
 
   47   while ((vpos = name.find ("_v", vpos)) != std::string::npos) {
 
   49     std::string::size_type vpos2 = vpos;
 
   50     if (isdigit (name[vpos2])) {
 
   52       while (vpos2 < name.size() && isdigit (name[vpos2]))
 
   54       if (vpos2 < name.size() && name[vpos2] == '>') {
 
   55         int vers = atoi (name.substr (vpos, vpos2-vpos).c_str());
 
   57           std::string name2 = name.substr(0,vpos) + CxxUtils::strformat("%d", vers) + name.substr(vpos2,std::string::npos);
 
   58           pool::TypeH typ2 = pool::DbReflex::forTypeName (name2);
 
   60             guids.push_back (pool::DbReflex::guid (typ2));
 
   71  * @brief Standard Gaudi initialize method.
 
   75 T_AthenaPoolViewVectorCnv<DV>::initialize()
 
   77   CHECK( Base::initialize() );
 
   79   m_guids = initGuids (typeid(pers_t));
 
   80   m_guids2 = initGuids (typeid(pers2_t));
 
   82   return StatusCode::SUCCESS;
 
   87  * @brief Convert a transient object to persistent form.
 
   88  * @param trans The transient object to convert.
 
   90  * Returns a newly-allocated persistent object.
 
   93 typename T_AthenaPoolViewVectorCnv<DV>::pers_t*
 
   94 T_AthenaPoolViewVectorCnv<DV>::createPersistent( trans_t* trans )
 
   96   AthenaPoolCnvSvc::debugCreatePersistent (ClassID_traits<DV>::ID());
 
   97   pers_t* pers =  new pers_t (*trans);
 
   98   pers->setClearOnPersistent();
 
  104  * @brief Read the persistent object and convert it to transient.
 
  106  * Returns a newly-allocated transient object.
 
  107  * Errors are reported by raising exceptions.
 
  110 typename T_AthenaPoolViewVectorCnv<DV>::trans_t*
 
  111 T_AthenaPoolViewVectorCnv<DV>::createTransient NO_SANITIZE_UNDEFINED ()
 
  113   AthenaPoolCnvSvc::debugCreateTransient (ClassID_traits<DV>::ID());
 
  114   // See if we're looking at one of the guids we can handle.
 
  115   // FIXME: For old persistent versions, this works by essentially doing
 
  116   // a reinterpret_cast from the version on the file to the current version.
 
  117   // That works for current ElementLink classes, but it's not very nice.
 
  118   // This also gets a ubsan warning with gcc6.2, so we suppress it
 
  119   // for this function.
 
  120   for (const pool::Guid& guid : m_guids) {
 
  121     if( this->compareClassGuid( guid ) ) {
 
  122       std::unique_ptr<pers_t> v (this->template poolReadObject< pers_t >());
 
  123       if (guid != m_guids.front()) {
 
  124         auto v2 = std::make_unique<pers_t> (*v);
 
  125         // Strictly superfluous, but allows suppressing the ubsan warning 
 
  126         // about implicit reinterpret_cast by moving the locus into this
 
  127         // function (which we've tagged with NO_SANITIZE_UNDEFINED)
 
  128         // rather than in a libtsdc++ function.
 
  131         // root read rule doesn't do anything in this case.
 
  134       v->clearPersistent();
 
  140   for (const pool::Guid& guid : m_guids2) {
 
  141     if( this->compareClassGuid( guid ) ) {
 
  142       std::unique_ptr<pers2_t> v (this->template poolReadObject< pers2_t >());
 
  143       auto c = std::make_unique<ConstDataVector<trans_t> > (*v);
 
  144       // FIXME: To get rid of this @c const_cast, the converter interfaces
 
  145       // need to be changed to allow returning a const pointer
 
  146       // all the way back to StoreGate.
 
  147       trans_t* vv ATLAS_THREAD_SAFE = const_cast<trans_t*>(c.release()->asDataVector());
 
  148       vv->clearPersistent();
 
  153   // Didn't recognize the ID.
 
  154   AthenaPoolCnvSvc::throwExcUnsupportedVersion (typeid(pers_t),
 
  155                                                 this->m_i_poolToken->classID());