diff --git a/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolCnvSvc.h b/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolCnvSvc.h index 31241fbe6d89c450af9a4573a123b02e113b1ae8..eb58529bd49d2fef6a4b08a316b4bb61dd7eef7a 100644 --- a/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolCnvSvc.h +++ b/Database/AthenaPOOL/AthenaPoolCnvSvc/src/AthenaPoolCnvSvc.h @@ -255,6 +255,9 @@ private: // properties StringProperty m_streamPortString{this,"StreamPortString","?pmerge=localhost:0"}; /// When using TMemFile call Write on number of Events, respecting CollectionTree auto_flush IntegerProperty m_numberEventsPerWrite{this,"NumberEventsPerWrite",-1}; + + /// Property for DataHeaderCnv input DHForm cache size + IntegerProperty m_DHFormCacheSize { this, "maxDHFormCacheSize", 100 }; }; #endif diff --git a/Database/PersistentDataModelAthenaPool/src/DataHeaderCnv.cxx b/Database/PersistentDataModelAthenaPool/src/DataHeaderCnv.cxx index b8f10827510ceaa5a2f5b2ceea6ca563f97e2eae..5ecd276e87971b92688100433903e33525647298 100755 --- a/Database/PersistentDataModelAthenaPool/src/DataHeaderCnv.cxx +++ b/Database/PersistentDataModelAthenaPool/src/DataHeaderCnv.cxx @@ -44,8 +44,21 @@ DataHeaderCnv::~DataHeaderCnv() //______________________________________________________________________________ StatusCode DataHeaderCnv::initialize() { - // listen to EndInputFile incidents to clear old DataHeaderForms from the cache - //Get IncidentSvc + m_inDHFMapMaxsize = 100; // default DHForm cache size + IConversionSvc* cnvSvc(nullptr); + if( service("AthenaPoolCnvSvc", cnvSvc, true ).isSuccess() ) { + IProperty* prop = dynamic_cast<IProperty*>( cnvSvc ); + if( prop ) { + IntegerProperty sizeProp("maxDHFormCacheSize", m_inDHFMapMaxsize); + if( prop->getProperty(&sizeProp).isSuccess() ) { + m_inDHFMapMaxsize = sizeProp.value(); + } + } + } + ATH_MSG_VERBOSE("Using DHForm cache size: " << m_inDHFMapMaxsize); + + // Listen to EndInputFile incidents to clear old DataHeaderForms from the cache + // Get IncidentSvc ServiceHandle<IIncidentSvc> incSvc("IncidentSvc", "DataHeaderCnv"); ATH_CHECK( incSvc.retrieve() ); incSvc->addListener(this, IncidentType::EndInputFile, 0); @@ -57,17 +70,24 @@ void DataHeaderCnv::handle(const Incident& incident) { if( incident.type() == IncidentType::EndInputFile ) { // remove cached DHForms that came from the file that is now being closed - const std::string& guid = static_cast<const FileIncident&>(incident).fileGuid(); - auto iter = m_persFormMap.begin(); - while( iter != m_persFormMap.end() ) { - size_t dbpos = iter->first.find("[DB="); - if( dbpos != std::string::npos && iter->first.substr(dbpos+4, dbpos+36) == guid ) { - iter = m_persFormMap.erase( iter ); - } else { - iter++; - } + const std::string& guid = static_cast<const FileIncident&>(incident).fileGuid(); + clearInputDHFormCache( guid ); + } +} + + +void DataHeaderCnv::clearInputDHFormCache( const std::string& dbGuid ) +{ + auto iter = m_inputDHForms.begin(); + while( iter != m_inputDHForms.end() ) { + size_t dbpos = iter->first.find("[DB="); + if( dbpos != std::string::npos && iter->first.substr(dbpos+4, dbpos+36) == dbGuid ) { + iter = m_inputDHForms.erase( iter ); + } else { + iter++; } } + m_inDHFormCount[ dbGuid ] = 0; } //______________________________________________________________________________ @@ -265,10 +285,20 @@ std::unique_ptr<DataHeader_p6> DataHeaderCnv::poolReadObject_p6() throw std::runtime_error("Could not get object for token = " + m_i_poolToken->toString()); } std::unique_ptr<DataHeader_p6> header( reinterpret_cast<DataHeader_p6*>(voidPtr1) ); - + // see if the DataHeaderForm is already cached - std::unique_ptr<DataHeaderForm_p6>& dh_form = m_persFormMap[ header->dhFormToken() ]; - if( !dh_form ) { + const std::string &dhFormToken = header->dhFormToken(); + if( m_inputDHForms.find(dhFormToken) == m_inputDHForms.end() ) { + // no cached DHForm + size_t dbpos = dhFormToken.find("[DB="); + if( dbpos != std::string::npos ) { + const std::string dbGuid = dhFormToken.substr(dbpos+4, dbpos+36); + if( ++m_inDHFormCount[dbGuid] > m_inDHFMapMaxsize ) { + // prevent the input DHFMap from growing too large + clearInputDHFormCache( dbGuid ); + m_inDHFormCount[dbGuid] = 1; + } + } // we need to read a new DHF void* voidPtr2 = nullptr; Token mapToken; @@ -280,7 +310,7 @@ std::unique_ptr<DataHeader_p6> DataHeaderCnv::poolReadObject_p6() throw std::runtime_error("Could not get object for token = " + mapToken.toString()); } } - dh_form.reset( reinterpret_cast<DataHeaderForm_p6*>(voidPtr2) ); + m_inputDHForms[dhFormToken].reset( reinterpret_cast<DataHeaderForm_p6*>(voidPtr2) ); } return header; } @@ -312,7 +342,7 @@ DataHeader* DataHeaderCnv::createTransient() { try { if( compareClassGuid( p6_guid ) ) { std::unique_ptr<DataHeader_p6> header( poolReadObject_p6() ); - auto dh = m_tpInConverter.createTransient( header.get(), *(m_persFormMap[ header->dhFormToken() ]) ); + auto dh = m_tpInConverter.createTransient( header.get(), *(m_inputDHForms[ header->dhFormToken() ]) ); // To dump the DataHeader uncomment below // std::ostringstream ss; dh->dump(ss); cout << ss.str() << endl; return dh; diff --git a/Database/PersistentDataModelAthenaPool/src/DataHeaderCnv.h b/Database/PersistentDataModelAthenaPool/src/DataHeaderCnv.h index 083d247389b128f518511716ad939b90592e1e22..708221ab3670fcf1b8e87bc45712e342ad41c0ad 100755 --- a/Database/PersistentDataModelAthenaPool/src/DataHeaderCnv.h +++ b/Database/PersistentDataModelAthenaPool/src/DataHeaderCnv.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration */ #ifndef DATAHEADERCNV_H @@ -55,6 +55,9 @@ public: /// Incident service handle listening for EndInputFile. virtual void handle(const Incident& incident) override; + /// Delete cached DHForms for a given input file GUID + void clearInputDHFormCache( const std::string& dbGuid ); + /// query if a new DHForm was written in the last createPersistent() bool wroteNewDHForm() { return m_wroteDHForm; } @@ -66,6 +69,13 @@ protected: /// DHForm cache indexed by filename or reference for writing std::map<std::string, std::unique_ptr<DataHeaderForm_p6> > m_persFormMap; + /// DHForm cache indexed by its parent DataHeader reference (for readinh) + std::map<std::string, std::unique_ptr<DataHeaderForm_p6> > m_inputDHForms; + + /// How many DHForms for an input file are in the cache + std::map<std::string, unsigned> m_inDHFormCount; + /// Max DHForms to cache per input file + unsigned m_inDHFMapMaxsize; /// true if the last writing of the DataHeader had to write a new DHForm bool m_wroteDHForm {false};