diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/TPCnvList.h b/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/TPCnvList.h index 92b0f0fa7b6e202beb7295cffc444c9453810e3a..8c737fb2b25d7b77f5ce94ecb2acff0e39e10392 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/TPCnvList.h +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/TPCnvList.h @@ -73,6 +73,8 @@ class TPCnvList public: + // Coverity fails to compile this correctly. +#ifndef __COVERITY__ // Convert the list of TP converters <T1, T2, ...> to a boost fusion vector // of converters wrapped by TPCnvElt: // boost::fusion::vector<TPCnvElt<T1>, TPCnvElt<T2>, ...> @@ -81,6 +83,7 @@ public: typedef boost::mpl::vector<TPCNVS...> vec_t; typedef typename boost::mpl::transform<vec_t, wrap_tpcnv<boost::mpl::_1> >::type list_mpl_t; typedef typename boost::fusion::result_of::as_vector<list_mpl_t>::type list_t; +#endif /** @@ -111,8 +114,10 @@ public: private: +#ifndef __COVERITY__ /// List of TP converter instances, wrapped by @c TPCnvElt. list_t m_list; +#endif }; diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/TPCnvList.icc b/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/TPCnvList.icc index 129f8d67a5206cf1f12adbd3464bf3efabd2c911..699c959a00bf6e56de8be9a4618cf5cbe115d3e2 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/TPCnvList.icc +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/TPCnvList.icc @@ -90,6 +90,7 @@ bool TPCnvList<CNV, TRANS, TPCNVS...>::do_pers_to_trans::operator() } +#ifndef __COVERITY__ /** * @brief Read the persistent object and convert it to transient. * @param parent The top-level pool converter object. @@ -109,8 +110,10 @@ TRANS* TPCnvList<CNV, TRANS, TPCNVS...>::createTransient (CNV& parent, return boost::fusion::accumulate (m_list, p, do_create_transient(parent, msg)); } +#endif +#ifndef __COVERITY__ /** * @brief Read the persistent object and convert it to transient. * @param parent The top-level pool converter object. @@ -131,6 +134,7 @@ bool TPCnvList<CNV, TRANS, TPCNVS...>::persToTrans (CNV& parent, return boost::fusion::accumulate (m_list, false, do_pers_to_trans(parent, trans, msg)); } +#endif } // namespace AthenaPoolCnvSvc diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/T_AthenaPoolViewVectorCnv.h b/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/T_AthenaPoolViewVectorCnv.h index 5b533ccec24359bb85c6220fc7180635b42a4708..9d630427acc2fb4cba74425424bad3b1ad24cc09 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/T_AthenaPoolViewVectorCnv.h +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/T_AthenaPoolViewVectorCnv.h @@ -34,19 +34,27 @@ /** * @brief Athena pool converter for a ViewVector class. * - * This pool converter converts between a transient ViewVector<DV> type - * and a persistent std::vector<ElementLink<DV> > type, where DV is - * a DataVector. + * This pool converter prepares a @c ViewVector class for writing, and + * cleans up after it has been read: + * - For writing, we make a copy and call @c toPersistent on it, clearing + * the transient contents in the process. + * - For writing, we need to call @c toTransient if there was schema + * evolution. We also can remove the persistent data. + * + * It can also handle reading from a persistent type of + * @c std::vector<ElementLink<DV> >. */ template <class DV> class T_AthenaPoolViewVectorCnv - : public T_AthenaPoolCustomCnv<ViewVector<DV>, - std::vector<ElementLink<DV> > > + : public T_AthenaPoolCustomCnv<ViewVector<DV>, ViewVector<DV> > { public: /// The transient and persistent types. typedef ViewVector<DV> trans_t; - typedef std::vector<ElementLink<DV> > pers_t; + typedef trans_t pers_t; + + /// Alternate persistent type; raw vector of EL. + typedef std::vector<ElementLink<DV> > pers2_t; /// Base class. typedef T_AthenaPoolCustomCnv<trans_t, pers_t> Base; @@ -82,8 +90,21 @@ public: */ virtual trans_t* createTransient() override; + private: + /** + * @brief Return the set of GUIDs for persistent type @c ti. + * + * The first entry will be the guid for @c ti itself, followed + * by entries for any earlier persistent versions. + */ + std::vector<pool::Guid> initGuids (const std::type_info& ti) const; + + /// List of guids for @c ViewVector classes. std::vector<pool::Guid> m_guids; + + /// List of guids for @c std::vector<ElementLink<DV> > classes. + std::vector<pool::Guid> m_guids2; }; diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/T_AthenaPoolViewVectorCnv.icc b/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/T_AthenaPoolViewVectorCnv.icc index c774ea3eac3d66bc458e4be9e5af552adbde554e..ad9622ac44bd296ada4886d52cc8c063a7d6ee02 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/T_AthenaPoolViewVectorCnv.icc +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/T_AthenaPoolViewVectorCnv.icc @@ -22,21 +22,18 @@ T_AthenaPoolViewVectorCnv<DV>::T_AthenaPoolViewVectorCnv (ISvcLocator* svcloc) } -/** - * @brief Standard Gaudi initialize method. - */ template <class DV> -StatusCode -T_AthenaPoolViewVectorCnv<DV>::initialize() +std::vector<pool::Guid> +T_AthenaPoolViewVectorCnv<DV>::initGuids (const std::type_info& ti) const { - CHECK( Base::initialize() ); - + std::vector<Guid> guids; + // Make a list of all the guids that this converter can read. // First, add the entry for pers_t. - pool::TypeH typ = pool::DbReflex::forTypeInfo (typeid(pers_t)); + pool::TypeH typ = pool::DbReflex::forTypeInfo (ti); if (!typ) - AthenaPoolCnvSvc::throwExcNoDictForClass (typeid(pers_t)); - m_guids.push_back (pool::DbReflex::guid (typ)); + AthenaPoolCnvSvc::throwExcNoDictForClass (ti); + guids.push_back (pool::DbReflex::guid (typ)); // Now look for entries for previous versions. // Look for a version tag in the type name and try replacing it with @@ -59,11 +56,28 @@ T_AthenaPoolViewVectorCnv<DV>::initialize() std::string name2 = name.substr(0,vpos) + CxxUtils::strformat("%d", vers) + name.substr(vpos2,std::string::npos); pool::TypeH typ2 = pool::DbReflex::forTypeName (name2); if (typ2) - m_guids.push_back (pool::DbReflex::guid (typ2)); + guids.push_back (pool::DbReflex::guid (typ2)); } } } } + + return guids; +} + + +/** + * @brief Standard Gaudi initialize method. + */ +template <class DV> +StatusCode +T_AthenaPoolViewVectorCnv<DV>::initialize() +{ + CHECK( Base::initialize() ); + + m_guids = initGuids (typeid(pers_t)); + m_guids2 = initGuids (typeid(pers2_t)); + return StatusCode::SUCCESS; } @@ -78,10 +92,8 @@ template <class DV> typename T_AthenaPoolViewVectorCnv<DV>::pers_t* T_AthenaPoolViewVectorCnv<DV>::createPersistent( trans_t* trans ) { - // Convert to ElementLinks and apply thinning. - pers_t* pers = new pers_t (SG::dataVectorAsELV (static_cast<const DV&>(*trans))); - for (ElementLink<DV>& el : *pers) - el.thin(); + pers_t* pers = new pers_t (*trans); + pers->setClearOnPersistent(); return pers; } @@ -103,11 +115,28 @@ T_AthenaPoolViewVectorCnv<DV>::createTransient() for (const pool::Guid& guid : m_guids) { if( this->compareClassGuid( guid ) ) { std::unique_ptr<pers_t> v (this->template poolReadObject< pers_t >()); + if (guid != m_guids.front()) { + auto v2 = std::make_unique<pers_t> (*v); + v = std::move (v2); + // root read rule doesn't do anything in this case. + v->toTransient(); + } + v->clearPersistent(); + return v.release(); + } + } + + + for (const pool::Guid& guid : m_guids2) { + if( this->compareClassGuid( guid ) ) { + std::unique_ptr<pers2_t> v (this->template poolReadObject< pers2_t >()); auto c = CxxUtils::make_unique<ConstDataVector<trans_t> > (*v); // FIXME: To get rid of this @c const_cast, the converter interfaces // need to be changed to allow returning a const pointer // all the way back to StoreGate. - return const_cast<trans_t*>(c.release()->asDataVector()); + trans_t* vv = const_cast<trans_t*>(c.release()->asDataVector()); + vv->clearPersistent(); + return vv; } } diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/T_AthenaPoolxAODCnv.icc b/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/T_AthenaPoolxAODCnv.icc index d2953c029c817774e018adb79f1f04df387d0537..27deedacc145193b7d1297f34a9693b5d0f4ed5d 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/T_AthenaPoolxAODCnv.icc +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/T_AthenaPoolxAODCnv.icc @@ -79,7 +79,9 @@ XAOD* T_AthenaPoolxAODCnv<XAOD, TPCNVS...>::createTransient() } if (c) { - c->setStore( DataLink< SG::IConstAuxStore > (m_key + "Aux." ) ); + DataLink< SG::IConstAuxStore > dl; + dl.toTransient (m_key + "Aux."); + c->setStore( dl ); return c; } diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/selection_test.xml b/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/selection_test.xml index abb50d92f452859da9279f34beeaebe846e93b93..e30e1f775a32ee48540089e3f822e206df4a43bb 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/selection_test.xml +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/AthenaPoolCnvSvc/selection_test.xml @@ -7,9 +7,9 @@ id="0AAC9C99-726D-4CF4-B9F9-00B6674C57DD" /> <class name="AthenaPoolCnvSvcTest::Y_v1"/> <class name="AthenaPoolCnvSvcTest::Y_v2"/> - <class name="AthenaPoolCnvSvcTest::YCont_v1_pers" + <class name="AthenaPoolCnvSvcTest::YCont_v1_pers2" id="7E1826B9-3666-42B3-A2E7-C916BD10A5B8" /> - <class name="AthenaPoolCnvSvcTest::YCont_v2_pers" + <class name="AthenaPoolCnvSvcTest::YCont_v2_pers2" id="80C19103-FE9B-4227-8E48-8C0DB468F892" /> <class name="DataVector<AthenaPoolCnvSvcTest::Y_v1>" id="05309E49-5567-4790-BE56-2E541E0B4B24" /> @@ -20,6 +20,11 @@ <class name="AthenaPoolCnvSvcTest::YAuxCont_v2" id="170BFEE4-F6B2-4AF4-919B-7EB3986656FA" /> + <class name="ViewVector<DataVector<AthenaPoolCnvSvcTest::Y_v1> >" + id="C5454482-92F6-4EE5-BBAB-44B36D571942"/> + <class name="ViewVector<DataVector<AthenaPoolCnvSvcTest::Y_v2> >" + id="CA993B46-C358-4F5E-9EE2-3693A8F3CDAF"/> + <class name="AthenaPoolCnvSvcTest::XCont" id="6AEA6831-8777-4571-8595-95FFF40B171F" /> <class name="AthenaPoolCnvSvcTest::XCont_p1" diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/python/ReadAthenaPool.py b/Database/AthenaPOOL/AthenaPoolCnvSvc/python/ReadAthenaPool.py index 5eeb07eda43a0289f8cb3074f0dde481a0ea6939..626833bb6851ce2a5c3f4b9058401daa47bb3eb8 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/python/ReadAthenaPool.py +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/python/ReadAthenaPool.py @@ -58,6 +58,10 @@ def _configureReadAthenaPool(): # Add in EventSelector svcMgr += CfgMgr.EventSelectorAthenaPool ("EventSelector") + #default InputCollections to FilesInput value of AthenaCommonFlags + from AthenaCommon.JobProperties import jobproperties as jps + svcMgr.EventSelector.InputCollections = jps.AthenaCommonFlags.FilesInput() + _n = svcMgr.EventSelector.getFullJobOptName() theApp.EvtSel = _n del _n @@ -65,7 +69,8 @@ def _configureReadAthenaPool(): # For Analysis release use DataHeader satellite and lower heartbeat import os if "AthAnalysisBase" in os.environ.get('CMTEXTRATAGS',""): - svcMgr.EventSelector.CollectionTree = "POOLContainer/basic" + #Sep2016: disabled satellite for now, until fully debugged + #svcMgr.EventSelector.CollectionTree = "POOLContainer/basic" # From Will Buttinger to suppress the event loop heartbeat as it is somewhat I/O hungry for # no real gain in analysis scenarii if not hasattr(svcMgr, theApp.EventLoop): diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/share/T_AthenaPoolViewVectorCnv_test.ref b/Database/AthenaPOOL/AthenaPoolCnvSvc/share/T_AthenaPoolViewVectorCnv_test.ref index f4f98f093a943c8060a266507d597302ce5711f0..3afca0c5d180f4590f1aa7014be24c7198944712 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/share/T_AthenaPoolViewVectorCnv_test.ref +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/share/T_AthenaPoolViewVectorCnv_test.ref @@ -4,8 +4,8 @@ Initializing Gaudi ApplicationMgr using job opts ../share/test.txt JobOptionsSvc INFO Job options successfully read in from ../share/test.txt ApplicationMgr SUCCESS ==================================================================================================================================== - Welcome to ApplicationMgr (GaudiCoreSvc v999r999) - running on karma on Wed Jan 20 12:20:45 2016 + Welcome to ApplicationMgr (GaudiCoreSvc v27r1p99) + running on karma on Mon Oct 10 19:17:16 2016 ==================================================================================================================================== ApplicationMgr INFO Application Manager Configured successfully EventLoopMgr WARNING Unable to locate service "EventSelector" @@ -14,7 +14,8 @@ HistogramPersis...WARNING Histograms saving not required. ApplicationMgr INFO Application Manager Initialized successfully ApplicationMgr Ready test1 -AthenaPoolConve... ERROR Failed to convert persistent object to transient: AthenaPoolCnvSvc::::ExcUnsupported version: Unsupported persistent version of std::vector<ElementLink<DataVector<AthenaPoolCnvSvcTest::Y_v2,DataModel_detail::NoBase> >,std::allocator<ElementLink<DataVector<AthenaPoolCnvSvcTest::Y_v2,DataModel_detail::NoBase> > > > found; guid: 79E2478D-C17F-45E9-848D-278240C2FED3 +AthenaPoolConve... ERROR Failed to convert persistent object to transient: AthenaPoolCnvSvc::::ExcUnsupported version: Unsupported persistent version of ViewVector<DataVector<AthenaPoolCnvSvcTest::Y_v2,DataModel_detail::NoBase> > found; guid: 79E2478D-C17F-45E9-848D-278240C2FED3 AthenaPoolConve... ERROR createObj PoolToDataObject() failed, Token = [DB=00000000-0000-0000-0000-000000000000][CNT=][CLID=79E2478D-C17F-45E9-848D-278240C2FED3][TECH=00000000][OID=FFFFFFFFFFFFFFFF-FFFFFFFFFFFFFFFF] AthenaPoolConve... ERROR createObj failed to get DataObject, Token = [DB=00000000-0000-0000-0000-000000000000][CNT=][CLID=79E2478D-C17F-45E9-848D-278240C2FED3][TECH=00000000][OID=FFFFFFFFFFFFFFFF-FFFFFFFFFFFFFFFF] test2 +test3 diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolCnvSvc.cxx b/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolCnvSvc.cxx index 0d1e6ddc9a6750940e7aab405a9cabe6a9a494b7..ea9755eec01d966863481ab3b9864915d58434a5 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolCnvSvc.cxx +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolCnvSvc.cxx @@ -29,8 +29,6 @@ #include "StorageSvc/DbReflex.h" -#include <set> - //______________________________________________________________________________ // Initialize the service. StatusCode AthenaPoolCnvSvc::initialize() { @@ -174,7 +172,7 @@ StatusCode AthenaPoolCnvSvc::queryInterface(const InterfaceID& riid, void** ppvI } //______________________________________________________________________________ StatusCode AthenaPoolCnvSvc::createObj(IOpaqueAddress* pAddress, DataObject*& refpObject) { -#ifdef ATHENAHIVE +#ifdef ATHENAHIVE std::lock_guard<CallMutex> lock(m_i_mut); #endif @@ -206,7 +204,7 @@ StatusCode AthenaPoolCnvSvc::createObj(IOpaqueAddress* pAddress, DataObject*& re } //______________________________________________________________________________ StatusCode AthenaPoolCnvSvc::createRep(DataObject* pObject, IOpaqueAddress*& refpAddress) { -#ifdef ATHENAHIVE +#ifdef ATHENAHIVE std::lock_guard<CallMutex> lock(m_o_mut); #endif assert(pObject); @@ -231,7 +229,7 @@ StatusCode AthenaPoolCnvSvc::createRep(DataObject* pObject, IOpaqueAddress*& ref } } else { // Forward to base class createRep - try { + try { status = ::AthCnvSvc::createRep(pObject, refpAddress); } catch(std::runtime_error& e) { ATH_MSG_FATAL(e.what()); @@ -272,7 +270,7 @@ StatusCode AthenaPoolCnvSvc::fillRepRefs(IOpaqueAddress* pAddress, DataObject* p status = ::AthCnvSvc::fillRepRefs(pAddress, pObject); } catch(std::runtime_error& e) { ATH_MSG_FATAL(e.what()); - } + } } if (m_useDetailChronoStat.value() && m_doChronoStat) { std::string objName = m_className.back(); @@ -381,20 +379,29 @@ StatusCode AthenaPoolCnvSvc::commitOutput(const std::string& /*outputConnectionS return(StatusCode::FAILURE); } // Deserialize object - Guid classId(std::string(strstr(placementStr, "[PCLID=")).substr(7, 36)); - const void* obj = m_serializeSvc->deserialize(buffer, nbytes, classId); + std::string className = strstr(placementStr, "[PNAME="); + className = className.substr(7, className.find(']') - 7); + RootType classDesc = RootType::ByName(className); + void* obj = 0; + if (className == "Token") { + obj = buffer; static_cast<char*>(obj)[nbytes - 1] = 0; buffer = 0; + } else if (classDesc.IsFundamental()) { + obj = buffer; buffer = 0; + } else { + obj = m_serializeSvc->deserialize(buffer, nbytes, classDesc); + } // Write object Placement placement; placement.fromString(placementStr); delete placementStr; placementStr = 0; - const Token* token = this->registerForWrite(&placement, obj, pool::DbReflex::forGuid(classId)); + const Token* token = this->registerForWrite(&placement, obj, classDesc); if (token == 0) { - ATH_MSG_ERROR("Failed to write Data for: " << classId.toString()); + ATH_MSG_ERROR("Failed to write Data for: " << className); return(StatusCode::FAILURE); } // For DataHeaderForm, Token needs to be inserted to DataHeader Object - if (classId == "3397D8A3-BBE6-463C-9F8E-4B3DFD8831FE") { + if (className == "DataHeaderForm_p5") { GenericAddress address(POOL_StorageType, ClassID_traits<DataHeader>::ID(), token->toString(), placement.auxString()); IConverter* cnv = converter(ClassID_traits<DataHeader>::ID()); if (!cnv->updateRepRefs(&address, (DataObject*)obj).isSuccess()) { @@ -405,7 +412,7 @@ StatusCode AthenaPoolCnvSvc::commitOutput(const std::string& /*outputConnectionS } // Found DataHeader - if (classId == "D82968A1-CF91-4320-B2DD-E0F739CBC7E6") { + if (className == "DataHeader_p5") { GenericAddress address(POOL_StorageType, ClassID_traits<DataHeader>::ID(), token->toString(), placement.auxString()); IConverter* cnv = converter(ClassID_traits<DataHeader>::ID()); if (!cnv->updateRep(&address, (DataObject*)obj).isSuccess()) { @@ -536,9 +543,9 @@ std::string AthenaPoolCnvSvc::getOutputContainer(const std::string& typeName, if (typeName.substr(0, 13) == "AttributeList") { return(m_collContainerPrefix + "(" + key + ")"); } - if (key.empty()) { - return(m_containerPrefix + typeName); - } + if (key.empty()) { + return(m_containerPrefix + typeName); + } const std::string typeTok = "<type>", keyTok = "<key>"; std::string ret = m_containerPrefix + m_containerNameHint; if (!m_branchNameHint.empty()) { @@ -577,8 +584,7 @@ const Token* AthenaPoolCnvSvc::registerForWrite(const Placement* placement, if (!m_outputStreamingTool.empty() && m_outputStreamingTool->isClient()) { ATH_MSG_VERBOSE("Requesting write object for: " << placement->toString()); // Lock object - Guid classID = pool::DbReflex::guid(classDesc); - std::string placementStr = placement->toString() + "[PCLID=" + classID.toString() + "]"; + std::string placementStr = placement->toString() + "[PNAME=" + classDesc.Name() + "]"; StatusCode sc = m_outputStreamingTool->lockObject(placementStr.c_str()); while (sc.isRecoverable()) { usleep(100); @@ -589,16 +595,22 @@ const Token* AthenaPoolCnvSvc::registerForWrite(const Placement* placement, return(0); } // Serialize object via ROOT - void* buffer = 0; + const void* buffer = 0; size_t nbytes = 0; - buffer = m_serializeSvc->serialize(obj, classID, nbytes); + if (classDesc.Name() == "Token") { + buffer = obj; nbytes = strlen(static_cast<const char*>(obj)) + 1; + } else if (classDesc.IsFundamental()) { + buffer = obj; nbytes = classDesc.SizeOf(); + } else { + buffer = m_serializeSvc->serialize(obj, classDesc, nbytes); + } // Share object sc = m_outputStreamingTool->putObject(buffer, nbytes); while (sc.isRecoverable()) { usleep(100); sc = m_outputStreamingTool->putObject(buffer, nbytes); } - if (!sc.isSuccess()) { + if (!sc.isSuccess() || !m_outputStreamingTool->putObject(0, 0).isSuccess()) { ATH_MSG_ERROR("Failed to put Data for " << placementStr); return(0); } @@ -813,15 +825,19 @@ StatusCode AthenaPoolCnvSvc::readData() const { if (token.classID() != Guid::null()) { this->setObjPtr(instance, &token); // Serialize object via ROOT + RootType cltype(pool::DbReflex::forGuid(token.classID())); void* buffer = 0; size_t nbytes = 0; - buffer = m_serializeSvc->serialize(instance, token.classID(), nbytes); - // Share object - sc = m_inputStreamingTool->putObject(buffer, nbytes, num); - delete [] (char*)buffer; buffer = 0; - if (!sc.isSuccess()) { - ATH_MSG_ERROR("Could not share object for: " << token.toString()); - return(StatusCode::FAILURE); + buffer = m_serializeSvc->serialize(instance, cltype, nbytes); + cltype.Destruct(instance); instance = 0; + // Share object (if not store object) + if (buffer != 0) { + sc = m_inputStreamingTool->putObject(buffer, nbytes, num); + delete [] (char*)buffer; buffer = 0; + if (!sc.isSuccess() || !m_inputStreamingTool->putObject(0, 0, num).isSuccess()) { + ATH_MSG_ERROR("Could not share object for: " << token.toString()); + return(StatusCode::FAILURE); + } } } else if (token.dbID() != Guid::null()) { std::string returnToken; @@ -838,7 +854,7 @@ StatusCode AthenaPoolCnvSvc::readData() const { usleep(100); sc = m_inputStreamingTool->putObject(returnToken.c_str(), returnToken.size() + 1, num); } - if (!sc.isSuccess()) { + if (!sc.isSuccess() || !m_inputStreamingTool->putObject(0, 0, num).isSuccess()) { ATH_MSG_ERROR("Could not share token for: " << token.toString()); return(StatusCode::FAILURE); } diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolCnvSvc.h b/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolCnvSvc.h index 97b0c566581dd12e011aa9affb2c619760fe9ba5..80c894772222385b3769506ea325fd064d01bbac 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolCnvSvc.h +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolCnvSvc.h @@ -193,8 +193,8 @@ private: // data ServiceHandle<IChronoStatSvc> m_chronoStatSvc; ServiceHandle<IClassIDSvc> m_clidSvc; ServiceHandle<IAthenaSerializeSvc> m_serializeSvc; - ToolHandle<IAthenaIPCTool> m_inputStreamingTool; - ToolHandle<IAthenaIPCTool> m_outputStreamingTool; + mutable ToolHandle<IAthenaIPCTool> m_inputStreamingTool; + mutable ToolHandle<IAthenaIPCTool> m_outputStreamingTool; private: // properties /// UseDetailChronoStat, enable detailed output for time and size statistics for AthenaPOOL: diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaRootSerializeSvc.cxx b/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaRootSerializeSvc.cxx index c63de7058896f05f9106c09378ff068a90e19a90..592aaf3e226fedd8e075f1f7e1aa2042fd6500b4 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaRootSerializeSvc.cxx +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaRootSerializeSvc.cxx @@ -57,6 +57,11 @@ void* AthenaRootSerializeSvc::serialize(const void* /*object*/, const std::strin //___________________________________________________________________________ void* AthenaRootSerializeSvc::serialize(const void* object, const Guid& id, size_t& nbytes) { RootType cltype(pool::DbReflex::forGuid(id)); + return(this->serialize(object, cltype, nbytes)); +} + +//___________________________________________________________________________ +void* AthenaRootSerializeSvc::serialize(const void* object, const RootType& cltype, size_t& nbytes) { TBufferFile writeBuffer(TBuffer::kWrite); writeBuffer.WriteObjectAny(object, cltype); void* buffer = writeBuffer.Buffer(); @@ -66,14 +71,20 @@ void* AthenaRootSerializeSvc::serialize(const void* object, const Guid& id, size } //___________________________________________________________________________ -void* AthenaRootSerializeSvc::deserialize(void* /*buffer*/, size_t /*nbytes*/, const std::string& /*name*/) { +void* AthenaRootSerializeSvc::deserialize(void* /*buffer*/, size_t& /*nbytes*/, const std::string& /*name*/) { return(0); } //___________________________________________________________________________ -void* AthenaRootSerializeSvc::deserialize(void* buffer, size_t nbytes, const Guid& id) { +void* AthenaRootSerializeSvc::deserialize(void* buffer, size_t& nbytes, const Guid& id) { RootType cltype(pool::DbReflex::forGuid(id)); + return(this->deserialize(buffer, nbytes, cltype)); +} + +//___________________________________________________________________________ +void* AthenaRootSerializeSvc::deserialize(void* buffer, size_t& nbytes, const RootType& cltype) { TBufferFile readBuffer(TBuffer::kRead, nbytes, buffer, kTRUE); void* obj = readBuffer.ReadObjectAny(cltype); + nbytes = readBuffer.Length(); return(obj); } diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaRootSerializeSvc.h b/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaRootSerializeSvc.h index 9eddf084377b5247ca41bc9a5e9c36921403d018..3c3177ab46d8ab6b609f74555a89ce5f2d8e456b 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaRootSerializeSvc.h +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaRootSerializeSvc.h @@ -33,9 +33,11 @@ public: void* serialize(const void* object, const std::string& name, size_t& nbytes); void* serialize(const void* object, const Guid& id, size_t& nbytes); + void* serialize(const void* object, const RootType& cltype, size_t& nbytes); - void* deserialize(void* buffer, size_t nbytes, const std::string& name); - void* deserialize(void* buffer, size_t nbytes, const Guid& id); + void* deserialize(void* buffer, size_t& nbytes, const std::string& name); + void* deserialize(void* buffer, size_t& nbytes, const Guid& id); + void* deserialize(void* buffer, size_t& nbytes, const RootType& cltype); }; #endif diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/test/AthenaPoolCnvSvcTestDict.h b/Database/AthenaPOOL/AthenaPoolCnvSvc/test/AthenaPoolCnvSvcTestDict.h index 7cda5404718cb924ea6baa80c78d99aba669b596..d96da70b30953d6e80eda2c1f7db6fa7edae5bf3 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/test/AthenaPoolCnvSvcTestDict.h +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/test/AthenaPoolCnvSvcTestDict.h @@ -73,6 +73,7 @@ struct Y_v2 : public SG::AuxElement { Y_v2(int a) : m_a(a) {} + ~Y_v2() {} int m_a; }; @@ -104,8 +105,8 @@ CLASS_DEF(AthenaPoolCnvSvcTest::XCont, 524263046, 1) namespace AthenaPoolCnvSvcTest { -typedef std::vector<ElementLink<DataVector<Y_v1> > > YCont_v1_pers; -typedef std::vector<ElementLink<DataVector<Y_v2> > > YCont_v2_pers; +typedef std::vector<ElementLink<DataVector<Y_v1> > > YCont_v1_pers2; +typedef std::vector<ElementLink<DataVector<Y_v2> > > YCont_v2_pers2; diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/test/T_AthenaPoolViewVectorCnv_test.cxx b/Database/AthenaPOOL/AthenaPoolCnvSvc/test/T_AthenaPoolViewVectorCnv_test.cxx index e8eacc3d401af56ec9502c77203a722a155bc016..7bd5562ed2185112d359fbb4fb7a230345dd77c0 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/test/T_AthenaPoolViewVectorCnv_test.cxx +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/test/T_AthenaPoolViewVectorCnv_test.cxx @@ -33,8 +33,62 @@ using namespace AthenaPoolCnvSvcTest; -std::string YCont_v1_guid = "7E1826B9-3666-42B3-A2E7-C916BD10A5B8"; -std::string YCont_v2_guid = "80C19103-FE9B-4227-8E48-8C0DB468F892"; +std::string YCont_v1_guid2 = "7E1826B9-3666-42B3-A2E7-C916BD10A5B8"; +std::string YCont_v2_guid2 = "80C19103-FE9B-4227-8E48-8C0DB468F892"; +std::string YCont_v1_guid = "C5454482-92F6-4EE5-BBAB-44B36D571942"; +std::string YCont_v2_guid = "CA993B46-C358-4F5E-9EE2-3693A8F3CDAF"; + + +class ViewVectorBaseTest +{ +public: + static void check (const SG::ViewVectorBase& vvb, SG::sgkey_t sgkey); + static void checkPersThinned (const SG::ViewVectorBase& vvb, SG::sgkey_t sgkey); + static void checkPersEmpty (const SG::ViewVectorBase& vvb); +}; + + +void ViewVectorBaseTest::check (const SG::ViewVectorBase& vvb, + SG::sgkey_t sgkey) +{ + assert (vvb.m_persKey.size() == 10); + assert (vvb.m_persIndex.size() == 10); + for (unsigned int i = 0; i < 10; i++) { + assert (vvb.m_persKey[i] == sgkey); + assert (vvb.m_persIndex[i] == 9-i); + } +} + + +void ViewVectorBaseTest::checkPersThinned (const SG::ViewVectorBase& vvb, + SG::sgkey_t sgkey) +{ + size_t sz = 10; + assert (vvb.m_persKey.size() == sz); + assert (vvb.m_persIndex.size() == sz); + for (size_t i = 0; i < sz; i++) { + SG::sgkey_t pkey = vvb.m_persKey[i]; + size_t pindex = vvb.m_persIndex[i]; + if (i == 5) { + assert (pkey == 0); + assert (pindex == 0); + } + else { + assert (pkey == sgkey); + if (i < 5) + assert (pindex == i); + else + assert (pindex == i-1); + } + } +} + + +void ViewVectorBaseTest::checkPersEmpty (const SG::ViewVectorBase& vvb) +{ + assert (vvb.m_persKey.empty()); + assert (vvb.m_persIndex.empty()); +} class TestCnvSvc @@ -43,23 +97,34 @@ class TestCnvSvc public: TestCnvSvc (const std::string& name, ISvcLocator* svcloc) : TestCnvSvcBase (name, svcloc), - m_pers (nullptr) + m_pers (nullptr), + m_pers_old (nullptr) {} - virtual void setObjPtr(void*& obj, const Token* /*token*/) const override + virtual void setObjPtr(void*& obj, const Token* token) const override { - obj = new YCont_v2_pers (*m_pers); + if (m_pers) { + auto vvb = new ViewVector<DataVector<Y_v2> > (*m_pers); + if (token->classID() == Guid(YCont_v2_guid)) + vvb->toTransient(); + obj = vvb; + } + else if (m_pers_old) { + obj = new YCont_v2_pers2 (*m_pers_old); + } } std::string m_name; - YCont_v2_pers* m_pers; + ViewVector<DataVector<Y_v2> >* m_pers; + YCont_v2_pers2* m_pers_old; }; void test1 (ISvcLocator* svcloc, TestCnvSvc& testsvc, DataVector<Y_v2>& vec) { std::cout << "test1\n"; - + SG::sgkey_t sgkey = + SGTest::store.stringToKey ("vec", ClassID_traits<DataVector<Y_v2> >::ID()); T_AthenaPoolCnv<ViewVector<DataVector<Y_v2> > > cnv (svcloc); assert (cnv.initialize().isSuccess()); @@ -68,12 +133,10 @@ void test1 (ISvcLocator* svcloc, TestCnvSvc& testsvc, DataVector<Y_v2>& vec) for (size_t i = 0; i < sz; i++) view.push_back (vec[sz-i-1]); - YCont_v2_pers* pers = cnv.createPersistent (&view); - assert (pers->size() == sz); - for (size_t i = 0; i < sz; i++) { - assert ((*pers)[i].dataID() == "vec"); - assert ((*pers)[i].index() == sz-i-1); - } + ViewVector<DataVector<Y_v2> >* pers = cnv.createPersistent (&view); + pers->toPersistent(); + ViewVectorBaseTest::check (*pers, sgkey); + assert (pers->size() == 0); testsvc.m_pers = pers; Token* token = new Token; @@ -86,17 +149,20 @@ void test1 (ISvcLocator* svcloc, TestCnvSvc& testsvc, DataVector<Y_v2>& vec) assert (trans1->size() == 10); for (size_t i = 0; i < sz; i++) assert ((*trans1)[i] == view[i]); + ViewVectorBaseTest::checkPersEmpty (*trans1); delete pObj; pObj = nullptr; delete pers; testsvc.m_pers = nullptr; - YCont_v2_pers pers1; + ViewVector<DataVector<Y_v2> > pers1; size_t ii = 0; for (size_t i = 0; i < sz; i++, ii+=2) { if (ii >= sz) ii = 1; - pers1.emplace_back ("vec", ii); + pers1.push_back (vec[ii]); } + pers1.setClearOnPersistent(); + pers1.toPersistent(); testsvc.m_pers = &pers1; token->setClassID (Guid (YCont_v1_guid)); assert (cnv.createObj (&taddr, pObj).isSuccess()); @@ -107,6 +173,7 @@ void test1 (ISvcLocator* svcloc, TestCnvSvc& testsvc, DataVector<Y_v2>& vec) if (ii >= sz) ii = 1; assert ((*trans2)[i] == vec[ii]); } + ViewVectorBaseTest::checkPersEmpty (*trans2); delete trans2; token->setClassID (Guid ("79E2478D-C17F-45E9-848D-278240C2FED3")); @@ -114,12 +181,65 @@ void test1 (ISvcLocator* svcloc, TestCnvSvc& testsvc, DataVector<Y_v2>& vec) } -// Test with thinning. -void test2 (ISvcLocator* svcloc, TestCnvSvc& /*testsvc*/, DataVector<Y_v2>& vec) +// Test reading std::vector<EL> +void test2 (ISvcLocator* svcloc, TestCnvSvc& testsvc, DataVector<Y_v2>& vec) { std::cout << "test2\n"; + T_AthenaPoolCnv<ViewVector<DataVector<Y_v2> > > cnv (svcloc); + assert (cnv.initialize().isSuccess()); size_t sz = vec.size(); + std::vector<ElementLink<DataVector<Y_v2> > > pers2; + size_t ii = 0; + for (size_t i = 0; i < sz; i++, ii+=2) { + if (ii >= sz) ii = 1; + pers2.emplace_back ("vec", ii); + } + + testsvc.m_pers = nullptr; + testsvc.m_pers_old = &pers2; + Token* token = new Token; + token->setClassID (Guid (YCont_v2_guid2)); + TokenAddress taddr (0, 0, "", "", 0, token); + + DataObject* pObj; + assert (cnv.createObj (&taddr, pObj).isSuccess()); + auto* trans2 = SG::Storable_cast<ViewVector<DataVector<Y_v2> > > (pObj); + assert (trans2->size() == 10); + ii = 0; + for (size_t i = 0; i < sz; i++, ii+=2) { + if (ii >= sz) ii = 1; + assert ((*trans2)[i] == vec[ii]); + } + ViewVectorBaseTest::checkPersEmpty (*trans2); + delete pObj; + pObj = nullptr; + + std::vector<ElementLink<DataVector<Y_v2> > > pers1; + for (size_t i = 0; i < sz; i++) + pers1.emplace_back ("vec", i); + testsvc.m_pers_old = &pers1; + token->setClassID (Guid (YCont_v1_guid2)); + assert (cnv.createObj (&taddr, pObj).isSuccess()); + auto* trans1 = SG::Storable_cast<ViewVector<DataVector<Y_v2> > > (pObj); + assert (trans1->size() == 10); + for (size_t i = 0; i < sz; i++) + assert ((*trans1)[i] == vec[i]); + ViewVectorBaseTest::checkPersEmpty (*trans1); + delete pObj; + pObj = nullptr; + testsvc.m_pers_old = nullptr; +} + + +// Test with thinning. +void test3 (ISvcLocator* svcloc, TestCnvSvc& /*testsvc*/, DataVector<Y_v2>& vec) +{ + std::cout << "test3\n"; + size_t sz = vec.size(); + SG::sgkey_t sgkey = + SGTest::store.stringToKey ("vec", ClassID_traits<DataVector<Y_v2> >::ID()); + TestThinningSvc thinsvc; TestThinningSvc::instance (&thinsvc, true); thinsvc.remap (&vec, 5, IThinningSvc::RemovedIdx); @@ -133,22 +253,9 @@ void test2 (ISvcLocator* svcloc, TestCnvSvc& /*testsvc*/, DataVector<Y_v2>& vec) for (size_t i = 0; i < sz; i++) view.push_back (vec[i]); - YCont_v2_pers* pers = cnv.createPersistent (&view); - assert (pers->size() == sz); - for (size_t i = 0; i < sz; i++) { - const ElementLink<DataVector<Y_v2> >& l = (*pers)[i]; - if (i == 5) { - assert (l.key() == 0); - assert (l.index() == 0); - } - else { - assert (l.dataID() == "vec"); - if (i < 5) - assert (l.index() == i); - else - assert (l.index() == i-1); - } - } + ViewVector<DataVector<Y_v2> >* pers = cnv.createPersistent (&view); + pers->toPersistent(); + ViewVectorBaseTest::checkPersThinned (*pers, sgkey); delete pers; } @@ -183,5 +290,6 @@ int main() DataVector<Y_v2>& vec = makeVecs(); test1 (pSvcLoc, *svc, vec); test2 (pSvcLoc, *svc, vec); + test3 (pSvcLoc, *svc, vec); }