Commit a98119b5 authored by Atlas-Software Librarian's avatar Atlas-Software Librarian Committed by Graeme Stewart
Browse files

'CMakeLists.txt' (TrigSerializeTP-00-02-11)

	* Did a major cleanup in the TrigSerTPTool source code. Removing
	  all functions and variables that I deemed unnecessary.
	* Explicitly including the types in the header now that we declare
	  ServiceHandles for. Since Gaudi has the tendency of introducing
	  this requirement these days. (Currently battling such an issue
	  with ToolHandles.)
	* Taught the tool how to make use of trigger specific T/P converters,
	  which we introduced to support using trigger specific auxiliary
	  containers with some offline types at Point1.
	* Tagging as TrigSerializeTP-00-02-11

2015-04-09  scott snyder  <snyder@bnl.gov>

	* Tagging TrigSerializeTP-00-02-10.
	* AthenaBaseComps migration.
parent 0e2ccf65
################################################################################
# Package: TrigSerializeTP
################################################################################
# Declare the package name:
atlas_subdir( TrigSerializeTP )
# Declare the package's dependencies:
atlas_depends_on_subdirs( PUBLIC
Control/AthenaBaseComps
Control/AthenaKernel
GaudiKernel
PRIVATE
Control/CxxUtils )
# External dependencies:
find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread )
# Component(s) in the package:
atlas_add_library( TrigSerializeTPLib
src/*.cxx
PUBLIC_HEADERS TrigSerializeTP
PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
LINK_LIBRARIES AthenaBaseComps AthenaKernel GaudiKernel
PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} CxxUtils )
atlas_add_component( TrigSerializeTP
src/components/*.cxx
INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps AthenaKernel GaudiKernel CxxUtils TrigSerializeTPLib )
......@@ -4,74 +4,69 @@
Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
*/
/**
* @class TrigSerTPTool
* @author Jiri Masik <Jiri.Masik@cern.ch>
* based on the code of AthenaROOTAccess by Scott Snyder
*/
// $Id$
#ifndef TRIGSERIALIZETP_TRIGSERTPTOOL_H
#define TRIGSERIALIZETP_TRIGSERTPTOOL_H 1
#include "GaudiKernel/AlgTool.h"
#include "GaudiKernel/ServiceHandle.h"
#include "GaudiKernel/ClassID.h"
// System include(s):
#include <string>
#include <vector>
#include <map>
#include <memory>
// Gaudi/Athena include(s):
#include "GaudiKernel/ServiceHandle.h"
#include "GaudiKernel/MsgStream.h"
#include "GaudiKernel/IMessageSvc.h"
#include "AthenaKernel/IDictLoaderSvc.h"
#include "AthenaKernel/ITPCnvSvc.h"
#include "AthenaBaseComps/AthAlgTool.h"
class MsgStream;
class TClass;
class ITPCnvBase;
class IMessageSvc;
class IDictLoaderSvc;
class ITPCnvSvc;
/**
* @class TrigSerTPTool
* @author Jiri Masik <Jiri.Masik@cern.ch>
* based on the code of AthenaROOTAccess by Scott Snyder
*/
class TrigSerTPTool : public AthAlgTool {
class TrigSerTPTool : public AlgTool {
public:
static const InterfaceID& interfaceID( ) {
static const InterfaceID
IID_TrigSerTPTool("TrigSerTPTool", 1, 0);
return IID_TrigSerTPTool;
}
TrigSerTPTool(const std::string& type, const std::string& name,
const IInterface* parent);
StatusCode initialize();
void* convertTP(const std::string &transName, void *trans, std::string &persName);
void* convertPT(const std::string &persName, void *pers, std::string &transName);
std::string persClassName(const std::string &transClassName);
std::string persClassNameFromCnv(const std::string &cnvname) const;
StatusCode finalize();
~TrigSerTPTool();
private:
StatusCode initCnvter();
StatusCode forceDictLoading(const std::string &clname) const;
StatusCode testTPCnv(const std::string &clname);
TClass* getClass(const std::string &clname) const;
/// Declare the interface provided by the tool
static const InterfaceID& interfaceID( ) {
static const InterfaceID
IID_TrigSerTPTool("TrigSerTPTool", 1, 0);
return IID_TrigSerTPTool;
}
/// Standard AlgTool constructor
TrigSerTPTool( const std::string& type, const std::string& name,
const IInterface* parent );
/// Function initialising the tool
virtual StatusCode initialize();
/// Convert a transient object to its persistent self
void* convertTP( const std::string& transName, void* trans,
std::string& persName );
/// Convert a persistent object to its transient self
void* convertPT( const std::string& persName, void* pers,
std::string& transName );
/// Get the name of the persistent class belonging to a transient one
const std::string& persClassName( const std::string& transClassName ) const;
private:
MsgStream *m_log;
MsgStream *m_logTP;
std::map<std::string, std::string> m_TPmap; //configure - lookup of
std::map<std::string, std::string> m_PTmap; //
TClass *m_tpCnvBaseClass;
std::map<std::string, ITPCnvBase*> m_convBasePtr;
std::map<void*, TClass*> m_convObj;
std::vector<std::string> m_activeClasses;
ServiceHandle<IMessageSvc> m_msgsvcTP;
ServiceHandle<IDictLoaderSvc> m_dictSvc;
bool m_useAthDictLoader;
bool m_online;
ServiceHandle<ITPCnvSvc> m_tpcnvsvc;
};
/// Get the ROOT dictionary for a type
TClass* getClass( const std::string& clname ) const;
std::unique_ptr< MsgStream > m_logTP;
std::map< std::string, std::string > m_TPmap; //configure - lookup of
std::vector< std::string > m_activeClasses;
ServiceHandle< IMessageSvc > m_msgsvcTP;
ServiceHandle< IDictLoaderSvc > m_dictSvc;
bool m_useAthDictLoader;
bool m_online;
ServiceHandle< ITPCnvSvc > m_tpcnvsvc;
}; // class TrigSerTPTool
#endif // !TRIGSERIALIZETP_TRIGSERTPTOOL_H
......@@ -2,12 +2,12 @@ package TrigSerializeTP
use AtlasPolicy AtlasPolicy-*
use GaudiInterface GaudiInterface-* External
use AthenaBaseComps AthenaBaseComps-* Control
use AthenaKernel AthenaKernel-* Control
apply_pattern dual_use_library files=*.cxx
private
use DataModel DataModel-* Control
use AthenaKernel AthenaKernel-* Control
use CxxUtils CxxUtils-* Control
use AtlasROOT AtlasROOT-* External
use AthenaPoolCnvSvc AthenaPoolCnvSvc-* Database/AthenaPOOL
end_private
......@@ -2,284 +2,209 @@
Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
*/
#include "TrigSerializeTP/TrigSerTPTool.h"
// $Id$
//TP
#include "AthenaPoolCnvSvc/ITPConverter.h"
#include "AthenaPoolCnvSvc/AthenaPoolTopLevelTPCnvBase.h"
// ROOT include(s):
#include <TClass.h>
#include "AthenaKernel/getMessageSvc.h"
// Gaudi/Athena include(s):
#include "GaudiKernel/System.h"
#include "AthenaKernel/IDictLoaderSvc.h"
#include "AthenaKernel/ITPCnvSvc.h"
#include "AthenaKernel/ITPCnvBase.h"
#include "AthenaKernel/errorcheck.h"
#include "CxxUtils/make_unique.h"
#include "GaudiKernel/MsgStream.h"
#include "GaudiKernel/IMessageSvc.h"
#include "GaudiKernel/System.h"
#include "DataModel/Arena.h"
//ROOT
#include "TROOT.h"
#include "TClass.h"
#include "TBaseClass.h"
#include <iostream>
#include <algorithm>
using std::map;
using std::string;
// Local include(s):
#include "TrigSerializeTP/TrigSerTPTool.h"
TrigSerTPTool::TrigSerTPTool( const std::string& type,
const std::string& name,
const IInterface* parent) :
AlgTool(type,name,parent),
m_log(0),
m_logTP(0),
m_tpCnvBaseClass(0),
m_msgsvcTP("",name),
m_dictSvc("AthDictLoaderSvc",name),
m_useAthDictLoader(true),
m_online(false),
m_tpcnvsvc("AthTPCnvSvc", name)
{
declareInterface<TrigSerTPTool>(this);
declareProperty("TPMap", m_TPmap, "map of T->P classes" );
declareProperty("ActiveClasses", m_activeClasses, "allows to skip classes not relevant in the current trigger level");
declareProperty("debuggingMsgSvc", m_msgsvcTP, "an instance of the messageSvc for debugging purposes");
declareProperty("onlineMode", m_online, "simpler setup for running online");
declareProperty("useAthDictLoader", m_useAthDictLoader, "use AthDictLoaderSvc instead of plain ROOT");
m_log = new MsgStream(msgSvc(), name);
}
TrigSerTPTool::~TrigSerTPTool(){
if (m_logTP!=m_log)
delete m_logTP;
delete m_log;
}
TClass *TrigSerTPTool::getClass(const std::string &cname) const {
TClass *cl(0);
if (m_useAthDictLoader && m_dictSvc){
m_dictSvc->load_type(cname);
}
cl = gROOT->GetClass(cname.c_str());
return cl;
AthAlgTool( type, name, parent ),
m_msgsvcTP( "", name ),
m_dictSvc( "AthDictLoaderSvc", name ),
m_useAthDictLoader( true ),
m_online( false ),
m_tpcnvsvc( "AthTPCnvSvc", name ) {
declareInterface< TrigSerTPTool >( this );
declareProperty( "TPMap", m_TPmap, "map of T->P classes" );
declareProperty( "ActiveClasses", m_activeClasses,
"allows to skip classes not relevant in the current "
"trigger level" );
declareProperty( "debuggingMsgSvc", m_msgsvcTP,
"an instance of the messageSvc for debugging purposes" );
declareProperty( "onlineMode", m_online,
"simpler setup for running online" );
declareProperty( "useAthDictLoader", m_useAthDictLoader,
"use AthDictLoaderSvc instead of plain ROOT" );
}
StatusCode TrigSerTPTool::initialize(){
// std::cout << "TrigSerTPTool::initialize: " << name() << ":" << msgSvc()->outputLevel(name()) << std::endl;
m_log->setLevel(msgSvc()->outputLevel(name()));
*m_log << MSG::INFO << "in initialize " << name() << endreq;
//a special instance of the MessageSvc for the T/P
m_logTP = m_log;
if(!m_msgsvcTP.empty()){
if (m_msgsvcTP.retrieve().isFailure()){
*m_log << MSG::INFO << "Could not retrieve a separate MsgSvc for the T/P debugging" << endreq;
} else {
*m_log << MSG::DEBUG << "Using " << m_msgsvcTP << " for debugging " << endreq;
IMessageSvc* msvc = m_msgsvcTP.operator->();
m_logTP = new MsgStream(msvc, "TrigSerTPTool-T/P");
}
}
if (!m_dictSvc.retrieve().isSuccess()) {
*m_log << MSG::ERROR << "could not retrieve athena dict. loader service !" << endreq;
return StatusCode::FAILURE;
}
if (!m_tpcnvsvc.retrieve().isSuccess()) {
*m_log << MSG::ERROR << "could not retrieve T/P cnv svc" << endmsg;
return StatusCode::FAILURE;
}
m_tpCnvBaseClass = getClass ("ITPCnvBase");
if (!m_tpCnvBaseClass ) {
*m_log << MSG::DEBUG << "Cannot find class ITPCnvBase" << endreq;
} else {
*m_log << MSG::DEBUG << "Found class ITPCnvBase" << endreq;
}
return StatusCode::SUCCESS;
}
StatusCode TrigSerTPTool::finalize(){
map <void*,TClass*>::const_iterator mit(m_convObj.begin());
map <void*,TClass*>::const_iterator mend(m_convObj.end());
while (mit!=mend){
void *p = (*mit).first;
TClass *cl = (*mit).second;
if (cl && p){
// *m_log << MSG::DEBUG << "cl=" << cl << " p=" << p << endreq;
cl->Destructor(p);
}
mit++;
}
m_convObj.clear();
return StatusCode::SUCCESS;
}
StatusCode TrigSerTPTool::forceDictLoading(const std::string &clname) const {
TClass *cl = getClass(clname);
if (!cl){
*m_log << MSG::DEBUG << "Dict loading of " << clname << " failed" << endreq;
return StatusCode::FAILURE;
} else {
void *p = cl->New();
cl->Destructor(p);
}
return StatusCode::SUCCESS;
// Greet the user:
ATH_MSG_INFO( "Initializing - Package version: " << PACKAGE_VERSION );
// Retrieve a custom message service:
if( ! m_msgsvcTP.empty() ) {
if( m_msgsvcTP.retrieve().isFailure() ) {
ATH_MSG_INFO( "Could not retrieve a separate MsgSvc for "
"the T/P debugging" );
} else {
ATH_MSG_DEBUG( "Using " << m_msgsvcTP << " for debugging" );
IMessageSvc* msvc = m_msgsvcTP.operator->();
m_logTP = CxxUtils::make_unique< MsgStream >( msvc,
"TrigSerTPTool-T/P" );
}
}
// Retrieve the used services:
ATH_CHECK( m_dictSvc.retrieve() );
ATH_CHECK( m_tpcnvsvc.retrieve() );
// Return gracefully:
return StatusCode::SUCCESS;
}
StatusCode TrigSerTPTool::testTPCnv(const std::string &clname) {
TClass *cl = getClass(clname);
if (!cl){
*m_log << MSG::DEBUG << "Dict loading of " << clname << " failed" << endreq;
return StatusCode::FAILURE;
} else {
void *p = cl->New();
if (p){
std::string persname;
void *pers = convertTP(clname, p, persname);
//cleanup
TClass *pcl = getClass(persname);
if (pcl)
pcl->Destructor(pers);
}
cl->Destructor(p);
}
return StatusCode::SUCCESS;
}
void* TrigSerTPTool::convertTP( const std::string &clname, void *ptr,
std::string &persName ) {
void* TrigSerTPTool::convertTP(const std::string &clname, void *ptr, std::string &persName){
const int loglvl = m_log->level();
ATH_MSG_DEBUG( "TrigSerTPTool::convertTP" );
if (loglvl<=MSG::DEBUG)
*m_log << MSG::DEBUG << "TrigSerTPTool::convertTP " << endreq;
//pers and persName set only after successful conversion
persName = "";
void *pers( 0 );
//pers and persName set only after successful conversion
persName = "";
void *pers(0);
// Start by trying to find the correct persistent class from the TP map
// Otherwise, use the internal logic of the TPCnvSvc
const auto tpItr = m_TPmap.find( clname );
if( tpItr == m_TPmap.end() ) {
REPORT_MESSAGE( MSG::ERROR )
<< "Transient class " << clname
<< " is not in the T/P Converter map";
return 0;
}
// First look for a trigger specific converter:
ITPCnvBase* cnvtr =
m_tpcnvsvc->p2t_cnv( tpItr->second, Athena::TPCnvType::Trigger );
if( ! cnvtr ) {
// If there is no such thing, try a generic one:
cnvtr = m_tpcnvsvc->p2t_cnv( tpItr->second );
}
if( ! cnvtr ) {
REPORT_MESSAGE( MSG::ERROR )
<< "T/P Converter for transient class "
<< clname << " could not be retrieved";
return 0;
}
// Create a persistent object:
const std::string persname =
System::typeinfoName( cnvtr->persistentTInfo() );
TClass *persObjCl = getClass( persname );
void *persptr( 0 );
if( persObjCl ) {
persptr = persObjCl->New();
ATH_MSG_DEBUG( "created object of " << persptr << " at " << persptr );
} else {
REPORT_MESSAGE( MSG::ERROR )
<< "Couldn't find dictionary for type " << persname;
return 0;
}
// Do the conversion:
ATH_MSG_DEBUG( "invoking TP for " << clname << " at " << ptr );
try {
cnvtr->transToPersUntyped( ptr, persptr, m_logTP ? *m_logTP : msg() );
persName = persname;
pers = persptr;
ATH_MSG_DEBUG( "succeeded at " << persptr );
}
catch( const std::runtime_error& e ){
//delete persObjCl->New();
const std::string issue = e.what();
if( issue.find( "is deprecated" ) != std::string::npos ) {
ATH_MSG_INFO( "An exception " << e.what() );
} else {
pers = 0;
REPORT_MESSAGE( MSG::ERROR ) << "An exception occurred: " << e.what();
}
}
// Return the converted object:
return pers;
}
// Start by trying to find the correct persistent class from the TP map
// Otherwise, use the internal logic of the TPCnvSvc
ITPCnvBase* cnvtr;
if(m_TPmap.find(clname) == m_TPmap.end())
{
*m_log << MSG::ERROR << "Transient class " << clname
<< " is not in the T/P Converter map" << endreq;
void* TrigSerTPTool::convertPT( const std::string &persName, void *pers,
std::string& transName ) {
// First look for a trigger specific converter:
ITPCnvBase* cnvtr =
m_tpcnvsvc->p2t_cnv( persName, Athena::TPCnvType::Trigger );
if( ! cnvtr ) {
// If there is no such thing, try a generic one:
cnvtr = m_tpcnvsvc->p2t_cnv( persName );
}
if( ! cnvtr ) {
REPORT_MESSAGE( MSG::ERROR )
<< "T/P Converter for persistent class "
<< persName << " could not be retrieved";
return 0;
}
cnvtr = m_tpcnvsvc->p2t_cnv(m_TPmap[clname]);
if (!cnvtr) {
*m_log << MSG::ERROR << "T/P Converter for transient class "
<< clname << " could not be retrieved" << endreq;
return 0;
}
const std::string _persname = System::typeinfoName(cnvtr->persistentTInfo());
TClass *persObjCl = getClass(_persname);
void *persptr(0);
if (persObjCl){
persptr = persObjCl->New();
if (loglvl<=MSG::DEBUG){
*m_log << MSG::DEBUG << "created object of " << persptr << " at " << persptr << endreq;
}
} else {
return 0;
}
if (loglvl<=MSG::DEBUG){
*m_log << MSG::DEBUG << "invoking TP for " << clname << " at " << ptr << " - ";
}
try {
cnvtr->transToPersUntyped(ptr, persptr, *m_logTP);
persName = _persname;
pers = persptr;
if (loglvl<=MSG::DEBUG){
*m_log << MSG::DEBUG << "succeeded at " << persptr << endreq;
}
}
catch (const std::runtime_error& e){
//delete persObjCl->New();
const std::string issue = e.what();
if (issue.find("is deprecated")!=std::string::npos){
*m_log << MSG::INFO << "An exception " << e.what() << endreq;
} else {
pers = 0;
*m_log << MSG::ERROR << "An exception " << e.what() << endreq;
}
}
return pers;
}
// Get the name of the transient class:
transName = System::typeinfoName( cnvtr->transientTInfo() );
// Create the transient object:
TClass *transCl = getClass( transName );
void *trans( 0 );
if( transCl ){
trans = transCl->New();
ATH_MSG_DEBUG( "trans " << trans );
}
// Do the conversion:
ATH_MSG_DEBUG( "invoking PT for " << transName );
try {
cnvtr->persToTransUntyped( pers, trans, m_logTP ? *m_logTP : msg() );
ATH_MSG_DEBUG( " succeeded at " << trans );
}
catch (const std::runtime_error& e){
REPORT_MESSAGE( MSG::ERROR ) << "An exception occurred: " << e.what();
//it should destruct trans here (is it in a good state?)
trans = 0;
}
// Return the converted object:
return trans;
}
void* TrigSerTPTool::convertPT(const std::string &persName, void *pers, std::string &transName){
const int loglvl = m_log->level();
// The p->t converter logic ensures the correct transient class is always loaded
ITPCnvBase* cnvtr = m_tpcnvsvc->p2t_cnv(persName);
if (!cnvtr) {
*m_log << MSG::ERROR << "T/P Converter for persistent class "
<< persName << " could not be retrieved" << endreq;
return 0;
}
transName = System::typeinfoName(cnvtr->transientTInfo());
TClass *transCl = getClass(transName);
void *trans(0);
if (transCl){
trans = transCl->New();
if (loglvl<=MSG::DEBUG){
*m_log << MSG::DEBUG << "trans " << trans << endreq;
}
}