ATLAS Offline Software
T_AthenaPoolViewVectorCnv.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
3 */
4 /**
5  * @file AthenaPoolCnvSvc/T_AthenaPoolViewVectorCnv.icc
6  * @author scott snyder <snyder@bnl.gov>
7  * @date Jan, 2016
8  * @brief Athena pool converter for a ViewVector class.
9  */
10 
11 
12 #include "CxxUtils/no_sanitize_undefined.h"
13 
14 
15 /**
16  * @brief Constructor.
17  * @param svcloc The Gaudi service locator.
18  */
19 template <class DV>
20 T_AthenaPoolViewVectorCnv<DV>::T_AthenaPoolViewVectorCnv (ISvcLocator* svcloc)
21  : Base (svcloc)
22 {
23 }
24 
25 
26 template <class DV>
27 std::vector<pool::Guid>
28 T_AthenaPoolViewVectorCnv<DV>::initGuids (const std::type_info& ti) const
29 {
30  std::vector<Guid> guids;
31 
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);
35  if (!typ)
36  AthenaPoolCnvSvc::throwExcNoDictForClass (ti);
37  guids.push_back (pool::DbReflex::guid (typ));
38 
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'.
44 
45  std::string name = typ.Name();
46  std::string::size_type vpos = 0;
47  while ((vpos = name.find ("_v", vpos)) != std::string::npos) {
48  vpos += 2;
49  std::string::size_type vpos2 = vpos;
50  if (isdigit (name[vpos2])) {
51  ++vpos2;
52  while (vpos2 < name.size() && isdigit (name[vpos2]))
53  ++vpos2;
54  if (vpos2 < name.size() && name[vpos2] == '>') {
55  int vers = atoi (name.substr (vpos, vpos2-vpos).c_str());
56  while (--vers > 0) {
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);
59  if (typ2)
60  guids.push_back (pool::DbReflex::guid (typ2));
61  }
62  }
63  }
64  }
65 
66  return guids;
67 }
68 
69 
70 /**
71  * @brief Standard Gaudi initialize method.
72  */
73 template <class DV>
74 StatusCode
75 T_AthenaPoolViewVectorCnv<DV>::initialize()
76 {
77  CHECK( Base::initialize() );
78 
79  m_guids = initGuids (typeid(pers_t));
80  m_guids2 = initGuids (typeid(pers2_t));
81 
82  return StatusCode::SUCCESS;
83 }
84 
85 
86 /**
87  * @brief Convert a transient object to persistent form.
88  * @param trans The transient object to convert.
89  *
90  * Returns a newly-allocated persistent object.
91  */
92 template <class DV>
93 typename T_AthenaPoolViewVectorCnv<DV>::pers_t*
94 T_AthenaPoolViewVectorCnv<DV>::createPersistent( trans_t* trans )
95 {
96  AthenaPoolCnvSvc::debugCreatePersistent (ClassID_traits<DV>::ID());
97  pers_t* pers = new pers_t (*trans);
98  pers->setClearOnPersistent();
99  return pers;
100 }
101 
102 
103 /**
104  * @brief Read the persistent object and convert it to transient.
105  *
106  * Returns a newly-allocated transient object.
107  * Errors are reported by raising exceptions.
108  */
109 template <class DV>
110 typename T_AthenaPoolViewVectorCnv<DV>::trans_t*
111 T_AthenaPoolViewVectorCnv<DV>::createTransient NO_SANITIZE_UNDEFINED ()
112 {
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.
129  delete v.release();
130  v = std::move (v2);
131  // root read rule doesn't do anything in this case.
132  v->toTransient();
133  }
134  v->clearPersistent();
135  return v.release();
136  }
137  }
138 
139 
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();
149  return vv;
150  }
151  }
152 
153  // Didn't recognize the ID.
154  AthenaPoolCnvSvc::throwExcUnsupportedVersion (typeid(pers_t),
155  this->m_i_poolToken->classID());
156  return 0;
157 }