diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/AccessProxy.h b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/AccessProxy.h new file mode 100644 index 0000000000000000000000000000000000000000..54fc7bf5728c7e101dc0d1b531273d288f92a80a --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/AccessProxy.h @@ -0,0 +1,18 @@ +// -*- c++ -*- + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#pragma once +#include "StoreGate/StoreGateSvc.h" + + +/** + * It used to be useful piece of code for replacing actual SG with other store of similar functionality + * In fact it used to be more like interface adapter for ARA objects access, nevertheless since the ARA project is gone it is only an unnecessary extra layer. + * The polimorphic dispatch only created unnecessary overhead. + */ +namespace HLT { + typedef StoreGateSvc AccessProxy; +} diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/ComboIterator.h b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/ComboIterator.h new file mode 100644 index 0000000000000000000000000000000000000000..a35ddd0f90c7cb74f790c8634595dafaf467e781 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/ComboIterator.h @@ -0,0 +1,10 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGNAVIGATION_ComboIterator_H +#define TRIGNAVIGATION_ComboIterator_H + +#include "TrigNavStructure/ComboIterator.h" + +#endif //#ifndef diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/Holder.h b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/Holder.h new file mode 100644 index 0000000000000000000000000000000000000000..4a212c83b834e2ff4f1a2c654be3d086a8181fb3 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/Holder.h @@ -0,0 +1,349 @@ +// Emacs -*- c++ -*- + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGNAVIGATION_HOLDER_H +#define TRIGNAVIGATION_HOLDER_H +#include <string> +#include <vector> + +#include "GaudiKernel/ClassID.h" + + +#include "DataModel/OwnershipPolicy.h" +#include "DataModel/DataVector.h" +#include "DataModel/ElementLinkVector.h" +#include "SGTools/StorableConversions.h" + +#include "TrigNavigation/AccessProxy.h" +#include "TrigNavigation/TypeProxy.h" +#include "TrigNavigation/TriggerElement.h" + +#include "TrigStorageDefinitions/TypeInformation.h" +#include "TrigStorageDefinitions/EDM_TypeInfoMethods.h" + + +class MsgStream; +class ITrigSerializerToolBase; + +namespace HLTNavDetails { + + /** + * @brief declaration of formatting function. + */ + //note: needs to be up here to get template compiled. + std::string formatSGkey(const std::string& prefix, const std::string& containername, const std::string& label); + + + + /** + * @class used for features holding + * In fact this class is here in order to allow STL container for all features + * This class is showing a common denominator of all Holders for given type + * The necessary for class to be storable is to have CLID. + * In order to be serialized by Serializer at least the dictionary must be generated. + */ + + class IHolder { + public: + IHolder(); + // IHolder(const std::string& label, uint16_t idx ); + virtual ~IHolder(); + + + virtual IHolder* clone(const std::string& label, uint16_t idx) = 0; // actual constructor + + /** + * @brief prepares this holder + */ + + virtual void prepare(MsgStream* log, HLT::AccessProxy* sg); + + + virtual bool syncWithSG(SG::OwnershipPolicy policy = SG::OWN_ELEMENTS) = 0; + virtual bool clearSG() = 0; + + /** + * @brief returns the CLID of objects stores by this holder + */ + virtual CLID typeClid() const =0; + virtual CLID containerClid() const =0; + virtual CLID auxClidOrZero() const =0; + + /** + * @brief returns the label of objects stores by this holder + */ + inline const std::string& label() const { return m_label; } + + + void setObjectsKeyPrefix(std::string& p) { m_prefix = p; } + + /** + * @brief returns the containers StoreGate key + */ + + virtual const std::string key() const = 0; + + /** + * @brief returns the object's name stored by this holder + */ + virtual const std::string typeName() const = 0; + + /** + * @brief returns the collection's name stored by this holder + */ + virtual const std::string collectionName() const = 0; + + /** + * @brief returns the index (short number used when linking object to the TE) + * of objects stores by this holder + */ + inline uint16_t subTypeIndex() const { return m_subTypeIndex; } + + std::string generateAliasKey(CLID c, uint16_t sti, const std::string& label, unsigned size); + + /** + * @brief serializes this Holder + */ + virtual bool serialize(std::vector<uint32_t>& output) const; + + virtual void print(MsgStream& m) const; + + /** + * @brief deserializes this Holder + */ + virtual bool deserialize(const std::vector<uint32_t>& input) = 0; + + /** + * @brief this staic method is used to figure out what is actuall contained in the blob of ints + */ + static bool enquireSerialized(const std::vector<uint32_t>& blob, + std::vector<uint32_t>::const_iterator& fromHere, + CLID& c, std::string& label, + uint16_t& subtypeIndex ); + + // serialization helpers + virtual DataObject* getDataObject() = 0; + virtual DataObject* getAuxDataObject() = 0; + + virtual bool setDataObject(DataObject* dobj) = 0; + virtual bool setAuxDataObject(DataObject* dobjaux) = 0; + + /** + * Get the proxy for the container + */ + virtual const ITypeProxy& containerTypeProxy() const = 0; + + protected: + mutable std::vector<uint32_t>* m_serialized; //!< serialized vector of this type + // serialization helpers + MsgStream* m_log; + HLT::AccessProxy* m_storeGate; //!< pointer to SG + ITrigSerializerToolBase* m_serializer; //!< pointer to Serializer + + + // CLID m_CLID; //!< class ID of objects holded + // CLID m_collectionCLID; //!< class ID of objects holded + std::string m_label; //!< label given to the objects in this holder (labels given at attachFeature) + std::string m_prefix; //!< prefix for key given to the objects + uint16_t m_subTypeIndex; //!< index to notify how many objects of given type we have (we need to record it in case of slimming will be done latter) + ITypeProxy * m_aux; + private: + mutable std::ostringstream m_ostream; //!< used internally for keys generation + int m_uniqueCounter; + + }; + + + ////////////////////////////////////////////////////////////////////////////////////// + + /** + * @brief Helper struct to determine if persistable type is a DataLink<CONTAINER> (in case STORED and CONTAINER are the same) + * of rather an ElementLink<CONTAINER> in case STORED is the element type of CONTAINER + * + * + * + */ + + template<class STORED, class CONTAINER, bool is_same> struct set_link; + + template<class STORED, class CONTAINER> + struct set_link<STORED,CONTAINER,true>{ + typedef DataLink<CONTAINER> type; + static type do_it(const STORED* el, const CONTAINER* src, HLT::TriggerElement::ObjectIndex idx){ + (void)src;(void)idx; //not used here + type t(el); + return t; + } + }; + + template<class STORED, class CONTAINER> + struct set_link<STORED,CONTAINER,false>{ + typedef ElementLink<CONTAINER> type; + static type do_it(const STORED* el,const CONTAINER* src, HLT::TriggerElement::ObjectIndex idx){ + (void)el;//not used here + type t(*src,idx.objectsBegin()); + return t; + } + }; + + ////////////////////////////////////////////////////////////////////////////////////// + template<class T, class C> class HolderImp; + /** + * @class Specialized holder class for each object type + ******************************************************************* + * This class in addition to the above IHolder implements 2 methods get & add. + */ + template<class STORED> + class Holder : public IHolder { + public: + Holder(); + Holder(const std::string& label, uint16_t idx); + virtual ~Holder(); + + + virtual HLT::TriggerElement::ObjectIndex add( const STORED* f, bool inSG, const std::string& = "" ) = 0; //!< saved object in this holder + virtual bool get(const STORED*& dest, HLT::TriggerElement::ObjectIndex idx) = 0; + + template<class CONTAINER2> + bool get(ElementLinkVector<CONTAINER2>& cont); + + template<class CONTAINER2> + bool get(ElementLinkVector<CONTAINER2>& cont, HLT::TriggerElement::ObjectIndex idx); + + template<class CONTAINER2> + bool getWithLink(typename set_link<STORED,CONTAINER2,boost::is_same<STORED,CONTAINER2>::value>::type& link, + HLT::TriggerElement::ObjectIndex& idx) { + + bool result = static_cast<HolderImp<STORED,CONTAINER2>*>(this)->getWithLink(link,idx); + return result; + } + + virtual bool contains(const STORED* obj, HLT::TriggerElement::ObjectIndex& idx) const = 0; + + virtual bool checkAndSetOwnership(SG::OwnershipPolicy policy) = 0; + virtual CLID typeClid() const { return ClassID_traits<STORED>::ID(); } + + + + virtual std::string getUniqueKey() = 0; // this is backward compatibility for TrigCaloRec and TrigTauRec, whould be removed + virtual std::string getNextKey() = 0; // this is backward compatibility for TrigCaloRec and TrigTauRec, whould be removed + virtual void print(MsgStream& m) const; + + private: + + + + + }; + + ////////////////////////////////////////////////////////////////////////////////////// + + /** + * @brief This is an implementation class for all Holders + * It is templated with 2 arguments STORED which is type of stored objects + * Another type is CONTAINER for that type. + * Examples when it works are: + * HolderImp<A, DataVector<A> > --- typical + * HolderImp< A, Acontainer> > --- as above, Acontainer is either typedef for DataVector<A> or inherits from it + * HolderImp< DataVector<A>, DataVector<A> > --- when both are of the same type + * HolderImp< Acontainer, Acontainer> > --- as above + * + * + */ + template<class STORED, class CONTAINER> + class HolderImp: public Holder<STORED> { + public: + + typedef Holder<STORED> base_type; + typedef STORED stored_type; + typedef CONTAINER container_type; + + HolderImp(); + HolderImp(const std::string& label, uint16_t idx); + virtual ~HolderImp(); + + virtual IHolder* clone(const std::string& label, uint16_t idx ); + + /** + * @brief adds object(s) to be holded + */ + virtual HLT::TriggerElement::ObjectIndex add( const STORED* f, bool inSG = false, const std::string& = "" ); + + /** + * @brief gets object(s) holded + */ + virtual bool get(const STORED*& dest, HLT::TriggerElement::ObjectIndex idx); + + /** + * @brief cehcks if object(s) in dest are holded by this holder + */ + virtual bool contains(const STORED* obj, HLT::TriggerElement::ObjectIndex& idx) const; + + bool getElementLinks(ElementLinkVector<CONTAINER>& cont, HLT::TriggerElement::ObjectIndex idx); + bool getElementLinks(ElementLinkVector<CONTAINER>& cont); + + bool getWithLink(typename set_link<STORED,CONTAINER,boost::is_same<STORED,CONTAINER>::value>::type& link, + HLT::TriggerElement::ObjectIndex& idx); + + virtual std::string getUniqueKey(); // this is backward compatibility for TrigCaloRec and TrigTauRec, whould be removed + virtual std::string getNextKey(); // this is backward compatibility for TrigCaloRec and TrigTauRec, whould be removed + + virtual void prepare(MsgStream* log, HLT::AccessProxy* sg); + virtual bool syncWithSG(SG::OwnershipPolicy policy=SG::OWN_ELEMENTS); + virtual bool clearSG(); + virtual bool checkAndSetOwnership(SG::OwnershipPolicy policy); + + virtual bool serialize(std::vector<uint32_t>& output) const; + virtual bool deserialize(const std::vector<uint32_t>& input); + virtual const std::string key() const { + return formatSGkey(this->m_prefix,ClassID_traits<CONTAINER>::typeName(),this->m_label); + }; + virtual const std::string typeName() const { return ClassID_traits<STORED>::typeName(); } + virtual const std::string collectionName() const { return ClassID_traits<CONTAINER>::typeName(); } + virtual void print(MsgStream& m) const; + + virtual DataObject* getDataObject(); + virtual DataObject* getAuxDataObject(); + virtual bool setDataObject(DataObject* dobj); + virtual bool setAuxDataObject(DataObject* dobjaux); + + virtual CLID containerClid() const { return ClassID_traits<CONTAINER>::ID(); } + virtual CLID auxClidOrZero() const; + + // virtual bool bindAux(IHolder* h); + + typedef HLTNavDetails::TypeProxy<CONTAINER> ContainerProxy; + mutable ContainerProxy m_containerProxy; + + virtual const ITypeProxy& containerTypeProxy() const { return m_containerProxy; } + + typedef HLTNavDetails::TypeProxy<STORED> FeatureProxy; + + // mutable CONTAINER* m_objects; + // STORED *m_return; + // for memory management + struct MemoryMgr { + MemoryMgr(); + MemoryMgr(const FeatureProxy& st, bool inSG); + void clear(); + FeatureProxy proxy; + bool inSG; + }; + typedef std::multimap<HLT::TriggerElement::ObjectIndex, MemoryMgr> MemoryMgrMap; + MemoryMgrMap m_memMgr; + }; + + MsgStream& operator<< ( MsgStream& m, const HLTNavDetails::IHolder& nav ); //<! printing helper + template<class T> + MsgStream& operator<< ( MsgStream& m, const HLTNavDetails::Holder<T>& nav ); //<! printing helper + template<class T, class C> + MsgStream& operator<< ( MsgStream& m, const HLTNavDetails::HolderImp<T, C>& nav ); //<! printing helper +} // end of namespace + +//#include "TrigNavigation/Holder.icc" + +// +#endif diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/Holder.icc b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/Holder.icc new file mode 100644 index 0000000000000000000000000000000000000000..c8a7a7e3107c05cc6bfdd9c10c6db30cc55d853c --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/Holder.icc @@ -0,0 +1,973 @@ +// Emacs -*- c++ -*- + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//#include "iostream" +#include <iterator> +#include <boost/type_traits/is_same.hpp> +#include <boost/mpl/if.hpp> + +#include "GaudiKernel/MsgStream.h" +// +#include "TrigNavigation/TypeMaps.h" + +#ifndef TrigNavigation_Holder_icc +#define TrigNavigation_Holder_icc + +#define HMLOG(x) if (Holder<STORED>::m_log->level()<=MSG::x) *Holder<STORED>::m_log << MSG::x +#define MLOG(x) if (m_log->level()<=MSG::x) *m_log << MSG::x + + + + + + +///////////////////////////////////////////////////////////////////////////// +// T is for objects, C for container for this objects +template<class STORED> +HLTNavDetails::Holder<STORED>::Holder() { +} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED> +HLTNavDetails::Holder<STORED>::Holder(const std::string& label, uint16_t idx) { + m_label = label; + m_subTypeIndex = idx; +} + + +///////////////////////////////////////////////////////////////////////////// +template<class STORED> +HLTNavDetails::Holder<STORED>::~Holder() { +} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, bool> struct createTemporary; + +///////////////////////////////////////////////////////////////////////////// +template<class STORED> +struct createTemporary<STORED, true> +{ + static STORED* do_it() { + // std::cerr << " created temporary return cache" << std::endl; + STORED *s = new STORED; + s->clear(SG::VIEW_ELEMENTS); + return s; + } +}; + +///////////////////////////////////////////////////////////////////////////// +template<class STORED> +struct createTemporary<STORED, false> +{ + static STORED* do_it() { + // std::cerr << " Not created temporary return cache" << std::endl; + return 0; + } +}; + +///////////////////////////////////////////////////////////////////////////// +template<class STORED> +template<class CONTAINER2> +bool HLTNavDetails::Holder<STORED>::get( ElementLinkVector<CONTAINER2>& el, HLT::TriggerElement::ObjectIndex idx) { + return static_cast<HolderImp<STORED, CONTAINER2>* >(this)->getElementLinks(el, idx); +} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED> +template<class CONTAINER2> +bool HLTNavDetails::Holder<STORED>::get( ElementLinkVector<CONTAINER2>& el ) { + return static_cast<HolderImp<STORED, CONTAINER2>* >(this)->getElementLinks(el); +} + + + + + + +///////////////////////////////////////////////////////////////////////////// +// Implementation +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +HLTNavDetails::HolderImp<STORED, CONTAINER>::HolderImp() + : Holder<STORED>()/*, m_return(0)*/ { + +} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +HLTNavDetails::HolderImp<STORED, CONTAINER>::HolderImp(const std::string& label, uint16_t idx) + : Holder<STORED>(label, idx)/*, m_return(0)*/ { + + // m_return = create<STORED, boost::is_same<STORED, CONTAINER>::value>::do_it(); + +} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +HLTNavDetails::HolderImp<STORED, CONTAINER>::~HolderImp() { + typedef Holder<STORED> H; + if (H::m_log) HMLOG(VERBOSE) << "~HolderImp clearing memory manager" << endreq; + // typename MemoryMgrMap::iterator it; + // for ( it = m_memMgr.begin(); it != m_memMgr.end(); ++it ) { + // if (H::m_log) HMLOG(VERBOSE) << "~HolderImp clearing MemoryMgrMap entry: " << it->first << " inSG: " << it->second.inSG << endreq; + //it->second.proxy.clear(H::m_storeGate); + // } + m_memMgr.clear(); + // if ( m_return ) delete m_return; + if (H::m_log) HMLOG(VERBOSE) << "~HolderImp Holder deleted" << endreq; +} + + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +HLTNavDetails::IHolder* HLTNavDetails::HolderImp<STORED, CONTAINER>::clone(const std::string& label, uint16_t idx ) { + typedef Holder<STORED> H; + if ( not m_containerProxy.empty() ) { + return 0; + } + HolderImp<STORED, CONTAINER> *imp = new HolderImp<STORED, CONTAINER>(label, idx); + // imp->m_return = create<STORED, boost::is_same<STORED, CONTAINER>::value>::do_it(); + IHolder *h = imp; + return h; +} + + +/* + //temporary debugging + if (Holder<STORED>::m_log->level()<=MSG::VERBOSE){ + HMLOG(VERBOSE) << "looking up SG key: " << l << " of clid: " << cc << endreq; + HMLOG(VERBOSE) << "inbetween keys: " ; + std::vector<std::string> kk = H::m_storeGate->keys(cc); + for (unsigned int ik=0; ik<kk.size(); ik++){ + HMLOG(VERBOSE) << kk[ik] << " "; + if (kk[ik]==l) + HMLOG(VERBOSE) << kk[ik] << "<-matched "; + } + HMLOG(VERBOSE) << endreq; + } +*/ +template<class AUX> +struct auxCLIDOrZero { + static CLID get() { + return ClassID_traits<AUX>::ID(); + } + static std::string getName() { + return ClassID_traits<AUX>::typeName(); + } +}; +template<> +struct auxCLIDOrZero<HLT::TypeInformation::no_aux> { + static CLID get() { + return 0; + } + static std::string getName() { + return std::string("no_aux"); + } +}; + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +CLID HLTNavDetails::HolderImp<STORED, CONTAINER>::auxClidOrZero() const { + return auxCLIDOrZero<typename Container2Aux<CONTAINER>::type>::get(); +} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +void HLTNavDetails::HolderImp<STORED, CONTAINER>::prepare(MsgStream* log, HLT::AccessProxy* sg){ + typedef Holder<STORED> H; + IHolder::prepare(log,sg); + CLID auxCLID = auxCLIDOrZero<typename Container2Aux<CONTAINER>::type>::get(); + if ( auxCLID ) { + H::m_aux = HLT::TypeMaps::proxies()[auxCLID]; + if ( H::m_aux == 0 ) { + HMLOG(ERROR) << "HolderImp::prepare can not find Aux store proxy " << *this << endreq; + } + + H::m_aux = H::m_aux->clone(); + if ( H::m_aux == 0 ) { + HMLOG(ERROR) << "HolderImp::prepare can not clone Aux store proxy " << *this << endreq; + } + HMLOG(VERBOSE) << "HolderImp::prepare proxy toAux store ready decorating" << endreq; + } +} + + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +bool HLTNavDetails::HolderImp<STORED, CONTAINER>::syncWithSG(SG::OwnershipPolicy policy) { + typedef Holder<STORED> H; + if ( !H::m_storeGate ) { + HMLOG(WARNING) << "HolderImp::syncWithSG no SG available " << *this << endreq; + return false; + } + HMLOG(VERBOSE) << "HolderImp::syncWithSG syncing holder with SG " << *this << endreq; + std::string l = key(); + + std::string auxkey = key()+"Aux."; + HMLOG(VERBOSE) << "HolderImp::syncWithSG looking in SG for key " << key() << " possible aux should have " << auxkey << endreq; + + const bool transientInSG ( m_containerProxy.transientContains(H::m_storeGate, key() ) ); + const bool persistentThroughSG ( m_containerProxy.contains(H::m_storeGate, key() ) ); + if ( transientInSG or persistentThroughSG ) { + HMLOG(VERBOSE) << "HolderImp::syncWithSG objects " + << ( transientInSG ? "already in" : "available through" ) + << " SG, syncing to them " << *this << endreq; + + + if ( m_containerProxy.sync( H::m_storeGate, key()).isFailure() ) { + HMLOG(WARNING) << "HolderImp::syncWithSG objects already in SG, however failed syncing (SG::retrieve) to them " << *this << endreq; + return false; + } + HMLOG(VERBOSE) << "HolderImp::syncWithSG got container from SG: " << m_containerProxy.data() << endreq; + if ( this->m_aux ) { + const bool transientInSGAux ( this->m_aux->transientContains(H::m_storeGate, auxkey ) ); + const bool persistentThroughSGAux ( this->m_aux->contains(H::m_storeGate, auxkey ) ); + if(!transientInSGAux and !persistentThroughSGAux){ + HMLOG(WARNING) << "HolderImp::syncWithSG syncing Aux holder and CONTAINER is SG but Aux Store not" << endreq; + return false; + } + if(this->m_aux->sync(H::m_storeGate,auxkey).isFailure()){ + HMLOG(WARNING) << "HolderImp::syncWithSG objects already in SG, however failed syncing aux (SG::retrieve) to them " << *this << endreq; + return false; + } + typedef typename Container2Aux<CONTAINER>::type auxtype; + HLTNavDetails::TypeProxy<auxtype>* auxcasted = static_cast<HLTNavDetails::TypeProxy<auxtype>*>(this->m_aux); + HMLOG(VERBOSE) << "HolderImp::syncWithSG got aux container from SG: " << auxcasted->data() << endreq; + HMLOG(VERBOSE) << "HolderImp::syncWithSG store is: " << m_containerProxy.data()->getStore() << endreq; + } + } else { // SG is empty, we need to put the obj ito it + HMLOG(VERBOSE) << "HolderImp::syncWithSG objects not in SG, adding them to SG " << *this << endreq; + if ( m_containerProxy.create().isFailure() ) { + HMLOG(WARNING) << "HolderImp::syncWithSG can not create container " << *this << endreq; + return false; + } + + m_containerProxy.data()->clear(policy); + + CLID auxCLID = auxCLIDOrZero<typename Container2Aux<CONTAINER>::type>::get(); + if ( auxCLID ) { + if ( H::m_aux == 0 ) { + HMLOG(ERROR) << "HolderImp::syncWithSG can not clone Aux store proxy " << *this << endreq; + return false; + } + + HMLOG(VERBOSE) << "HolderImp::syncWithSG proxy toAux store ready decorating" << endreq; + + if( H::m_aux->create().isFailure() ) { + HMLOG(WARNING) << "HolderImp::syncWithSG can not create Aux store for container " << *this << endreq; + return false; + } + std::string auxkey = formatSGkey(this->m_prefix, + ClassID_traits<CONTAINER>::typeName(), + this->m_label+"Aux."); + + if( H::m_aux->reg(H::m_storeGate,auxkey).isFailure() ) { + HMLOG(WARNING) << "HolderImp::syncWithSG can not register Aux store for container in SG " << *this << endreq; + return false; + } + + SG::AuxVectorBase* container = m_containerProxy.castAuxVectorBase(); + SG::IAuxStore* aux = H::m_aux->castIAuxStore(); + if ( container and aux ) { + HMLOG(DEBUG) << "HolderImp::syncWithSG Aux sotore configured for " << *this << endreq; + container->setStore(aux); + } else { + HMLOG(WARNING) << "HolderImp::syncWithSG type configured to have Aux store but no appropriate Aux interaces are implemented AuxVectorBase for container: " + << container << " IAuxStore for Aux sotore: " << aux << " "<< *this << endreq; + return false; + } + } + + if ( m_containerProxy.reg( H::m_storeGate, key()).isFailure() ) { + HMLOG(ERROR) << "HolderImp::syncWithSG recording collection failed " << *this << endreq; + return false; + } + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +bool HLTNavDetails::HolderImp<STORED, CONTAINER>::clearSG() { + if ( m_containerProxy.empty() ) return false; + + // typedef Holder<STORED> H; + // if ( m_containerProxy.clear(H::m_storeGate).isFailure() ) + // return false; + return true; +} + + + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +bool HLTNavDetails::HolderImp<STORED, CONTAINER>::checkAndSetOwnership(SG::OwnershipPolicy policy) { + if ( m_containerProxy.empty() ) + return false; + + if ( m_containerProxy.data()->empty() ) { + m_containerProxy.data()->clear(policy); + return true; + } + + if ( m_containerProxy.data()->ownPolicy() == policy ) + return true; + + return false; +} +///////////////////////////////////////////////////////////////////////////// +template<class CONTAINER, bool b> +struct transferBetweenContainers; + + +// case when the containers can be transfered +template <class CONTAINER> +struct transferBetweenContainers<CONTAINER, true> { + static void do_it(CONTAINER *source, CONTAINER* dest, MsgStream* m_log) { + const size_t orig_size = dest->size(); + dest->resize( orig_size + source->size() ); + std::swap_ranges( source->begin(), source->end(), dest->begin() + orig_size ); + MLOG( VERBOSE ) << "insert::do_it objects moved, converting to a view container now" << endreq; + source->setStore((SG::IAuxStore*)0); + source->clear(SG::VIEW_ELEMENTS); + MLOG( VERBOSE ) << "insert::do_it refilling the feature container" << endreq; + source->insert(source->begin(), std::next(dest->begin(), orig_size), dest->end()); + + } +}; + +///////////////////////////////////////////////////////////////////////////// +// case when the containers CAN NOT be transfered +template <class CONTAINER> +struct transferBetweenContainers<CONTAINER, false> { + static void do_it(CONTAINER *, CONTAINER* , MsgStream* ) { + throw std::runtime_error + ("TrigNavigation: Tried to attach an owning container of type " + + ClassName<CONTAINER>::name() + + "; only view containers of this type are supported."); + } +}; + +///////////////////////////////////////////////////////////////////////////// +// code below checks if the transfer of elements between the two OWNING containers can happen +// It is based on the check of the type returned by the iterator i.e. if the reference is const or not const (i.e. assignable) +// +template<class CONTAINER> +struct canTransfer { + const static bool value = std::is_assignable<typename CONTAINER::iterator::reference, + typename CONTAINER::iterator::value_type>::value; +}; + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER, bool b> struct insert; + +///////////////////////////////////////////////////////////////////////////// +// implementation if stored and container are the same +// this version is suggested by Attila, it has several advantages +// 1) the source container is useable after the insertion (important for the monitoring) +// 2) ownership of objects is greately simplified (i.e. the event-wise container always own objects, +// the roi-wise containers always view objects +// +template <class STORED, class CONTAINER> +struct insert<STORED, CONTAINER, true>{ + static bool do_it(STORED *source, CONTAINER* dest, bool /*hasAux*/, MsgStream* m_log) { + + MLOG( VERBOSE ) << "insert::do_it CONTAINER " << ClassID_traits<STORED>::typeName() << endreq; + MLOG( VERBOSE ) << "Destination is " << (dest->ownPolicy() == SG::VIEW_ELEMENTS ? "VIEW" : "OWN") + << " source is " << (source->ownPolicy() == SG::VIEW_ELEMENTS ? "VIEW" : "OWN") << endreq; + + + // From Scott + // - Input container is owning. Output container should also be owning; + // ownership should be transferred from input to output container. + + // - Input is a view container and doesn't track indices + // (trackIndices() is false). Output should be a view container. + // Aux data are not transferred in this case. + + // - Input is a view container that does track indices + // (trackIndices() is true). Output should be a view container + // with ALWAYS_TRACK_INDICES. Aux data are transferred in this case. + // (I don't think trigger will see this case.) + + + if ( dest->empty() ) { // epmty destination, we can do adaptations + if ( source->ownPolicy() == SG::OWN_ELEMENTS ) { + dest->clear( SG::OWN_ELEMENTS ); + } + + if ( source->ownPolicy() == SG::VIEW_ELEMENTS and source->trackIndices() == false ) { + MLOG( VERBOSE ) << "insert::do_it destination container made a VIEW" << endreq; + dest->clear( SG::VIEW_ELEMENTS); + } + + if ( source->ownPolicy() == SG::VIEW_ELEMENTS and source->trackIndices() == true ) { + MLOG( VERBOSE ) << "insert::do_it destination container made a VIEW wiht indices tracking " << endreq; + // it should be like this but I can not implemnt it like this because many container do not implement second arg dest->clear( SG::VIEW_ELEMENTS, SG::ALWAYS_TRACK_INDICES ); + dest->clear( SG::VIEW_ELEMENTS ); + } + } + if ( source->ownPolicy() != dest->ownPolicy() ) { // a simple check if in case of nonempty container we are dooing consistent insertion + MLOG( WARNING ) << "insert::do_it objects can not be inserted because of ownership issues. " + << "Destination container has already " << dest->size() << " objects " + << " and ownership policy " + << (dest->ownPolicy() == SG::OWN_ELEMENTS ? "OWN" : "") // this is dumb code but who knows what other policies will be implemented in the future + << (dest->ownPolicy() == SG::VIEW_ELEMENTS ? "VIEW" : "") + << " no action is performed, potential memory leak" << endreq; + return false; + } + + + if ( source->ownPolicy() == SG::VIEW_ELEMENTS ) { + // const size_t orig_size = dest->size(); + // dest->resize( orig_size + source->size() ); + dest->insert(dest->end(), source->begin(), source->end()); + MLOG( VERBOSE ) << "insert::do_it objects copied, conversion to view container not needed" << endreq; + } else { + // We have an owning container. Transfer the element ownership + // from SOURCE to DEST. We can only do this if the container + // has modifiable iterators. For containers with non-modifiable + // iterators (like CaloTowerContainer), we throw an exception. + // Such containers should be added only as view containers. + transferBetweenContainers<CONTAINER, canTransfer<CONTAINER>::value> + ::do_it(source, dest, m_log); + + + // const size_t orig_size = dest->size(); + // dest->resize( orig_size + source->size() ); + // std::swap_ranges( source->begin(), source->end(), dest->begin() + orig_size ); + // MLOG( VERBOSE ) << "insert::do_it objects moved, converting to a view container now" << endreq; + // source->setStore((SG::IAuxStore*)0); + // source->clear(SG::VIEW_ELEMENTS); + // MLOG( VERBOSE ) << "insert::do_it refilling the feature container" << endreq; + // source->insert(source->begin(), std::next(dest->begin(), orig_size), dest->end()); + } + return true; + } +}; + + +/* +template <class STORED, class CONTAINER> +struct insert<STORED, CONTAINER, true>{ + static bool do_it(STORED *source, CONTAINER* dest, bool hasAux, MsgStream* m_log) { + + if (hasAux) { + + MLOG( VERBOSE ) << "insert::do_it CONTAINER " << ClassID_traits<STORED>::typeName() + << " has defined Aux decorations, swap_ranges used" << endreq; + + const size_t orig_size = dest->size(); + dest->resize( orig_size + source->size() ); + std::swap_ranges( source->begin(), source->end(), dest->begin() + orig_size ); + return true; + } else { + + // we may to have little problem here because the either both source and destination own the memory or + // or noone owns it + if ( source->ownPolicy() == dest->ownPolicy() ) { + if (dest->empty() ) { // if the destination is still empty we can adapt it + MLOG( VERBOSE ) << "insert::do_it CONTAINER " << ClassID_traits<STORED>::typeName() + << " adapting the destination container SG::OwnPolicy for the first insert" << endreq; + + if ( source->ownPolicy() == SG::OWN_ELEMENTS) dest->clear( SG::VIEW_ELEMENTS ); + if ( source->ownPolicy() == SG::VIEW_ELEMENTS) dest->clear( SG::OWN_ELEMENTS ); + } else { // real issue + MLOG( WARNING ) << "insert::do_it CONTAINER " << ClassID_traits<STORED>::typeName() + << " already has has objects and own policiec clash" << source->ownPolicy() << " " << dest->ownPolicy() << endreq; + return false; + } + } + MLOG ( VERBOSE ) << "insert::do_it CONTAINER " << ClassID_traits<STORED>::typeName() + << " has no decorations, insert used" << endreq; + dest->insert(dest->end(), source->begin(), source->end()); + } + return true; + } +}; +*/ +///////////////////////////////////////////////////////////////////////////// +// implementation if stored and container are distinct +template <class STORED, class CONTAINER> +struct insert <STORED, CONTAINER, false>{ + static bool do_it(STORED *s, CONTAINER* dest, bool /*hasAux*/, MsgStream* /*msglog*/ ) { + + // if (dest->empty()) + // dest->clear(SG::VIEW_ELEMENTS); // this is the way to change ownership + dest->push_back(s); + return true; + } +}; + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER, bool b> struct remap; +template<class STORED, class CONTAINER> +struct remap<STORED, CONTAINER, false> { + static void do_it(const std::string&, const std::string&, STORED *, CONTAINER*, HLT::AccessProxy*, MsgStream* ) { + + } +}; + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +struct remap<STORED, CONTAINER, true> { + static void do_it(const std::string& storedkey , const std::string& contkey, STORED *s, CONTAINER* cont, HLT::AccessProxy *sg, MsgStream* m_log ) { + std::string skey = storedkey; + if ( storedkey == "" ) { + // we can't do it + if ( m_log->level() <= MSG::VERBOSE ) { + *m_log << MSG::VERBOSE << "HolderImp::remap trying to discover object key, this is potentially slow and should be avoided, type: " << ClassID_traits<STORED>::typeName() << " from: " << s << " to: " << cont << endreq; + } + SG::DataProxy* px = sg->proxy((void const* )s); + if ( !px ) { + *m_log << MSG::WARNING << "HolderImp::remap When remaping containers found no proxy for the object" << s << " of type " << ClassID_traits<STORED>::typeName() << endreq; + return; + } + if ( !px->isValid() ) { + *m_log << MSG::WARNING << "HolderImp::remap When remaping containers found no valid proxy for the object" << s << " of type " << ClassID_traits<STORED>::typeName() << endreq; + return; + } + skey = px->name(); + } + if ( m_log->level() <= MSG::VERBOSE ) + *m_log << MSG::VERBOSE << "HolderImp::remap remapping collections of type: " << ClassID_traits<STORED>::typeName() + << " from: " << skey << " to: " << contkey << " while destination container size is: " << cont->size() << endreq; + sg->remap(ClassID_traits<CONTAINER>::ID(), skey, contkey, cont->size()); + + } +}; + + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +HLT::TriggerElement::ObjectIndex HLTNavDetails::HolderImp<STORED, CONTAINER>::add( const STORED* f, bool inSG, const std::string& sgKey ) { + typedef Holder<STORED> H; + if ( ! syncWithSG() ) + return HLT::TriggerElement::ObjectIndex(); + + uint32_t bidx = m_containerProxy.data()->size(); + + std::string thiskey(sgKey); + if ( !inSG && boost::is_same<STORED, CONTAINER>::value ) { // conditions to place partial containers in SG + thiskey = this->getUniqueKey(); + if ( H::m_storeGate->record(f, thiskey).isFailure() ) { + HMLOG(WARNING) << "HolderImp::add object " << f << "and sgKey:" << thiskey << " intended for holder" << *this << " can't be placed directly in SG" << endreq; + } else { + inSG = true; + HMLOG(VERBOSE) << "HolderImp::add feature SG direct registration succesful with the key:" << thiskey << endreq; + } + } + + if ( inSG ) { //conditions to add remapping + remap<STORED, CONTAINER, + boost::is_same<STORED, CONTAINER>::value>::do_it (thiskey, key(), const_cast<STORED*>(f), m_containerProxy.data(), H::m_storeGate, H::m_log); + } + + bool insertStatus = insert<STORED, CONTAINER, boost::is_same<STORED, CONTAINER>::value> + ::do_it (const_cast<STORED*>(f), m_containerProxy.data(), H::m_aux != 0, H::m_log); + if ( insertStatus == false ) { + HMLOG(WARNING) << "HolderImp::add insert failed " << endreq; + return HLT::TriggerElement::ObjectIndex(); + } + + uint32_t eidx = m_containerProxy.data()->size(); + HMLOG(VERBOSE) << "HolderImp::add added object(s) to the container, size increase from : " << bidx << " to: " << eidx << endreq; + HLT::TriggerElement::ObjectIndex objIdx (H::subTypeIndex(), bidx, eidx ); + + m_memMgr.insert(std::make_pair(objIdx, MemoryMgr(const_cast<STORED*>(f), inSG||m_containerProxy.data()->ownPolicy() == SG::OWN_ELEMENTS))); + + return objIdx; +} + + + + + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER, bool b> struct retrieve; + +///////////////////////////////////////////////////////////////////////////// +// implementation if stored and container are the same +template <class STORED, class CONTAINER> +struct retrieve<STORED, CONTAINER, true>{ + static bool do_it(STORED*& dest, CONTAINER* src, HLT::TriggerElement::ObjectIndex idx) { + // find 2 iterators + // assert(idx.objectsBegin()); + if ( src->size() < idx.objectsBegin() || src->size() < idx.objectsEnd()) { + REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"Holder") << "either begin index or end index is larger than size"; + REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"Holder") << "size: " << src->size() << " begin: " << idx.objectsBegin() << " end: " << idx.objectsEnd(); + dest = 0; + return false; + } + dest = createTemporary<STORED, boost::is_same<STORED, CONTAINER>::value>::do_it(); + typename CONTAINER::iterator beg = src->begin(); + typename CONTAINER::iterator end = src->begin(); + std::advance(beg, idx.objectsBegin()); + std::advance(end, idx.objectsEnd()); + dest->insert(dest->end(), beg, end); + return true; + } +}; + +///////////////////////////////////////////////////////////////////////////// +// implementation if stored and container are distinct +template <class STORED, class CONTAINER> +struct retrieve <STORED, CONTAINER, false>{ + static bool do_it(STORED*& dest, CONTAINER* src, HLT::TriggerElement::ObjectIndex idx) { + + if (idx.objectsBegin() < (*src).size()) { + dest = src->at(idx.objectsBegin()); + return true; + } else { + /* + HMLOG(ERROR) << "idx.objectsBegin()=" << idx.objectsBegin() + << " out of range in source container of size " << (*src).size() << endreq; + */ + dest = 0; + return false; + } + } +}; + +template<class STORED, class CONTAINER> +bool HLTNavDetails::HolderImp<STORED, CONTAINER>::getWithLink(typename set_link<STORED,CONTAINER,boost::is_same<STORED,CONTAINER>::value>::type& link, + HLT::TriggerElement::ObjectIndex& idx) { + + const STORED* dest = 0; + bool result = this->get(dest,idx); + if(!result) return false; + + link = set_link<STORED,CONTAINER,boost::is_same<STORED,CONTAINER>::value>::do_it(dest,m_containerProxy.data(),idx); + return true; +} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +bool HLTNavDetails::HolderImp<STORED, CONTAINER>::get(const STORED*& dest, HLT::TriggerElement::ObjectIndex idx) { + typedef Holder<STORED> H; + if ( !syncWithSG() ) + return false; + + + HMLOG(VERBOSE) << "HolderImp::get getting object(s) from Holder" << *this << endreq; + typename MemoryMgrMap::const_iterator cache; + if ( (cache = m_memMgr.find(idx)) != m_memMgr.end() ) { + HMLOG(DEBUG) << "HolderImp::get object found in the cache with address " << idx << endreq; + dest = cache->second.proxy.data(); + return true; + } + else{ + HMLOG(VERBOSE) << "HolderImp::get getting object from primary collection " << idx << endreq; + } + + if ( ! retrieve<STORED, CONTAINER, // short circuited .. retrieve will not run if in cache + boost::is_same<STORED, CONTAINER>::value>:: + do_it (const_cast<STORED*&>(dest), m_containerProxy.data(), idx) ) { + HMLOG(WARNING) << "HolderImp::get getting chunk of the container failed for Holder: " << *this + << " index: " << idx << endreq; + return false; + } + + if ( boost::is_same<STORED, CONTAINER>::value ) { // temporary view containers in SG and cache filling + FeatureProxy tempProxy( const_cast<STORED*>(dest) ); + + m_memMgr.insert(std::make_pair(idx, MemoryMgr(tempProxy, true))); // store it in the cache for futher uses + + std::string sgKey = this->generateAliasKey( H::typeClid(), H::subTypeIndex(), H::label(), 0xffffffff ); + + if ( tempProxy.reg(H::m_storeGate, sgKey).isFailure() ) { + HMLOG(WARNING) << "HolderImp::get for some reason object can't be placed in SG, key:" << sgKey << endreq; + return false; + } + remap<STORED, CONTAINER, + boost::is_same<STORED, CONTAINER>::value>::do_it (sgKey, key(), tempProxy.data(), m_containerProxy.data(), H::m_storeGate, H::m_log); + HMLOG(VERBOSE) << "Added view collection to SG with defined EL remapping to event-wide colection, key: " << sgKey << endreq; + } + return true; +} + + +///////////////////////////////////////////////////////////////////////////// +// check if objects in obj are in the container +template<class STORED, class CONTAINER, bool b> struct isin; + +///////////////////////////////////////////////////////////////////////////// +// check if the container obj is a subcontainer of cont +template <class STORED, class CONTAINER> +struct isin<STORED, CONTAINER, true> { + static bool do_it(const STORED* obj, const CONTAINER* cont, MsgStream* /*msg*/, uint32_t& begin, uint32_t& end) { + typename CONTAINER::const_iterator it = std::search(cont->begin(), cont->end(), obj->begin(), obj->end()); + if ( it == cont->end() ) { + return false; + } + begin = it - cont->begin(); + end = begin + obj->size(); + return true; + } +}; + +///////////////////////////////////////////////////////////////////////////// +// check if the obj is in a container cont +template <class STORED, class CONTAINER> +struct isin<STORED, CONTAINER, false> { + static bool do_it(const STORED* obj, const CONTAINER* cont, MsgStream* /*msg*/, uint32_t& begin, uint32_t& end) { + typename CONTAINER::const_iterator it = std::find(cont->begin(), cont->end(), obj); + if ( it == cont->end() ) { + return false; + } + // std::cerr << "fubu " << obj << " " << *it << std::endl; + begin = it - cont->begin(); + end = begin+1; + + return true; + } +}; + +template<class STORED, class CONTAINER> +bool HLTNavDetails::HolderImp<STORED, CONTAINER>::contains(const STORED* obj, HLT::TriggerElement::ObjectIndex& idx) const { + typedef Holder<STORED> H; + if ( !const_cast<HolderImp<STORED, CONTAINER>* >(this)->syncWithSG() ) + return false; + + HMLOG(VERBOSE) << "HolderImp::contains" << endreq; + uint32_t begin=0; + uint32_t end=0; + bool ok = isin<STORED, CONTAINER, + boost::is_same<STORED, CONTAINER>::value>::do_it (obj, m_containerProxy.data(), H::m_log, begin, end); + if ( !ok ) { + HMLOG(VERBOSE) << "HolderImp::contains object " << obj << " not in the holder" << *this << endreq; + return false; + } + idx = HLT::TriggerElement::ObjectIndex(H::subTypeIndex(),begin,end); + HMLOG(VERBOSE) << "HolderImp::contains object " << obj << " found by in holder" << *this << " " << idx << endreq; + return true; +} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +bool HLTNavDetails::HolderImp<STORED, CONTAINER>::getElementLinks(ElementLinkVector<CONTAINER>& cont, + HLT::TriggerElement::ObjectIndex idx) { + typedef Holder<STORED> H; + if ( !syncWithSG() ) + return false; + + HMLOG(VERBOSE) << "HolderImp::getElementLinks(ELV, Index) getting objects" << endreq; + for (unsigned i = idx.objectsBegin(); i != idx.objectsEnd(); ++i ){ + cont.push_back(ElementLink<CONTAINER>(*(m_containerProxy.data()), i)); + } + return true; +} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +bool HLTNavDetails::HolderImp<STORED, CONTAINER>::getElementLinks(ElementLinkVector<CONTAINER>& cont) { + + typedef Holder<STORED> H; + if ( !syncWithSG() ) + return false; + HMLOG(VERBOSE) << "HolderImp::getElementLinks (ELV) getting all objects" << endreq; + for (unsigned i = 0; i < m_containerProxy.data()->size(); ++i ){ + cont.push_back(ElementLink<CONTAINER>(*(m_containerProxy.data()), i)); + } + return true; +} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +std::string HLTNavDetails::HolderImp<STORED, CONTAINER>::getUniqueKey() { + HMLOG(VERBOSE) << "HolderImp::getUniqueKey" << endreq; + if ( !syncWithSG() ) + return "Bad_Key"; + return IHolder::generateAliasKey( Holder<STORED>::typeClid(), + Holder<STORED>::subTypeIndex(), + Holder<STORED>::label(), + m_containerProxy.data()->size() ); +} + +template<class STORED, class CONTAINER> +std::string HLTNavDetails::HolderImp<STORED, CONTAINER>::getNextKey() { + HMLOG(VERBOSE) << "HolderImp::getNextKey" << endreq; + return getUniqueKey(); +} + + + + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +bool HLTNavDetails::HolderImp<STORED, CONTAINER>::serialize(std::vector<uint32_t>& output) const { + typedef Holder<STORED> H; // this is to make things below shorter + + HMLOG(VERBOSE) << "HolderImp::serialize " << *this << endreq; + // if feature to be forgotten then indication of it is simply 0 size of serialized vector + H::serialize(output); + + + // copy(output.begin(), output.end(), std::ostream_iterator<int>(std::cerr, " S ")); + // std::cerr << "\n"; + return true; +} + + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +bool HLTNavDetails::HolderImp<STORED, CONTAINER>::deserialize(const std::vector<uint32_t>& input) { + // first is recorded method of serialization used for this feature + typedef Holder<STORED> H; // this is to make things below shorter + // copy(input.begin(), input.end(), std::ostream_iterator<int>(std::cerr, " D ")); + // std::cerr << "\n"; + HMLOG(VERBOSE) << "HolderImp::deserialize " << *this << endreq; + CLID c; + std::vector<uint32_t>::const_iterator it = input.begin(); + if ( ! IHolder::enquireSerialized(input, it, + c, H::m_label, H::m_subTypeIndex ) ) { + HMLOG(WARNING) << "HolderImp::deserialize failed to enquire serialized blob of data" << endreq; + return false; + } + HMLOG(DEBUG) << "HolderImp::deserialize success " << *this << endreq; + return true; +} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED> +void HLTNavDetails::Holder<STORED>::print(MsgStream& m) const { + IHolder::print(m); + m << " Stored type name: " << ClassID_traits<STORED>::typeName(); +} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +void HLTNavDetails::HolderImp<STORED, CONTAINER>::print(MsgStream& m) const { + Holder<STORED>::print(m); + m << " Collection type name: " << ClassID_traits<CONTAINER>::typeName() << " CLID: " << ClassID_traits<CONTAINER>::ID(); + if ( not m_containerProxy.empty() ) + m << " size: " << m_containerProxy.data()->size() << " @"<<m_containerProxy.data(); + else + m << " container not allocated yet"; +} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +DataObject* HLTNavDetails::HolderImp<STORED, CONTAINER>::getDataObject() { + if(!m_containerProxy.data()) return 0; + return SG::asStorable(m_containerProxy.data()); +} + +#define _IS_AUXTYPE_ !boost::is_same<typename Container2Aux<T>::type,HLT::TypeInformation::no_aux>::value + +struct AuxDataObjectHelper{ + template<typename T> + static typename std::enable_if<!_IS_AUXTYPE_,DataObject*>::type get(HLTNavDetails::ITypeProxy*/* aux*/){ + return 0; + } + template<typename T> + static typename std::enable_if<_IS_AUXTYPE_,DataObject*>::type get(HLTNavDetails::ITypeProxy* aux){ + typedef typename Container2Aux<T>::type auxtype; + HLTNavDetails::TypeProxy<auxtype>* auxcasted = static_cast<HLTNavDetails::TypeProxy<auxtype>*>(aux); + if(auxcasted){ + if(!auxcasted->data()) return 0; + return SG::asStorable(auxcasted->data()); + } + return 0; + } + template<typename T> + static typename std::enable_if<!_IS_AUXTYPE_,bool>::type set(HLTNavDetails::ITypeProxy*,DataObject*){ + return true;//always success + } + template<typename T> + static typename std::enable_if<_IS_AUXTYPE_,bool>::type set(HLTNavDetails::ITypeProxy* aux, DataObject* dobjaux){ + typedef typename Container2Aux<T>::type auxtype; + HLTNavDetails::TypeProxy<auxtype>* auxcasted = static_cast<HLTNavDetails::TypeProxy<auxtype>*>(aux); + if(auxcasted){ + bool success = SG::fromStorable(dobjaux,auxcasted->data_ref()); + auxcasted->syncTypeless(); + REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"Holder") << "set from storable " << success << " to address " << auxcasted->data() << std::endl; + return success; + } + return 0; + } +}; + + +template<class STORED, class CONTAINER> +DataObject* HLTNavDetails::HolderImp<STORED, CONTAINER>::getAuxDataObject() { + return AuxDataObjectHelper::get<CONTAINER>(this->m_aux); +} + +template<class STORED, class CONTAINER> +bool HLTNavDetails::HolderImp<STORED, CONTAINER>::setAuxDataObject(DataObject* dobjaux) { + bool status = AuxDataObjectHelper::set<CONTAINER>(this->m_aux,dobjaux); + HMLOG(VERBOSE) << "container data is: " << m_containerProxy.data() << endreq; + SG::AuxVectorBase* container = m_containerProxy.castAuxVectorBase(); + if(!this->m_aux or !container){ + HMLOG(ERROR) << "in aux branch but aux type proxy or container proxy is null" << endreq; + HMLOG(ERROR) << "container is: " << container << endreq; + HMLOG(ERROR) << "aux is: " << this->m_aux << endreq; + return false; + } + SG::IAuxStore* aux = this->m_aux->castIAuxStore(); + if(!aux){ + HMLOG(ERROR) << "cast of auxstore failed " << endreq; + } + if(container and aux and status){ + HMLOG(VERBOSE) << "container is: " << container << endreq; + HMLOG(VERBOSE) << "aux is: " << this->m_aux << endreq; + container->setStore(aux); + return true; + } + HMLOG(WARNING) << "something went wrong setting aux data object " << endreq; + return false; +} + + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +bool HLTNavDetails::HolderImp<STORED, CONTAINER>::setDataObject(DataObject* dobj) { + bool success = SG::fromStorable(dobj, m_containerProxy.data_ref()); + m_containerProxy.syncTypeless(); + REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"Holder") << "set from storable " << success << " to address " << m_containerProxy.data(); + return success; +} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +HLTNavDetails::HolderImp<STORED, CONTAINER>::MemoryMgr::MemoryMgr(const FeatureProxy& st, bool sg) + : proxy(st), inSG(sg) +{} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +HLTNavDetails::HolderImp<STORED, CONTAINER>::MemoryMgr::MemoryMgr() + : inSG(false) +{} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +void HLTNavDetails::HolderImp<STORED, CONTAINER>::MemoryMgr::clear() { + // if the thing is not in SG it shoudl not be cleared, if is the SG will take care of it if ( !inSG ) proxy.clear(); +} + + + +///////////////////////////////////////////////////////////////////////////// +template<class STORED> +MsgStream& HLTNavDetails::operator<< ( MsgStream& m, const HLTNavDetails::Holder<STORED>& h ) { + h.print(m); + return m; +} + +///////////////////////////////////////////////////////////////////////////// +template<class STORED, class CONTAINER> +MsgStream& HLTNavDetails::operator<< ( MsgStream& m, const HLTNavDetails::HolderImp<STORED, CONTAINER>& h ) { + h.print(m); + return m; +} + + +#undef HMLOG +#undef MLOG +#endif diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/Navigation.h b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/Navigation.h new file mode 100644 index 0000000000000000000000000000000000000000..2340c314b8d4ded7a6fdaf8d78893c325ecc2e20 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/Navigation.h @@ -0,0 +1,233 @@ +// Emacs -*- c++ -*- + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +#ifndef TRIGNAVIGATION_HLTNAVIGATION_H +#define TRIGNAVIGATION_HLTNAVIGATION_H + +#include <stdint.h> +#include <set> +#include <sstream> +#include <iostream> + +//#include <boost/cstdint.hpp> +//#include <stdint.h> + +#include "GaudiKernel/ClassID.h" +#include "GaudiKernel/MsgStream.h" +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/ToolHandle.h" +#include "GaudiKernel/ServiceHandle.h" +#include "GaudiKernel/IConversionSvc.h" + +#include "DataModel/OwnershipPolicy.h" +#include "DataModel/DataVector.h" +#include "DataModel/ElementLinkVector.h" + +// for 2 ways of performing serialization +#include "StoreGate/StoreGateSvc.h" +//#include "TrigSerializeResult/ITrigSerializerToolBase.h" +//#include "TrigSerializeCnvSvc/TrigSerializeCnvSvc.h" +//#include "TrigSerializeResult/StringSerializer.h" + +#include "TrigNavigation/NavigationCore.h" +#include "TrigNavigation/TriggerElement.h" +#include "TrigNavigation/Holder.h" + +class StringSerializer; + +static const InterfaceID IID_TrigNavigation("TrigNavigation", 1 , 0); + + +namespace HLT { + + + + /** + * @brief The Navigation class, organizes TriggerElements into the tree structure. + * + * @author Tomasz Bold <Tomasz.Bold@cern.ch> - U. of California - Irvine + * @author Till Eifert <Till.Eifert@cern.ch> - U. of Geneva, Switzerland + * @author Nicolas Berger <Nicolas.Berger@cern.ch> - CERN + * + * The class is providing an interface to the whole navigation. The internal ingredients + * of the navigation which are TriggerElements are well hidden. + * All operations on the navigation structure are possible only via trick class. + * This operations are basically: + * + * -# creation of TriggerElements + * - creation of the initial (root) node + * - creation of RoI nodes (one per RoI, also for secondary RoIs) + * - creation of normal nodes (seed by one TriggerElement) + * - creation of normal nodes suitable for topological selection (being seed by 2 TriggerElements) + * . + * The created nodes are given to user with all the navigational links prepared + * + * -# features attaching and retrieval + * - attaching feature to node + * - attaching feature to RoI node ( therefore all TE originating from node can use it ) + * - attaching feature to initial (root) node for global (event wide) features + * - retrieval of features attached to given node + * - retrieval of features attached to given node or any predecessor (back to an initial node) + * - retrieval of features attached to given node or any predecessor (traversing back to an initial node) + * - retrieval of recent feature attached to given node or any predecessor (traversing back to an initial node) + * - retrieval of features attached to RoI nodes of given TriggerElement + * - retrieval of features attached to initial (root) node + * . + * + * -# queering methods + * - simple queries (isInitial, isTerminal, isRoI) + * - more complicated queries for 2 TriggerElements (if they share RoI etc) + * - global comparison for 2 navigation structures (needed up to the moment only for validation of serialization) + * - query for all TriggerElements of a given type + * Queries are designed to be usable with STL algorithms. + * + * + * Documentation of EDM related upgrade: + * -# objects storage + * - all possible types are known at compile time (Scott's magic) + * - some collections are placed in the SG always independently of the event content + * - there can be more collection of given type (one for each user label i.e. number of tracks collections) + * - if in navigation config this is given: TrigVertexCollection#HLTAutoKey_T2HistoPrmVtx --> + * then DataVector<TrigVertexCollection> of label "HLTAutoKey_T2HistoPrmVtx" is placed in the SG in every event + * - if in config only type is mentioned TrigVertexCollection#HLTAutoKey ---> + * then DataVector<TrigVertexCollection> of label HLTAutoKey is placed in SG for each event + * - if nothing is mentioned in config the DataVector<TrigVertexCollection> labeled at runtime depending on user labels will be placed in SG (one per label) + * + * - the object of given type are then organized then as follows: + * there is many collections of given type per event (each for one label) + * this collections are accessible by label or "SubTypeIndex" + * second is to keep the TE -> feature link unchanged if we remove obe of collection during slimming or we simply not record it + * + * Is is like this + * collection of type T |XXXXXXX| label: ID subTypeIndex: 0 + * collection of type T |XXXX| label: MS subTypeIndex: 1 + * collection of type T |XXXXXXXXXXXXX| label: Muons subTypeIndex: 2 + * collection of type T |XXXXXXXX| label: Calo subTypeIndex: 3 + * + * -# the features <-> TE link + * - Features are located in supercontainers DataVector<TrigVertexCollection> + * - each label yields in one supercontainer (the unlabeled objects are in the container with HLTAutoKey_ label) + * - The link to object in the TE is composed out of 2 numbers CLID, and index + * - index (from above) is composed out of 2 parts collection coordinate and second is coordinate within collection + * - this way we do not need to touch TE serialization/desetialization + * - collection index and inter-collection index are uint16_t word which means we are limited to 65000 collections + * of given type and same number of objects in each sub collection + */ + + + class Navigation : public AthAlgTool, public NavigationCore { + + public: + + Navigation( const std::string& type, + const std::string& name, + const IInterface* parent ); + + virtual ~Navigation(); + static const InterfaceID& interfaceID() { + return IID_TrigNavigation; + } + + virtual StatusCode initialize(); //!< initialization, there JO are read,parsed + virtual StatusCode finalize(); //!< finalization, as reset() + + + + + /** + * @brief attaches feature to given TriggerElement + * @param te TriggerElement to which attach feature + * @param feature is feature ptr to attach + * @param key is filled up by the key used to put into SG (if not SG is involved then untouched) + * @param label for additional marking of this feature + * @return false if error enountered, true if no error encountered + * if this feature is on the list of classes to be serialized by reference then + * it is put into the SG (using SG->record) + */ + template<class T> + bool attachFeature( TriggerElement* te, const T* feature, + MemoryManagement, std::string& key, + const std::string& label="" ); + + // template<class T> bool attachFeature( TriggerElement* te, typename DataVector<T>::const_iterator begin, + // typename DataVector<T>::const_iterator end, + // MemoryManagement, std::string& key, + // const std::string& label="" ); + + + /* + * brief attaches feature to given TriggerElement + * param te TriggerElement to which attach feature + * param feature is feature ptr to attach + * param label for additional marking of this feature + * warning WILL REMOVE IT, seems to be unusable, everyone can do the loop by him/herself + * + * template<class T> bool attachFeatures( TriggerElement* te, const std::vector<T*>& features, const std::string& label="" ); + */ + + + + + + + + + /** + * @brief find all TriggerElements which have this object attached given feature + * @warning This search is costly since all TEs needs to be searched for. It can be significantly improved if + * search is limited to TEs with given ID + * @param obj is a pointer to object of interest + * @param owners is a vector of TEs which will be filled by all owners of the feature + * @param id the id of TEs which should be inspected + * @return true if no error was encountered, this does not mean that object is found, false if data access error occured + **/ + template<class T> bool findOwners(const T* obj, std::vector<const TriggerElement*>& owners, unsigned int id = 0); + + /** + * @brief Get the next key for a given object + */ + template<class T> const std::string getNextKey( const std::string& label = "" ); + + /** + * @brief Get a unique key (not in the usual series) for a given object + */ + template<class T> const std::string getUniqueKey( const std::string& label = "" ); + + + protected: + Navigation(); //> not implemented + Navigation (const Navigation&); //> not implemented + Navigation& operator= (const Navigation&); //> not implemented + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + private: + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // features holding classes + + + // private stuff of Navigation class + + + ServiceHandle<IConversionSvc> m_serializerServiceHandle; + ServiceHandle<StoreGateSvc> m_storeGateHandle; + StringSerializer *m_stringSerializer; + std::vector<std::string> m_dlls; + + + StatusCode classKey2CLIDKey(const std::vector<std::string> prop, std::vector<std::pair<CLID, std::string> >& decoded); + + + + }; + + MsgStream& operator<< ( MsgStream& m, const Navigation& nav ); //<! printing helper + +} // eof namespace + +//#include "TrigNavigation/Navigation.icc" + +#endif //#ifndef HLTNAVIGATION_H diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/Navigation.icc b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/Navigation.icc new file mode 100644 index 0000000000000000000000000000000000000000..f50ac24f2b1814752dc68ea0e12edf6d3a9c9b93 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/Navigation.icc @@ -0,0 +1,267 @@ +// Emacs -*- c++ -*- + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +#ifndef TRIGNAVIGATION_HLTNAVIGATION_ICC +#define TRIGNAVIGATION_HLTNAVIGATION_ICC + + +/***************************************************************************** + * + * COMPILE TYPE OBJECTS REGISTRATION + * + *****************************************************************************/ + +#include <boost/type_traits.hpp> +#include "TrigNavigation/Holder.h" +#include "TrigNavigation/RoICacheHistory.h" + +#undef MLOG +#define MLOG(x) if (m_log->level()<=MSG::x) *m_log << MSG::x + + + +/***************************************************************************** + * + * FEATURES OPERATIONS + * + *****************************************************************************/ + +template<class T> +__attribute__((__used__)) +bool HLT::Navigation::attachFeature( TriggerElement* te, const T* feature, + MemoryManagement mmanagement, std::string& key, + const std::string& label ) { + //typedef DataVector<T> C; + // // NavHook<T>::instan(); + + // Get clid + CLID clid = ClassID_traits<T>::ID(); + + MLOG(DEBUG) << "attachFeature: of clid: " << clid << "(" << ClassID_traits<T>::typeName() << ")" + << " to TE: " << te->getId() + << " label: \"" << label << "\"" + << " memory management: " << mmanagement << endreq; + + // get a holder for this type --- if that's new it will be created + + HLTNavDetails::Holder<T>* holder = getHolder<T>(label, nextSubTypeIndex(clid,label)); + + if ( ! holder ) { + MLOG(WARNING) << "attachFeature: Holder missing for CLID: " << clid << endreq; + return false; + } + // holder is keeping all objects of given class (indexes in this holder are used to get back to it) + // unsigned int index = holder->getFeatures().size(); + + + // do forced SG registration + /* std::string key; + if ( ObjectToStoreGate == mmanagement ) { + key = holder->getUniqueKey(); + if ( m_storeGate->record(feature, key).isFailure() ) { + MLOG(WARNING) << "attachFeature: feature of type: " << ClassID_traits<T>::typeName() + << " and clid: " << clid << " can't be placed directly in SG" << endreq; + } else { + MLOG(DEBUG) << "attachFeature: feature SG direct registration succesful with the key:" << key << endreq; + } + } + */ + + TriggerElement::ObjectIndex objectIndex = holder->add(feature, mmanagement == ObjectInStoreGate, key); + if ( not objectIndex.valid() ) + return false; + te->addFeature(clid, objectIndex, false); + RoICacheHistory::RememberAttachFeature(te, clid, label, this, objectIndex); + return true; +} + + + + + +/* + //std::cerr << "Holder<" << m_typeName <<">::deserialize: unpacking labels, size of serialized:" << m_serialized << std::endl; + // first is recorded method of serialization used for this feature + SerializationMethod serializationMethod = (SerializationMethod)(input[0]); + + // then comes size of serialized labels + uint32_t sizeOfLabels = input[1]; + + + + std::vector<uint32_t>::const_iterator begin = input.begin(); + std::advance(begin, 2); // + + std::vector<uint32_t>::const_iterator end = begin; + std::advance(end, sizeOfLabels); + + // unpack labels + std::vector<std::string> labels; + std::vector<uint32_t> serializedLabels; + // copy out serialized lables + + //std::cerr << "Holder<" << m_typeName <<">::deserialize: unpacking labels, size of serialized:" << sizeOfLabels << std::endl; + serializedLabels.insert(serializedLabels.end(), begin, end ); + m_stringSerializer->deserialize(serializedLabels, labels); + + //std::cerr << "Holder<" << m_typeName <<">::deserialize: unpacked labels" << std::endl; + //for ( unsigned int lab = 0 ; lab < labels.size() ; ++lab ) { + // std::cerr << "Holder<" << m_typeName <<">::deserialize: label " << lab << " " << labels[lab] << std::endl; + // } + + // unpack object itself + begin = end; + end = input.end(); + + std::vector<uint32_t> serializedObjects; + serializedObjects.insert(serializedObjects.end(), begin, end ); + + begin = serializedObjects.begin(); + if ( SerializeByPayload == serializationMethod) { + + std::vector<uint32_t> oneSerializedObject; + for ( unsigned int obj = 0; obj < labels.size() ; ++obj ) { + // std::cerr << "Holder<" << m_typeName <<">::deserialize: starting with: " << labels[obj] << std::endl; + uint32_t sizeOfObject = *begin; + // std::cerr << "Holder<" << m_typeName <<">::deserialize: oneObjectSize: " << sizeOfObject << std::endl; + advance(begin, 1); + end = begin; + advance(end, sizeOfObject); + oneSerializedObject.clear(); + oneSerializedObject.insert(oneSerializedObject.end(), begin, end); + begin = end; + + // std::cerr << "Holder<" << m_typeName <<">::deserialize: oneObjectDeserialization size: " << oneSerializedObject.size() << std::endl; + m_serializer->reset(); + T* ptr = (T*)m_serializer->deserialize( m_typeName, oneSerializedObject); + + std::string key; + addFeature(ptr, key, labels[obj], RecordInSG); // features not in SG and should be deleted + } + } else if ( SerializeByReference == serializationMethod) { + + //std::cerr << "Holder<" << m_typeName <<">::deserialize: from StoreGate" << std::endl; + // retrieve this objects from SG + unsigned int size = labels.size(); + if (size == 0) + return true; + // std::cerr << "deserializing: " << m_typeName << " and the size is: " << size << std::endl; + + + // loop and regenerate the keys + for ( unsigned int i = 0 ; i < size; ++i ) { + const std::string& key = generateAliasKey(i, labels[i]); + const T* object; + //std::cerr << "deserializing: " << m_typeName << " and the key is: " << key << " sg ptr: " << m_storeGate << std::endl; + if ( m_storeGate->retrieve(object, key).isFailure() ) + return false; + + // if ( m_storeGate->remove(object).isFailure() ) + // return false; + std::string newkey; + //std::cerr << "deserializing: " << m_typeName << "adding feature with key: " << key << " " << labels[i] << std::endl; + addFeature(object, newkey, labels[i], InSG); // features in SG and shouldn't be deleted + } + } + return true; +} + +template<class T> +const std::string HLT::Navigation::Holder<T>::getNextKey( const std::string& label ) const { + return generateAliasKey( m_pointers.size(), label); +} + +template<class T> +const std::string HLT::Navigation::Holder<T>::getUniqueKey( const std::string& label ) const { + static unsigned int counter = 0; + counter--; + return generateAliasKey(counter , label); +} +*/ + + +///////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// +template<class T> +__attribute__((__used__)) +bool HLT::Navigation::findOwners(const T* obj, std::vector<const TriggerElement*>& owners, unsigned int id) { + std::vector<TriggerElement*>::const_iterator it = m_factory.listOfProduced().begin(); + std::vector<TriggerElement*>::const_iterator itEnd = m_factory.listOfProduced().end(); + if ( id != 0 ) { + it = m_factory.listOfProduced(id).begin(); + itEnd = m_factory.listOfProduced(id).end(); + MLOG(VERBOSE) << "findOwners will scann TEs of ID : " << id << " #: " << itEnd-it << endreq; + } else { + MLOG(VERBOSE) << "findOwners will scann ALL TEs (slow):" << itEnd-it << endreq; + } + + CLID clid = ClassID_traits<T>::ID(); + std::map<CLID, std::map<uint16_t, HLTNavDetails::IHolder*> >::const_iterator hit = m_featuresByIndex.find(clid); + if (hit == m_featuresByIndex.end() ) { + return true; + } + MLOG(VERBOSE) << "findOwners features of this CLID present " << endreq; + bool holderFound = false; + HLT::TriggerElement::ObjectIndex idx; + std::map<uint16_t, HLTNavDetails::IHolder*>::const_iterator holderIt = hit->second.begin(); + std::map<uint16_t, HLTNavDetails::IHolder*>::const_iterator holderEnd = hit->second.end();; + for ( ; holderIt != holderEnd; ++holderIt ) { + HLTNavDetails::Holder<T>* holder = (HLTNavDetails::Holder<T>*)holderIt->second; + if ( holder->contains(obj, idx) ) { + holderFound = true; + MLOG(VERBOSE) << "findOwners found holder owning the object " << *holder << " and index: " << idx << endreq; + break; + } + } + if ( !holderFound ) + return true; + + // tmp vec + // std::vector<const T*> tmp; + for (; it != itEnd; ++it ) { + // tmp.clear(); + std::vector< TriggerElement::FeatureAccessHelper >::const_iterator featureAccessIt = (*it)-> getFeatureAccessHelpers().begin(); + std::vector< TriggerElement::FeatureAccessHelper >::const_iterator featureAccessEnd = (*it)-> getFeatureAccessHelpers().end(); + + for ( ; featureAccessIt != featureAccessEnd ; ++featureAccessIt ) { + if ( featureAccessIt->getCLID() == clid && + featureAccessIt->getIndex().isSameOrWithin(&idx) ) { + owners.push_back(*it); + MLOG(VERBOSE) << "findOwners while looking in TE(id): " << *it <<"(" << (*it)->getId() << ")" << " and access helper " << featureAccessIt->getIndex() << " found owner " << endreq; + break; + } + } + } + return true; +} + +template<class T> +__attribute__((__used__)) +const std::string HLT::Navigation::getNextKey( const std::string& label ) { + CLID clid = ClassID_traits<T>::ID(); + HLTNavDetails::Holder<T>* holder = getHolder<T>(label, nextSubTypeIndex(clid,label)); + if (!holder) return ""; // should never happen, but who knows + + return holder->getNextKey( ); +} + +template<class T> +__attribute__((__used__)) +const std::string HLT::Navigation::getUniqueKey( const std::string& label ) { + CLID clid = ClassID_traits<T>::ID(); + HLTNavDetails::Holder<T>* holder = getHolder<T>(label, nextSubTypeIndex(clid, label)); + + if (!holder) return ""; // should never happen, but who knows + + return holder->getUniqueKey( ); +} + + +#undef MLOG +//EOF +#endif // TRIGNAVIGATION_HLTNAVIGATION_ICC diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/NavigationCore.h b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/NavigationCore.h new file mode 100644 index 0000000000000000000000000000000000000000..8ecf0cf0e45d0c4a1fa092789e285c91e323d7a4 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/NavigationCore.h @@ -0,0 +1,551 @@ +// Emacs -*- c++ -*- + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +#ifndef TRIGNAVIGATION_HLTNAVIGATIONCORE_H +#define TRIGNAVIGATION_HLTNAVIGATIONCORE_H + +#include <stdint.h> +#include <set> +#include <sstream> +#include <iostream> + +//#include <boost/cstdint.hpp> +//#include <stdint.h> + +#include "GaudiKernel/ClassID.h" +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/ServiceHandle.h" + +#include "DataModel/OwnershipPolicy.h" +#include "DataModel/DataVector.h" + +// for 2 ways of performing serialization +#include "StoreGate/StoreGateSvc.h" +//#include "TrigSerializeResult/ITrigSerializerToolBase.h" +//#include "TrigSerializeCnvSvc/TrigSerializeCnvSvc.h" + +#include "TrigNavStructure/TrigNavStructure.h" + +#include "TrigNavigation/Holder.h" +#include "TrigNavigation/TypeProxy.h" +#include "TrigNavigation/AccessProxy.h" +#include "TrigNavigation/TypeMaps.h" +#include "TrigNavigation/TrigFeatureLink.h" + + + +#include "TrigStorageDefinitions/EDM_TypeInfoMethods.h" + +class StringSerializer; + +//static const InterfaceID IID_TrigNavigation("TrigNavigation", 1 , 0); + + +namespace HLTNavDetails { class TypeMapDeleter; } + +class TrigBStoxAODTool; + +namespace HLT { + class TrigNavigationSlimmingTool; + /** + * @brief The NavigationCore class, adds on top of the TrigNavStructure the EDM read-only handling + * + * @author Tomasz Bold <Tomasz.Bold@cern.ch> - U. of California - Irvine + * @author Till Eifert <Till.Eifert@cern.ch> - U. of Geneva, Switzerland + * @author Nicolas Berger <Nicolas.Berger@cern.ch> - CERN + * + * + * The created nodes are given to user with all the navigational links prepared + * + * -# features attaching and retrieval (the retrieval is implemented by this class whilc the attachement only needed in athena is in the HLTNavgation tool) + * - attaching feature to node + * - attaching feature to RoI node ( therefore all TE originating from node can use it ) + * - attaching feature to initial (root) node for global (event wide) features + * - retrieval of features attached to given node + * - retrieval of features attached to given node or any predecessor (back to an initial node) + * - retrieval of features attached to given node or any predecessor (traversing back to an initial node) + * - retrieval of recent feature attached to given node or any predecessor (traversing back to an initial node) + * - retrieval of features attached to RoI nodes of given TriggerElement + * - retrieval of features attached to initial (root) node + * . + * + * + * Documentation of EDM related upgrade: + * -# objects storage + * - all possible types are known at compile time (Scott's magic) + * - configured collections are placed in the SG always independently of the event content + * - there can be more collection of given type (one for each user label i.e. there can be several of tracks collections depending on the reconstruction) + * + * - the object of given type are then organized then as follows: + * there is many collections of given type per event (each for one label) + * this collections are accessible by label or "SubTypeIndex" uint16_t - it is used to save space in the creation of the link from TE to the feature + * + * Is is like this + * collection of type T |XXXXXXX| label: ID subTypeIndex: 0 + * collection of type T |XXXX| label: MS subTypeIndex: 1 + * collection of type T |XXXXXXXXXXXXX| label: Muons subTypeIndex: 2 + * collection of type T |XXXXXXXX| label: Calo subTypeIndex: 3 + * (nothe that the association is not hardcoeded anywhere and can change from event to event. For that reason the association between the label and SubTypeIndex is recorded.) + * + * -# the features <-> TE link + * - Features are located in supercontainers DataVector<TrigVertexCollection> + * - each label yields in one supercontainer (the unlabeled objects are in the container with HLT_label) + * - The link to object in the TE is composed out of 2 numbers CLID, and index + * - index (from above) is composed out of 2 parts collection coordinate and second is coordinate within collection + * - collection index and inter-collection index are uint16_t word which means we are limited to 65000 collections + * of given type and same number of objects in each sub collection (this has been lifted up actually) + */ + + + class NavigationCore : public HLT::TrigNavStructure { + friend class HLT::TrigNavigationSlimmingTool; + friend class HLTNavDetails::TypeMapDeleter; + friend class ::TrigBStoxAODTool; + public: + /** + * @brief constructor gets as an argument the TriggerElementFactory + * + * Will revise this Factory concept since it is probably better + * to have templated factory ... to instantiate RoIDescriptors this way as well + */ + + NavigationCore(); + virtual ~NavigationCore(); + + /* + Navigation( const std::string& type, + const std::string& name, + const IInterface* parent ); + + + static const InterfaceID& interfaceID() { + return IID_TrigNavigation; + } + + virtual StatusCode initialize(); //!< initialization, there JO are read,parsed + virtual StatusCode finalize(); //!< finalization, as reset() + */ + + + /** + * @brief prepapres the navigation for next event + */ + virtual void prepare(); + /** + * @brief resets all the navigation, goes to the factory and asks to withdraw all produced objects + */ + virtual void reset(); + + /** + * @brief method serizlizes the navigation structure + * The structure is serrizlized in following order ... + * 1. TEs(together with links) + * 2. features in accordane to the lists given in property ClassesToPayload + * + * The truncation mechainsm. The parameter space should be given to the method. + * No more space than that will be ever taken. But since the actuall space limitation is not known + * at the time whrn this call happens additional list of safe to cut places is returned. + * One may ask why no tonly this cuts. ... Answer is follwing. If the event is huge then + * giving this rought limit would make procedure faster since not all features will + * be serialized. Otherwice they would be serialized and then thrown away, which is waste of CPU. + * For safe operation one can easilly make space huge (like 2MB) and not care. But for online such tuning + * can be considered. Space can be given as a property. + * + * @param output vector to place the result + * @param cuts are indexes where one can safely cut the navigation + * + * @return if true then OK + * if false then truncated because of missing space - if output.size() != 0 + * if false and output.size() == 0 internal error + */ + bool serialize( std::vector<uint32_t>& output, std::vector<unsigned int>& cuts ) const; + bool serialize( std::vector<uint32_t>& output, std::vector<unsigned int>& cuts, std::vector<std::pair<CLID, std::string> >& clid_name) const; + bool serialize_DSonly( std::vector<uint32_t>& output, std::vector<unsigned int>& cuts, std::vector<std::pair<CLID, std::string> >& clid_name) const; + bool deserialize( const std::vector<uint32_t>& input ); + + /** + * @brief reports on number of features which were unpacked frm BS but never accessed + * This mehtod is to report what objects are unnecesarilly put in BS or not extracted. + */ + //int numberOfSerializedByPayload( std::vector<CLID>& listOfTypes ); + + + /** + * @brief defines 3 possible origins of the objects which are attached to TEs + * This should be used like this: + * -# All the objects which are produced out of blue + * using "new" operator should be attached with ObjectCreatedByNew switch. + * This objects may also go to SG depending on configuration. + * -# All objects which needs to be registered in the StoreGate + * should be registered using switch "ObjectToStoreGate" which tells + * basically thet SG take control over the cleanup. + * All objects registered like this will for sure go to SG. + * -# the switch "ObjectInStoreGate" should be used for objects + * which are already in SG. (i.e. put there by offline reco. tools). + */ + enum MemoryManagement { ObjectInStoreGate = 1, ObjectToStoreGate = 2, ObjectCreatedByNew = 3 }; + + + /** + * @brief retrieve features attached to given TriggerElement + * @param te TriggerElement from retrieve + * @param features is collection to be feed + * @param label for additional marking of this feature + * @param labels list of all features of this type already in place and thier labels + * @return false if error enountered, true if no error encountered + * @warning No error (return true) does not mean that features were found, + * therefore what has to be checked is ... returned bool and + * size of features vector (if it has grew). + */ + template<class T> + bool getFeatures( const TriggerElement* te, std::vector< const T*>& features, const std::string& label="", + std::map<const T*, std::string>* labels=0 ); + + template<class T> + bool getFeature( const TriggerElement* te, const T*& features, const std::string& label="", std::string& sourcelabel = m_unspecifiedLabel); + + template<class T> + const T* featureLink2Object( const TrigFeatureLink& ); + + template<class T> + TrigFeatureLink object2FeatureLink(const TriggerElement* te, const std::string& label, + const T* obj); + + + template<class C> + TrigFeatureLink object2FeatureLink(const TriggerElement* te, const std::string& label, + const typename Container2Object<C>::type * obj, + const C* container); + + //const TriggerElement* te, const T*& features, const std::string& label="", std::string& sourcelabel = m_unspecifiedLabel); + + + template<class C, class T> + bool getFeaturesLinks( const TriggerElement* te, ElementLinkVector<C>& links, const std::string& label=""); + + + + /** + * @brief retrieve features attached to given TriggerElement or its predecessors + * the algorithm will go recursively to all predecessors and once the feature is found attached to given TE + * returns all features (of this type and label) attached to this TE + * @param te TriggerElement from which to start + * @param features is vector to be filled up + * @param label for additional marking of this feature + * @param labels list of all features of this type already in place and thier labels (of not specified) faster query + * @return false if error enountered, true if no error encountered + * @warning No error (return true) does not mean that features were found, + * therefore what has to be checked is ... returned bool and + * feature ptr != 0; + */ + template<class T> + bool getRecentFeatures( const TriggerElement* te, + std::vector< const T*>& features, const std::string& label="", + std::map<const T*, std::string>* labels=0 ); + + template<class T> + bool getRecentFeature( const TriggerElement* te, + const T*& feature, const std::string& label="", + const TriggerElement*& source = m_unspecifiedTE, + std::string& sourcelabel = m_unspecifiedLabel ); + + template<class LinkType> + bool getRecentFeatureDataOrElementLink( const TriggerElement* te, + LinkType& link, const std::string& label="", + const TriggerElement*& source = m_unspecifiedTE, std::string& sourcelabel = m_unspecifiedLabel); + + template<class C, class T> + bool getRecentFeaturesLinks( const TriggerElement* te, + ElementLinkVector<C>& links, const std::string& label="" ); + + template<class C, class T> + bool getRecentFeatureLink( const TriggerElement* te, + ElementLink<C>& link, const std::string& label="", + const TriggerElement*& source = m_unspecifiedTE, + std::string& sourcelabel = m_unspecifiedLabel ); + + + + /** + * @brief retrieve features accessors according to the requrements + * This method is actually workhorse for all above. I.e. the TEs structure traversing happens inside it. + * + * @param te is TriggerElement at which searching starts + * @param clid is ClassID of type which is searched for + * @param label is object label (as used by attachFeature), empty lables (i.e. == "") means any label, + * nonempty label means exact matching, and noverlty label == "!" means we are specifically looking for empty label + * @param only_single_feature if true means we are looking for only one last object (i.e. imagine several object of the same type attached to TE) + * @param features vector of FeatureAccessHelper objects to fill up + * @param with_cache_recording record informations for caching + * @param travel_backward_recursively if true will doe actual travering TriggerElement structure to find objects, if false search will stop at the TriggerElement te + * @param source TriggerElement where the object was found (or query stopped) + * @param sourcelabel is labels which the object had (useful when calling this routine with empty label) + **/ + + bool getFeatureAccessors( const TriggerElement* te, CLID clid, const std::string& label, + bool only_single_feature, + TriggerElement::FeatureVec& features, + bool with_cache_recording, + bool travel_backward_recursively, + const TriggerElement*& source = m_unspecifiedTE, + std::string& sourcelabel = m_unspecifiedLabel); + + + /** + * @brief retrieve features attached to the RoIs seeding this TriggerElement + * @param te TriggerElement from which start + * @param features is collection to be feed + * @param label for additional marking of this feature + * @return false if error enountered, true if no error encountered + * @param labels list of all features of this type already in place and thier labels (of not specified) faster query + * @warning No error (return true) does not mean that features were found, + * therefore what has to be checked is ... returned bool and + * size of features vector (if it has grew). + */ + template<class T> bool getFeaturesInRoI( const TriggerElement* te, std::vector<const T*>& features, + const std::string& label="", std::map<const T*, std::string>* labels=0 ); + + + /** + * @brief gets all features of type T atachedd to whichever TE + * @param features vector of pointers to features to which will be filled up + * @param label the label for a given feature + * @param labels list of all features of this type already in place and thier labels (of not specified) faster query + * @return true if no errors encountered + */ + template<class C, class T> bool getAllFeatures( ElementLinkVector<C>& features, const std::string& label="" ) ; + + + + /** + * @brief Specialized by type and container for this type + */ + template<class T, class C> static void registerFeatureContainer(); + + + + /** + * @brief attemtps to merge two trees + */ + + bool merge(const NavigationCore& l2); + + + void tweakMsgLvl(int newOffset); + + void testMsgService() const; //!< test Message Svc + + void testStaticMaps(); + + /** + * @brief convert strin g to hash. + * This is just making the function available, since there is no dict + * for TrigConf::HLTUtils + */ + static uint32_t string2hash( const std::string&, const std::string& category="TE" ); + + + /** + * @brief return trigger elements given the name of TEs + */ + void getAllOfType ( const std::string& id, + std::vector< HLT::TriggerElement* >& output, + const bool activeOnly=true) const; + + using HLT::TrigNavStructure::getAllOfType;//( const HLT::te_id_type id, std::vector< TriggerElement* >& output, const bool activeOnly = true ) const; + + /** @brief return StoreGate label and position for each feature. + * + * The format used here is: label::position, e.g. "HLT_initialRoi::1" + * @warning obsolete, will be removed + **/ + /* maybe now + std::vector< std::string > + getFeatureSGLabelAndPosition( unsigned int clid, const TriggerElement* te, + const std::string& label=""); + + std::vector< std::string > + getFeatureSGLabelAndPosition( std::string featureClassName, const TriggerElement* te, + const std::string& label=""); + + std::vector< std::string > + getRecentFeatureSGLabelAndPosition( unsigned int clid, const TriggerElement* te, + const std::string& label=""); + + std::vector< std::string > + getRecentFeatureSGLabelAndPosition( std::string featureClassName, const TriggerElement* te, + const std::string& label=""); + */ + + /** @brief retrieve position of features inside the SG collections + * + * All data objects (features) attached to the TriggerElement te - with the given CLID + label - + * are retrieved and their positions are returned. + * @warning obsolete, will be removed + **/ + /* maybe now + std::vector< unsigned int > + getFeatureContainerPosition( unsigned int clid, const TriggerElement* te, + const std::string& label); + + + std::vector< unsigned int > + getFeatureContainerPosition( std::string typeName, const TriggerElement* te, + const std::string& label); + */ + /** @brief retrieve position of features inside the SG collections + * + * All data objects (features) attached to the TriggerElement te - with the given CLID - + * are retrieved and their (label, position start - end) are returned. + * + * @warning obsolete, will be removed + */ + // used in: TrigOfflineVal.cxx (follow up) + /* + std::vector< HLT::FeatureDescriptor > + getFeatureContainerPosition( unsigned int clid, const TriggerElement* te); + + + std::vector< HLT::FeatureDescriptor > + getFeatureContainerPosition( std::string typeName, const TriggerElement* te); + + + std::pair<std::string, std::string> getClassContainerNames(unsigned int clid) const; + */ + + /** + * @brief sets the object mediating communcation with SG + * We need this extra lightweight layer because in ARA we need to redirect SG::retrieve calls to ROOT TTree + **/ + void setAccessProxy(AccessProxy* ap); + + /** + * @brief gets the access proxy + **/ + AccessProxy* getAccessProxy() const; + + /** + * @brief changes the default collections prefix (HLT) to another + **/ + void setObjKeyPrefix(const std::string& k); + + + template<class T> HLTNavDetails::Holder<T>* getHolder ( uint16_t subTypeIndex ); //!< as above but does not create holder on demand (return 0 if not found) + /////////////////////////////////////////////////////////////////////////////////////////////////////////// + protected: + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + // private stuff of Navigation class + + + bool createHolder ( HLTNavDetails::IHolder*& holder, CLID clid, const std::string& label, uint16_t idx ); //!< creates holder for type given by CLID + bool registerHolder ( HLTNavDetails::IHolder* holder ); + + template<class T> HLTNavDetails::Holder<T>* getHolder ( const std::string& label, uint16_t suggestedIndex ); //!< aware holder discovery, creates holder if needed + + // template<class T> HLTNavDetails::HolderCont<T>* getHolderCont ( const std::string& label ); //!< type aware holder discovery, creates holder if needed + // template<class T> HLTNavDetails::HolderCont<T>* getHolderCont ( uint16_t subTypeIndex ); //!< as above but does not create holder on demand (return 0 if not found) + HLTNavDetails::IHolder* getHolder ( CLID clid, uint16_t subTypeIndex ) const; //!< as above but not type wise holder returned + HLTNavDetails::IHolder* getHolder ( CLID clid, const std::string& label ) const; //!< as above + + std::map< CLID, std::map< uint16_t, std::string> > m_lookupLabels; + + typedef std::map<uint16_t, HLTNavDetails::IHolder*> IndexToHolderMap; + typedef std::map<std::string, HLTNavDetails::IHolder*> StringToHolderMap; + typedef std::map<CLID, IndexToHolderMap> FeaturesStructure; + typedef std::map<CLID, StringToHolderMap> FeaturesStructureLabelIndexed; + + FeaturesStructure m_featuresByIndex; //!< all objects map (it can be addressed by m_features[clid][idx] + + FeaturesStructureLabelIndexed m_featuresByLabel; //!< all objects map (it can be addressed by m_features[clid][label] + + std::map< CLID, std::vector<uint32_t>* > m_serializedFeatures; //!< map can be replaced by the same concept as in TriggerStore + + /** + * @brief Helper method for "combine": add one "level" of multiplicity to the results. + */ + bool addOneLevel(std::vector< std::vector<TriggerElement*> >& currentCombs, + std::vector< std::vector<std::pair<unsigned int, unsigned int> > >& currentIdxs, + unsigned int type, + std::vector< std::vector<TriggerElement*> >& newCombs, + std::vector< std::vector<std::pair<unsigned int, unsigned int> > >& newIdxs, + unsigned int maxResults = 1000, bool onlyActive = 1); + + + // ITrigSerializerToolBase* m_serializer; //!< pointer to Serializer + + MsgStream *m_log; //!< log stream + // IConversionSvc *m_serializerSvc; + ServiceHandle<IConversionSvc> m_serializerSvc; + StringSerializer *m_stringSerializer; + AccessProxy *m_storeGate; + // StoreGateSvc *m_storeGate; + // unsigned int m_serializeSpaceLimit; //!< proprty to limit BS content to some reasonable size + std::string m_objectsKeyPrefix; //!< property setting prefix which is to be given to all trigger EDM objects + unsigned m_objectsIndexOffset; //!< small integer used to generate sub type index + + typedef std::pair<CLID, std::string> CSPair; + + std::vector<std::string> m_classesToPayloadProperty; //!< list of classes#keys to be put to BS payload + std::vector<CSPair> m_classesToPayload; //!< classess are put to payload according to that priority list (CLID + key) + + std::vector<std::string> m_classesToPayloadProperty_DSonly; //!< list of classes#keys to be put to DS payload + std::vector<CSPair> m_classesToPayload_DSonly; //!< classess are put to payload according to that priority list (CLID + key) + + std::vector<std::string> m_classesFromPayloadProperty; //!< list of classes#keys to be extracted from BS payload + + + std::vector<std::string> m_classesToPreregisterProperty; //!< as above but for preregistration + std::vector<CSPair> m_classesToPreregister; //!< classes mentioned here will be put to SG irrespectively of thier presence in event + + + + /** + * @brief initialization helper - turns the list of class#key into map of CLID:key + * As the same conversion (class name ==> CLID) needs to be done for classes to payload and classes to preregister this is outsourced to this function + */ + StatusCode classKey2CLIDKey(const std::vector<std::string> prop, std::vector<CSPair>& decoded); + + + + bool m_referenceAllClasses; + inline bool toBeReferenced(CLID /*c*/) { return m_referenceAllClasses; } + bool toBePutToPayload(const HLTNavDetails::IHolder*) const; + + + + bool appendSerializedFeatureToPayload(CLID c, std::vector<uint32_t>& payload, const std::vector<uint32_t>& feature) const; + + + uint16_t nextSubTypeIndex(CLID clid, const std::string&label); + + bool addBlob(std::vector<uint32_t>& output, + const std::vector<uint32_t>& blob1, + const std::vector<uint32_t>& blob2 ) const ; + + bool extractBlob(const std::vector<uint32_t>& input, + std::vector<uint32_t>::const_iterator& it, + std::vector<uint32_t>& blob) const ; + + + + + private: + static const TriggerElement* m_unspecifiedTE; + static std::string m_unspecifiedLabel; + + HLTNavDetails::IHolder* prepareOneHolder(CLID clid, const std::string& label); + + }; + + MsgStream& operator<< ( MsgStream& m, const NavigationCore& nav ); //<! printing helper + +} // eof namespace + +//#include "TrigNavigation/NavigationCore.icc" + +#endif //#ifndef HLTNAVIGATION_H diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/NavigationCore.icc b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/NavigationCore.icc new file mode 100644 index 0000000000000000000000000000000000000000..88173e2e220078c069c2fc93c37e481eabb1a316 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/NavigationCore.icc @@ -0,0 +1,623 @@ +// Emacs -*- c++ -*- + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +#ifndef TRIGNAVIGATION_HLTNAVIGATIONCORE_ICC +#define TRIGNAVIGATION_HLTNAVIGATIONCORE_ICC + +#include "TrigNavigation/Holder.h" +#include "TrigNavigation/Holder.icc" +#include "TrigNavigation/RoICacheHistory.h" + + + +#include <algorithm> +//#include <assert.h> +#include <boost/foreach.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/if.hpp> +#include <boost/utility/enable_if.hpp> + +#include <iostream> + +/***************************************************************************** + * + * COMPILE TYPE OBJECTS REGISTRATION + * + *****************************************************************************/ +#include <boost/type_traits.hpp> +#undef MLOG +#define MLOG(x) if (m_log->level()<=MSG::x) *m_log << MSG::x + + +///////////////////////////////////////////////////////////////////////////// +template<class T> +__attribute__((__used__)) +bool HLT::NavigationCore::getFeatures( const TriggerElement* te, + std::vector<const T*>& features, const std::string& label, + std::map<const T*, std::string>* /*labels*/) { + + + MLOG(DEBUG) << "getFeatures: of clid: " << ClassID_traits<T>::ID() << "(" << ClassID_traits<T>::typeName() << ")" + <<" to TE: " << te->getId() + << " label: \"" << label << "\"" << endreq; + + TriggerElement::FeatureVec features_access_helpers; + if ( getFeatureAccessors(te, ClassID_traits<T>::ID(), label, false, features_access_helpers, true, false ) == false ) { + return false; + } + + // type specific code + BOOST_FOREACH( const TriggerElement::FeatureAccessHelper& fea, features_access_helpers) { + TriggerElement::ObjectIndex objectIndex(fea.getIndex()); + HLTNavDetails::Holder<T>* holder = getHolder<T>(objectIndex.subTypeIndex()); + const T* obj(0); + if ( holder->get(obj, objectIndex) == false ) { + MLOG(WARNING) << "getFeatures: problems while getting objects #" << objectIndex + << " from the holder: " << *holder << endreq; + } else { + features.push_back(obj); + } + } + return true; +} + +///////////////////////////////////////////////////////////////////////////// +template<class T> +__attribute__((__used__)) +bool HLT::NavigationCore::getFeature( const TriggerElement* te, const T*& feature, const std::string& label, std::string& sourcelabel) { + + feature = 0; + MLOG(DEBUG) << "getFeature: of clid: " << ClassID_traits<T>::ID() << "(" << ClassID_traits<T>::typeName() << ")" + <<" to TE: " << te->getId() + << " label: \"" << label << "\"" << endreq; + + TriggerElement::FeatureVec features_access_helpers; + if ( getFeatureAccessors(te, ClassID_traits<T>::ID(), label, true, features_access_helpers, true, false, m_unspecifiedTE, sourcelabel ) == false ) { + return false; + } + // remove following after testing + if ( features_access_helpers.size() > 1 ) { + MLOG(WARNING) << "getFeature: logic error, got: " << features_access_helpers.size() << " features from: getFeatureAccessors" << endreq; + } + + + if ( features_access_helpers.empty() ) + return true; + + const TriggerElement::FeatureAccessHelper& fea = features_access_helpers.front(); + TriggerElement::ObjectIndex objectIndex(fea.getIndex()); + HLTNavDetails::Holder<T>* holder = getHolder<T>(objectIndex.subTypeIndex()); + + if ( holder->get(feature, objectIndex) == false ) { + MLOG(WARNING) << "getFeature: problems while getting objects #" << objectIndex + << " from the holder: " << *holder << endreq; + feature = 0; + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////// +template<class C, class T> +__attribute__((__used__)) +bool HLT::NavigationCore::getFeaturesLinks( const TriggerElement* te, ElementLinkVector<C>& links, const std::string& label) { + + MLOG(DEBUG) << "getFeaturesLinks: of clid: " << ClassID_traits<T>::ID() << "(" << ClassID_traits<T>::typeName() << ")" + << " to TE: " << te->getId() + << " label: \"" << label << "\"" << endreq; + + TriggerElement::FeatureVec features_access_helpers; + if ( getFeatureAccessors(te, ClassID_traits<T>::ID(), label, false, features_access_helpers, true, false ) == false ) { + return false; + } + + BOOST_FOREACH( const TriggerElement::FeatureAccessHelper& fea, features_access_helpers) { + TriggerElement::ObjectIndex objectIndex(fea.getIndex()); + HLTNavDetails::Holder<T>* holder = getHolder<T>(objectIndex.subTypeIndex()); + + if ( holder->get(links, objectIndex) == false ) { + MLOG(WARNING) << "getFeaturesLinks: problems while getting objects #" << objectIndex + << " from the holder: " << *holder << endreq; + } + } + return true; +} + + +///////////////////////////////////////////////////////////////////////////// +template<class T> +__attribute__((__used__)) +bool HLT::NavigationCore::getRecentFeatures( const TriggerElement* te, + std::vector<const T*>& features, const std::string& label, + std::map<const T*, std::string>* /*labels*/) { + + // start from itself + MLOG(DEBUG) << "getRecentFeatures: looking for CLID: " << ClassID_traits<T>::ID() << "(" << ClassID_traits<T>::typeName() << ")" + << " in TE: " << te->getId() + << " label: \"" << label << "\"" << endreq; + + TriggerElement::FeatureVec features_access_helpers; + if ( getFeatureAccessors(te, ClassID_traits<T>::ID(), label, false, features_access_helpers, true, true ) == false ) { + return false; + } + + // type specific code + BOOST_FOREACH( const TriggerElement::FeatureAccessHelper& fea, features_access_helpers) { + TriggerElement::ObjectIndex objectIndex(fea.getIndex()); + HLTNavDetails::Holder<T>* holder = getHolder<T>(objectIndex.subTypeIndex()); + const T* obj(0); + if ( holder->get(obj, objectIndex) == false ) { + MLOG(WARNING) << "getRecentFeatures: problems while getting objects #" << objectIndex + << " from the holder: " << *holder << endreq; + } else { + features.push_back(obj); + } + } + return true; +} + +///////////////////////////////////////////////////////////////////////////// +template<class T> +__attribute__((__used__)) +bool HLT::NavigationCore::getRecentFeature( const TriggerElement* te, + const T*& feature, const std::string& label, + const TriggerElement*& source, std::string& sourcelabel ) { + + // important! set pointer to NULL to signify nothing was found, it will later be reset to sth else eventually + feature = 0; + + MLOG(DEBUG) << "getRecentFeature: looking for CLID: " << ClassID_traits<T>::ID() << "(" << ClassID_traits<T>::typeName() << ")" + << " in TE: " << te->getId() + << " label: \"" << label << "\"" << endreq; + + TriggerElement::FeatureVec features_access_helpers; + if ( getFeatureAccessors(te, ClassID_traits<T>::ID(), label, true, features_access_helpers, true, true, source, sourcelabel ) == false ) { + return false; + } + // remove following after testing + if ( features_access_helpers.size() > 1 ) { + MLOG(WARNING) << "getRecentFeature: logic error, got: " << features_access_helpers.size() << " features from: getRecentFeaturesImpl" << endreq; + } + + if ( features_access_helpers.empty() ) + return true; + + const TriggerElement::FeatureAccessHelper& fea = features_access_helpers.front(); + TriggerElement::ObjectIndex objectIndex(fea.getIndex()); + HLTNavDetails::Holder<T>* holder = getHolder<T>(objectIndex.subTypeIndex()); + + if ( holder->get(feature, objectIndex) == false ) { + MLOG(WARNING) << "getRecentFeature: problems while getting objects #" << objectIndex + << " from the holder: " << *holder << endreq; + feature = 0; + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////// +template<class C, class T> +__attribute__((__used__)) +bool HLT::NavigationCore::getRecentFeaturesLinks( const TriggerElement* te, + ElementLinkVector<C>& links, const std::string& label ) { + + MLOG(DEBUG) << "getRecentFeaturesLinks: looking for CLID: " << ClassID_traits<T>::ID() << "(" << ClassID_traits<T>::typeName() << ")" + << " in TE: " << te->getId() + << " label: \"" << label << "\"" << endreq; + + + TriggerElement::FeatureVec features_access_helpers; + if ( getFeatureAccessors(te, ClassID_traits<T>::ID(), label, false, features_access_helpers, true, true ) == false ) { + return false; + } + + BOOST_FOREACH( const TriggerElement::FeatureAccessHelper& fea, features_access_helpers) { + TriggerElement::ObjectIndex objectIndex(fea.getIndex()); + HLTNavDetails::Holder<T>* holder = getHolder<T>(objectIndex.subTypeIndex()); + + if ( holder->get(links, objectIndex) == false ) { + MLOG(WARNING) << "getRecentFeaturesLinks: problems while getting objects #" << objectIndex + << " from the holder: " << *holder << endreq; + } + } + return true; +} + +//helper struct to get the container type if template argument is datalink or the element type if template arg is ElementLink + +template<class LinkType> +struct link_to_type; + +template<class CONTAINERTYPE> +struct link_to_type<DataLink<CONTAINERTYPE> >{ + typedef CONTAINERTYPE container_type; + typedef typename DataLink<CONTAINERTYPE>::value_type type; +}; + +template<class CONTAINERTYPE> +struct link_to_type<ElementLink<CONTAINERTYPE> >{ + typedef CONTAINERTYPE container_type; + typedef typename ElementLink<CONTAINERTYPE>::ElementType ptr2constT_type; // is a const T* if T is the feature type + typedef typename boost::remove_pointer<ptr2constT_type>::type constT_type; // is a const T + typedef typename boost::remove_const<constT_type>::type type; // is a T +}; + + +///////////////////////////////////////////////////////////////////////////// +template<class LinkType> +__attribute__((__used__)) +bool HLT::NavigationCore::getRecentFeatureDataOrElementLink( const TriggerElement* te, LinkType& link, const std::string& label, + const TriggerElement*& source, std::string& sourcelabel) { + + typedef typename link_to_type<LinkType>::type T; + MLOG(DEBUG) << "getRecentFeatureDataOrElementLink: looking for CLID: " << ClassID_traits<T>::ID() << "(" << ClassID_traits<T>::typeName() << ")" + << " in TE: " << te->getId() + << " label: \"" << label << "\"" << endreq; + + TriggerElement::FeatureVec features_access_helpers; + if ( getFeatureAccessors(te, ClassID_traits<T>::ID(), label, true, features_access_helpers, true, true, source, sourcelabel ) == false ) { + MLOG(WARNING) << "looking for FAs failed. Returning false! Details CLID: " << ClassID_traits<T>::ID() << "(" << ClassID_traits<T>::typeName() << ")" + << " in TE: " << te->getId() + << " label: \"" << label << "\"" << endreq; + return false; + } + // remove following after testing + if ( features_access_helpers.size() > 1 ) { + MLOG(WARNING) << "getRecentFeature: logic error, got: " << features_access_helpers.size() << " features from: getRecentFeaturesImpl" << endreq; + } + + if ( features_access_helpers.empty() ) + return true; + + const TriggerElement::FeatureAccessHelper& fea = features_access_helpers.front(); + TriggerElement::ObjectIndex objectIndex(fea.getIndex()); + HLTNavDetails::Holder<T>* holder = getHolder<T>(objectIndex.subTypeIndex()); + + //apparently must use function pointer to get all the types resolved properly + typedef typename link_to_type<LinkType>::container_type containertype; + bool (HLTNavDetails::Holder<T>::*funcptr) (LinkType&, HLT::TriggerElement::ObjectIndex&) = + &HLTNavDetails::Holder<T>::template getWithLink<containertype>; + + if ( (holder->*funcptr)(link, objectIndex) == false ) { + MLOG(WARNING) << "getRecentFeatureLink: problems while getting objects #" << objectIndex + << " from the holder: " << *holder << endreq; + } + return true; +} + +///////////////////////////////////////////////////////////////////////////// +template<class C, class T> +__attribute__((__used__)) +bool HLT::NavigationCore::getRecentFeatureLink( const TriggerElement* te, + ElementLink<C>& link, const std::string& label, + const TriggerElement*& source, + std::string& sourcelabel) { + + MLOG(DEBUG) << "getRecentFeatureLink: looking for CLID: " << ClassID_traits<T>::ID() << "(" << ClassID_traits<T>::typeName() << ")" + << " in TE: " << te->getId() + << " label: \"" << label << "\"" << endreq; + + if( boost::is_same<C, T>::value ) + return false; + + + TriggerElement::FeatureVec features_access_helpers; + if ( getFeatureAccessors(te, ClassID_traits<T>::ID(), label, true, features_access_helpers, true, true, source, sourcelabel ) == false ) { + return false; + } + // remove following after testing + if ( features_access_helpers.size() > 1 ) { + MLOG(WARNING) << "getRecentFeature: logic error, got: " << features_access_helpers.size() << " features from: getRecentFeaturesImpl" << endreq; + } + + if ( features_access_helpers.empty() ) + return true; + + const TriggerElement::FeatureAccessHelper& fea = features_access_helpers.front(); + TriggerElement::ObjectIndex objectIndex(fea.getIndex()); + HLTNavDetails::Holder<T>* holder = getHolder<T>(objectIndex.subTypeIndex()); + + ElementLinkVector<C> links; + if ( holder->get(links, objectIndex) == false ) { + MLOG(WARNING) << "getRecentFeatureLink: problems while getting objects #" << objectIndex + << " from the holder: " << *holder << endreq; + } else { + if ( links.size() != 1 ) { + MLOG(WARNING) << "getRecentFeatureLink: problems while getting objects #" << objectIndex + << " from the holder: " << *holder << " links vector has size " << links.size() << " while shoudl have size == 1" << endreq; + return false; + } else { + link = links.back(); + } + } + return true; +} + + +///////////////////////////////////////////////////////////////////////////// +template<class T> +__attribute__((__used__)) +bool HLT::NavigationCore::getFeaturesInRoI( const TriggerElement* te, + std::vector<const T*>& features, const std::string& label, + std::map<const T*, std::string>* labels) { + // easy, jump to the RoI (if not RoI node) and loop over all TEs attached to it + const TriggerElement* roi(0); + if ( TrigNavStructure::isRoINode(te) ) + roi = te; + else if ( te->getRelated(TriggerElement::sameRoIRelation).size() == 1 ) // means we do not support topological TEs here + roi = *(te->getRelated(TriggerElement::sameRoIRelation).begin()); + else + return false; + + bool oneRetStatus = false; + bool allRetStatus = false; + std::vector<TriggerElement*>::const_iterator it; + for ( it = roi->getRelated(TriggerElement::sameRoIRelation).begin(); + it != roi->getRelated(TriggerElement::sameRoIRelation).end(); ++it ) { + oneRetStatus = getFeatures(*it, features, label, labels ); // the features will be paked to the end of the vector (see push_back in getFeatures) + allRetStatus = allRetStatus || oneRetStatus; // that's OK if at least one call returns some feature + } + return allRetStatus; +} + +///////////////////////////////////////////////////////////////////////////// +template<class C, class T> +__attribute__((__used__)) +bool HLT::NavigationCore::getAllFeatures( ElementLinkVector<C>& features, const std::string& label ) { + CLID clid = ClassID_traits<T>::ID(); + MLOG(DEBUG) << "getAllFeatures: of clid: " << clid << "(" << ClassID_traits<T>::typeName() << ")" + << " label: \"" << label << "\"" << endreq; + + FeaturesStructureLabelIndexed::const_iterator fit = m_featuresByLabel.find(clid); + if (fit == m_featuresByLabel.end() ) + return true; + + const std::map<std::string, HLTNavDetails::IHolder*>& allOfThisType = fit->second; + std::map<std::string, HLTNavDetails::IHolder*>::const_iterator hit; + for ( hit = allOfThisType.begin(); hit != allOfThisType.end(); ++hit ) { + if ( label == hit->first || label == "" ) { + HLTNavDetails::Holder<T>* holder = getHolder<T>(hit->second->label(), nextSubTypeIndex(clid, label)); + MLOG(VERBOSE) << "getAllFeatures: getting from: " << *holder << endreq; + if ( holder->get(features) == false ) { + MLOG(WARNING) << "getAllFeatures: failed with the holder: " << *(hit->second) << endreq; + return false; + } + } + } + return true; +} + + +///////////////////////////////////////////////////////////////////////////// +template<class T> +__attribute__((__used__)) +HLTNavDetails::Holder<T>* HLT::NavigationCore::getHolder(const std::string& label, uint16_t suggestedIndex) { + + // find object + CLID clid = ClassID_traits<T>::ID(); + MLOG(DEBUG) << "Getting holder for type: " << clid << " label: " << label << endreq; + + HLTNavDetails::Holder<T>* holder = static_cast<HLTNavDetails::Holder<T>* >(getHolder(clid, label)); + + if ( holder ) { + return holder; + } + + // take an appropriate action if this is the first feature of that type#label to be attached/retrieved + HLTNavDetails::IHolder* baseholder; + if ( createHolder(baseholder, clid, label, suggestedIndex) ) { // create fresh holder + MLOG(DEBUG) << "getHolder: predefined holder got" << endreq; + + } else { + MLOG(ERROR) << "getHolder: predefined holder does not exist, load EDM classes for: " + << ClassID_traits<T>::typeName() << " CLID " << ClassID_traits<T>::ID() << endreq; + return 0; + } + holder = static_cast<HLTNavDetails::Holder<T>*>(baseholder); + registerHolder(holder); + + return holder; +} + +///////////////////////////////////////////////////////////////////////////// +template<class T> +__attribute__((__used__)) +HLTNavDetails::Holder<T>* HLT::NavigationCore::getHolder(uint16_t subTypeIndex ) { + // find object + CLID clid = ClassID_traits<T>::ID(); + MLOG(DEBUG) << "Getting holder for type: " << clid << endreq; + HLTNavDetails::Holder<T>* holder = static_cast<HLTNavDetails::Holder<T>* >(getHolder(clid, subTypeIndex)); + + return holder; +} + +///////////////////////////////////////////////////////////////////////////// +// 2012-09-14 new stuff for composite obejcts + +//#include "TrigNavigation/TypeInformation.h" + + +#include "TrigNavigation/NavigationInit.h" + +/* +template<class T> +const T* HLT::NavigationCore::featureLink2ObjectByObject( const TrigFeatureLink& fl) { + + HLTNavDetails::Holder<Feature>* holder = getHolder<Feature>(fl.subTypeIndex()); + const T* ptr(0); + holder->get(ptr, TriggerElement::ObjectIndex(fl.subTypeIndex(), fl.index(), fl.index()+1)); + return ptr; +} + +template<class T> +const T* HLT::NavigationCore::featureLink2ObjectByContainer( const TrigFeatureLink& fl) { + + HLTNavDetails::Holder<Feature>* holder = getHolder<Feature>(fl.subTypeIndex()); + const T* ptr(0); + holder->get(ptr, TriggerElement::ObjectIndex(fl.subTypeIndex(), fl.index(), fl.index()+1)); + return ptr; +} +*/ + +#include <stdlib.h> +#include <cxxabi.h> + +namespace HLT{ + /* + struct tool{ + static std::string rtti_real_name(const char* name) + { + int status; + char *realname = abi::__cxa_demangle(name, 0, 0, &status); + std::string n(realname); + free(realname); + + return n; + } + }; + */ + + template<class T, class C, bool get_by_contianer, bool get_by_object> + struct get{}; + + template<class T, class C> + struct get< T, C, false, false>{ + static const T* do_it(const TrigFeatureLink&, HLT::NavigationCore* ){ + return 0; // here compile time error shoudl be generated + } + }; + + template<class T, class C> + struct get< T, C, false, true>{ + static const T* do_it(const TrigFeatureLink&fl, HLT::NavigationCore* nav){ + HLTNavDetails::Holder<T>* holder = nav->getHolder<T>(fl.subTypeIndex()); + //std::cerr << " Holder acquired " << __LINE__ << std::endl; + const T* ptr(0); + holder->get(ptr, HLT::TriggerElement::ObjectIndex(fl.subTypeIndex(), fl.index(), fl.index()+1)); + // std::cerr << " object retrieved " << __LINE__ << std::endl; + return ptr; + } + + }; + + template<class T, class C> + struct get< T, C, true, false>{ + static const T* do_it(const TrigFeatureLink&fl, HLT::NavigationCore* nav){ + HLTNavDetails::Holder<C>* holder = nav->getHolder<C>(fl.subTypeIndex()); + //std::cerr << " Holder acquired " << __LINE__ << " " << fl.clid() << " " << fl.subTypeIndex() << " " << holder << " " << ClassID_traits<C>::ID() << std::endl; + const C* ptr(0); + holder->get(ptr, HLT::TriggerElement::ObjectIndex(fl.subTypeIndex(), fl.index(), fl.index()+1)); + //std::cerr << " object retrieved " << __LINE__ << std::endl; + if ( ptr and ptr->size() == 1) { + return ptr->at(0); + } + return 0; + } + }; + + + template<class T, class C> + struct get< T, C, true, true> { + static const T* do_it(const TrigFeatureLink&fl, HLT::NavigationCore* nav){ + if ( fl.clid() == ClassID_traits<C>::ID() ) { + return get<T,C, true, false>::do_it(fl, nav); + } else if ( fl.clid() == ClassID_traits<T>::ID() ) { + return get<T,C, false, true>::do_it(fl, nav); + } + return 0; + } + }; +} + +template<class T> +__attribute__((__used__)) +const T* HLT::NavigationCore::featureLink2Object( const TrigFeatureLink& fl) { + if (! fl.isValid()) + return (const T*)0; + + typedef typename Object2Features<T>::type list_of_possible_features; + typedef typename Object2Container<T>::type container; + + // std::cerr << " in the list " << HLT::tool::rtti_real_name(typeid(list_of_possible_features).name()) << std::endl; + // std::cerr << " container " << HLT::tool::rtti_real_name(typeid(container).name()) << std::endl; + // std::cerr << " has T " << list_of_possible_features::template has<T>::result << std::endl; + // std::cerr << " has container " << list_of_possible_features::template has<container>::result << std::endl; + + const T* ptr = HLT::get<T, container, + list_of_possible_features::template has<container>::result, + list_of_possible_features::template has<T>::result>::do_it(fl, this); + + return ptr; + +} + +//not sure why i need to redef the macro here +#define MLOG(x) if (m_log->level()<=MSG::x) *m_log << MSG::x + +template<class T> +__attribute__((__used__)) +TrigFeatureLink HLT::NavigationCore::object2FeatureLink(const TriggerElement* te, const std::string& label, + const T* obj) { + + typedef typename Features2Container<T>::type Container; + if ( obj == 0 ) + return TrigFeatureLink(); + TriggerElement::FeatureVec features_access_helpers; + std::string sourcelabel; + if ( getFeatureAccessors(te, ClassID_traits<T>::ID(), label, true, features_access_helpers, false, true, m_unspecifiedTE, sourcelabel ) == false ) { + return TrigFeatureLink(); + } + + // remove following after testing + if ( features_access_helpers.size() > 1 ) { + MLOG(WARNING) << "getFeature: logic error, got: " << features_access_helpers.size() << " features from: getFeatureAccessors" << endreq; + } + + if ( features_access_helpers.empty() ) + return TrigFeatureLink(); + + const TriggerElement::ObjectIndex& oindex = features_access_helpers.at(0).getIndex(); + return TrigFeatureLink(ClassID_traits<T>::ID(), oindex.subTypeIndex(), oindex.objectsBegin()); + +} + +template<class C> +__attribute__((__used__)) +TrigFeatureLink HLT::NavigationCore::object2FeatureLink(const TriggerElement* te, const std::string& label, + const typename Container2Object<C>::type* obj, + const C* container) { + + TriggerElement::FeatureVec features_access_helpers; + std::string sourcelabel; + if ( getFeatureAccessors(te, ClassID_traits<C>::ID(), label, true, features_access_helpers, false, true, m_unspecifiedTE, sourcelabel ) == false ) { + return TrigFeatureLink(); + } + // remove following after testing + if ( features_access_helpers.size() > 1 ) { + MLOG(WARNING) << "getFeature: logic error, got: " << features_access_helpers.size() << " features from: getFeatureAccessors" << endreq; + } + + if ( features_access_helpers.empty() ) + return TrigFeatureLink(); + + const TriggerElement::ObjectIndex& oindex = features_access_helpers.at(0).getIndex(); + typename C::const_iterator lookup = std::find(container->begin(), container->end(),obj); + if ( lookup == container->end() ) + return TrigFeatureLink(); + + const unsigned offset = lookup - container->begin(); + return TrigFeatureLink(ClassID_traits<C>::ID(), oindex.subTypeIndex(), oindex.objectsBegin()+offset); + +} + + + + +#undef MLOG + +//EOF +#endif // #ifndef TRIGNAVIGATION_HLTNAVIGATIONCORE_ICC diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/NavigationInit.h b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/NavigationInit.h new file mode 100644 index 0000000000000000000000000000000000000000..68af06d424928c692d58cb07516aab0687196693 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/NavigationInit.h @@ -0,0 +1,60 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TrigNavigation_NavigationInit_h +#define TrigNavigation_NavigationInit_h + + /** + * @brief Classes used to provide static Trigger EDM list + * + * This code is from Scott Snyder + */ +//#include "TrigNavigation/NavigationCore.h" + + +#include <boost/function_types/function_type.hpp> +#include <boost/function_types/parameter_types.hpp> +#include <boost/function_types/function_arity.hpp> +#include <boost/typeof/std/utility.hpp> +#include <boost/type_traits/remove_pointer.hpp> +#include "DataModel/ElementLink.h" +#include "DataModel/DataLink.h" + +#include "TrigNavigation/NavigationTraits.h" +#include "TrigStorageDefinitions/EDM_TypeInfoMethods.h" + +namespace HLT{ + template <class FEATURE, class CONTAINER > + struct FeatureContainerInit { + FeatureContainerInit(); + void null(){;} + }; + + template <class FEATURE, class CONTAINER > + struct RegisterFeatureContainerTypes { + static void instan(){s.null();} + static FeatureContainerInit<FEATURE, CONTAINER> s; + }; + template <class FEATURE, class CONTAINER> FeatureContainerInit<FEATURE, CONTAINER> RegisterFeatureContainerTypes<FEATURE, CONTAINER>::s; + + + template <class TYPE > + struct AuxInit { + AuxInit(); + void null(){;} + }; + + template <class TYPE > + struct RegisterAuxType { + static void instan(){s.null();} + static AuxInit<TYPE> s; + }; + template <class TYPE> AuxInit<TYPE> RegisterAuxType<TYPE>::s; +} + + + +#include "TrigNavigation/NavigationInit.icc" + +#endif diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/NavigationInit.icc b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/NavigationInit.icc new file mode 100644 index 0000000000000000000000000000000000000000..3098ab18ff88dfede9c787ad03d8066328bc9225 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/NavigationInit.icc @@ -0,0 +1,274 @@ +// dear emacs this is -*- c++ -*- + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +#ifndef TrigNavigation_NavigationInit_icc +#define TrigNavigation_NavigationInit_icc + +//#include "GaudiKernel/MsgStream.h" +#include <boost/type_traits/is_same.hpp> + +#include "DataModel/ConstDataVector.h" +#include "TrigNavigation/Holder.h" +#include "TrigNavigation/Holder.icc" + +#include "TrigNavigation/Navigation.h" +#include "TrigNavigation/Navigation.icc" + +#include "TrigNavigation/NavigationCore.h" +#include "TrigNavigation/NavigationCore.icc" + +#include "TrigNavigation/TypeMaps.h" + + +//#include "TrigNavigation/AccessProxy.h" + +#include "TrigNavigation/TrigFeatureLink.h" +#include "TrigNavigation/NavigationTraits.h" + +namespace HLT { + class TriggerElement; +} + +template<class T> +struct FeatureLinkMethods { + typedef const T* (HLT::NavigationCore::*fl2o)( const TrigFeatureLink& ); + typedef TrigFeatureLink (HLT::NavigationCore::*o2fl_1)(const HLT::TriggerElement*, const std::string&, const T*); +}; + +template<class T> +struct FeatureLinkMethods2 { + typedef typename Container2Object<T>::type Contained; + typedef TrigFeatureLink (HLT::NavigationCore::*o2fl_2)(const HLT::TriggerElement*, const std::string&, const Contained*, const T* ); +}; + + + + ///////////////////////////////////////////////////// +template<class T, bool> struct acquire_featureLinkToObject; +template<class T> +struct acquire_featureLinkToObject<T, false> { + // typename FF<T>::type; + static typename FeatureLinkMethods<T>::fl2o do_it() { + return &HLT::NavigationCore::featureLink2Object<T>;} +}; + +template<class T> struct acquire_featureLinkToObject<T, true>{ + static typename FeatureLinkMethods<T>::fl2o do_it() { + return 0;} +}; + + ///////////////////////////////////////////////////// +template<class T, bool FeatureIsContainer> struct acquire_getRecentFeatureConstDV; +template<class T> +struct acquire_getRecentFeatureConstDV<T, true> { + typedef bool (HLT::NavigationCore::*type)( const HLT::TriggerElement*, + const ConstDataVector<T>*&, const std::string&, + const HLT::TriggerElement*&, std::string& ); + static type do_it() { return &HLT::NavigationCore::getRecentFeature<ConstDataVector<T>>; } +}; + +template<class T> +struct acquire_getRecentFeatureConstDV<T, false> { + typedef void* type; + static type do_it() { return 0; } + +}; + ///////////////////////////////////////////////////// + +template<class T, bool FeatureIsContainer> struct acquire_attachFeatureConstDV; +template<class T> +struct acquire_attachFeatureConstDV<T, true> { + typedef bool (HLT::Navigation::*type)( HLT::TriggerElement*, const ConstDataVector<T>*, + HLT::Navigation::MemoryManagement, std::string&, const std::string& ); + + static type do_it() { return &HLT::Navigation::attachFeature<ConstDataVector<T>>; } +}; + +template<class T> +struct acquire_attachFeatureConstDV<T, false> { + typedef void* type; + static type do_it() { return 0; } + +}; + + + + +//template<class T> +//struct O2FLMethod_1 { +// typedef TrigFeatureLink (HLT::NavigationCore::*o2fl_1)(const HLT::TriggerElement*, const std::string&, const T*); +//}; + +template<class T, bool> struct acquire_object2FeatureLink1; +template<class T> struct acquire_object2FeatureLink1<T, true> { + static typename FeatureLinkMethods<T>::o2fl_1 do_it() { + return &HLT::NavigationCore::object2FeatureLink<T>; + } +}; +template<class T> struct acquire_object2FeatureLink1<T, false> { + static typename FeatureLinkMethods<T>::o2fl_1 do_it() { + return 0; + } +}; + +// +template<class T, bool> struct acquire_object2FeatureLink2; +template<class T> struct acquire_object2FeatureLink2<T, false> { + static typename FeatureLinkMethods2<T>::o2fl_2 do_it() { + return &HLT::NavigationCore::object2FeatureLink<T>; + } +}; +template<class T> struct acquire_object2FeatureLink2<T, true> { + static typename FeatureLinkMethods2<T>::o2fl_2 do_it() { + return 0; + } +}; + +template<typename C, bool> +struct instantiate_dataelementlink; + +template<typename C> +struct instantiate_dataelementlink<C,true>{ + static void do_it(){ + __attribute__((__unused__)) + bool (HLT::NavigationCore::*temp)(const HLT::TriggerElement*,DataLink<C>& link, + const std::string&, const HLT::TriggerElement*&, std::string&); + temp = &HLT::NavigationCore::getRecentFeatureDataOrElementLink<DataLink<C> >; + //std::cout << "DataLink version instantiated for " << ClassID_traits<C>::ID() << std::endl; + } +}; + +template<typename C> +struct instantiate_dataelementlink<C,false>{ + static void do_it(){ + __attribute__((__unused__)) + bool (HLT::NavigationCore::*temp)(const HLT::TriggerElement*,ElementLink<C>& link, + const std::string&, const HLT::TriggerElement*&, std::string&); + temp = &HLT::NavigationCore::getRecentFeatureDataOrElementLink<ElementLink<C> >; + //std::cout << "ElementLink version instantiated for " << ClassID_traits<C>::typeName() << std::endl; + } +}; + +template <class T, class C> +HLT::FeatureContainerInit<T, C>::FeatureContainerInit() { + HLT::TypeMaps::registerFeatureContainer<T, C>(); + + // staements below force generation of the specializations for the methods + __attribute__((__unused__)) + bool (HLT::Navigation::*temp_attachFeature)( TriggerElement*, const T*, + Navigation::MemoryManagement, std::string&, const std::string& ); + temp_attachFeature = &HLT::Navigation::attachFeature<T>; + + + __attribute__((__unused__)) + typename acquire_attachFeatureConstDV<T, boost::is_same<T,C>::value>::type temp_attachFeatureConstDV; + temp_attachFeatureConstDV = acquire_attachFeatureConstDV<T, boost::is_same<T,C>::value>::do_it(); + + // typename acquire_getRecentFeatureConstDV<T, boost::is_same<T,C>::value>::type temp_getRecentFeatureConstDV; + // temp_getRecentFeatureConstDV = acquire_getRecentFeatureConstDV<T, boost::is_same<T,C>::value>::do_it(); + + + // + __attribute__((__unused__)) + bool (HLT::NavigationCore::*temp_getFeatures)( const TriggerElement*, std::vector< const T*>&, + const std::string&, std::map<const T*, std::string>* ); + temp_getFeatures = &HLT::NavigationCore::getFeatures<T>; + + + // + __attribute__((__unused__)) + bool (HLT::NavigationCore::*temp_getFeature)( const TriggerElement*, const T*&, const std::string&, std::string&); + temp_getFeature = &HLT::NavigationCore::getFeature<T>; + + + //const T* (HLT::NavigationCore::*temp_featureLink2Object)( const TrigFeatureLink& ); + __attribute__((__unused__)) + typename FeatureLinkMethods<T>::fl2o temp_featureLink2Object; + temp_featureLink2Object = acquire_featureLinkToObject<T, boost::is_same<T, C>::value>::do_it();//&HLT::NavigationCore::featureLink2Object<T>; + + // + __attribute__((__unused__)) + typename FeatureLinkMethods<T>::o2fl_1 temp_object2FeatureLink; + temp_object2FeatureLink = acquire_object2FeatureLink1<T, boost::is_same<T, C>::value>::do_it(); + + // + __attribute__((__unused__)) + typename FeatureLinkMethods2<C>::o2fl_2 temp_object2FeatureLink2; + temp_object2FeatureLink2 = acquire_object2FeatureLink2<C, boost::is_same<T, C>::value>::do_it(); + + // + __attribute__((__unused__)) + bool (HLT::NavigationCore::*temp_getRecentFeatures)( const TriggerElement*, + std::vector< const T*>&, const std::string&, + std::map<const T*, std::string>* ); + temp_getRecentFeatures = &HLT::NavigationCore::getRecentFeatures<T>; + + // + __attribute__((__unused__)) + bool (HLT::NavigationCore::*temp_getRecentFeature)( const TriggerElement*, + const T*&, const std::string&, const TriggerElement*&, std::string& ); + temp_getRecentFeature = &HLT::NavigationCore::getRecentFeature<T>; + + + __attribute__((__unused__)) + typename acquire_getRecentFeatureConstDV<T, boost::is_same<T,C>::value and canTransfer<C>::value >::type temp_getRecentFeatureConstDV; + temp_getRecentFeatureConstDV = acquire_getRecentFeatureConstDV<T, boost::is_same<T,C>::value and canTransfer<C>::value>::do_it(); + + + // + __attribute__((__unused__)) + bool (HLT::NavigationCore::*temp_getRecentFeaturesLinks)( const TriggerElement*, + ElementLinkVector<C>&, const std::string& ); + temp_getRecentFeaturesLinks = &HLT::NavigationCore::getRecentFeaturesLinks<C,T>; + + + // + __attribute__((__unused__)) + bool (HLT::NavigationCore::*temp_getRecentFeatureLink)( const TriggerElement*, + ElementLink<C>&, const std::string&, const TriggerElement*&, std::string& ); + temp_getRecentFeatureLink = &HLT::NavigationCore::getRecentFeatureLink<C,T>; + + //getRecentFeatureDataOrElementLink depends on what kind of feature we have + //therefore we need to outsource to helper + instantiate_dataelementlink<C,boost::is_same<T,C>::value >::do_it(); + + // + __attribute__((__unused__)) + bool (HLT::NavigationCore::*temp_getFeaturesInRoI)( const TriggerElement*, std::vector<const T*>&, + const std::string&, std::map<const T*, std::string>* ); + temp_getFeaturesInRoI = &HLT::NavigationCore::getFeaturesInRoI<T>; + + // + __attribute__((__unused__)) + bool (HLT::NavigationCore::*temp_getAllFeatures)(ElementLinkVector<C>&, const std::string& ); + temp_getAllFeatures = &HLT::NavigationCore::getAllFeatures<C,T>; + + // + __attribute__((__unused__)) + bool (HLT::Navigation::*temp_findOwners)(const T*, std::vector<const TriggerElement*>&, unsigned int); + temp_findOwners = &HLT::Navigation::findOwners<T>; + + // + typedef const std::string const_string; + __attribute__((__unused__)) + const_string (HLT::Navigation::*temp_getNextKey)( const std::string& ); + temp_getNextKey = &HLT::Navigation::getNextKey<T>; + + + // + __attribute__((__unused__)) + const_string (HLT::Navigation::*temp_getUniqueKey)( const std::string&); + temp_getUniqueKey = &HLT::Navigation::getUniqueKey<T>; + +} + +template <class T> +HLT::AuxInit<T>::AuxInit() { + HLT::TypeMaps::registerType<T>(); +} + +#endif diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/NavigationTraits.h b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/NavigationTraits.h new file mode 100644 index 0000000000000000000000000000000000000000..427c690b1d29e3c356a1f1849401ffb369da397a --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/NavigationTraits.h @@ -0,0 +1,17 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TrigNavigation_NavigationTraits_h +#define TrigNavigation_NavigationTraits_h + +// template <class T> struct Feature2Container; +// template <class T> struct Feature2Object; +// template <class T> struct Container2Object; +// template <class T> struct Object2Feature; +// template <class T> struct Object2Container; +// template <class T> struct Link2Object; + + + +#endif // TrigNavigation_NavigationTraits_h diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/RoICacheHelper.h b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/RoICacheHelper.h new file mode 100644 index 0000000000000000000000000000000000000000..97a20e0444e213869fb8b5f7627c0f9001d6d9f7 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/RoICacheHelper.h @@ -0,0 +1,155 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGNAVIGATION_ROICACHEHELPER_H +#define TRIGNAVIGATION_ROICACHEHELPER_H + +#include <iostream> +#include <vector> +#include <set> + +#include "TrigNavigation/RoICacheHistory.h" +#include "TrigNavigation/TriggerElement.h" + +namespace HLT { + /** + * \brief class to support in RoI caching + * If algo wants to profit from caching it should create private objects + * of HLT::TriggerElement::CacheHelper or inherit from it. + * + * Each time when the algo wants to run on TE given as an argument it should + * check if needsExecution() returns true. If so, then the algorithms needs to be executed. + * The execution needs to be wrapped by calls to start/stop caching + * startCaching(TE) + * ... algo execution + * stopCaching(TE) + * + * If false is returned then caching has heppened. Nothing else needs to be done. + * + * After event processing the cahce needs to be reset. + * + * + */ + + + class RoICacheHelper { + public: + + /** + * \brief adds objects from cache to this TE as if the algorithm would have run on this TE + * \param te is trigger element, non-const since eventually it will be updated from cache + * \return true if all worked correctly, false if failed, this should never ahppen, if it does it shoudl be severe error + */ + bool cache ( TriggerElement* te ); + + + + + /** + * \brief checks if there was an execution on RoI already + * \param te is trigger element + * \return true if running is needed, false if not + */ + bool needsExecution ( const TriggerElement* te ); + + + + /** + * \brief checks if there was an execution on RoI already + * \param te is trigger element + * \return true if running is needed, false if not + */ + bool isInputAccepted ( const TriggerElement* te ); + + + /** + * \brief starts collecting cache + * \param te the same te as for needsExecution + * \warning For optimization reasons this calls assume that is done only after needsExecution returned true. If that is not the case it will make mess. + * \return true if all went OK, false if there is logica failure, (this method can only be called after needsExecution(te) == true) + */ + bool startCaching( const TriggerElement* te ); + + /** + * \brief stop collecting cache + * \see startCaching(const TriggerElement*) + */ + bool stopCaching( const TriggerElement* te ); + + /** + * \brief reset caches for this event + */ + void reset(); + + enum CachingMode { None=0, RoIOnly=1, AllObjects=2, HistoryBased=3 }; + static enum CachingMode s_cachingMode; + + private: + /** + * \brief Helper class for caching. + * This class keeps cache for all RoIs. + * That means it remembers if the algo was run on this RoIs and whcih objects reated for the first time. + **/ + + class CacheEntry { + public: + + typedef std::vector<HLT::RoICacheHistory::FeatureCall> FeatureCallVec; + typedef HLT::RoICacheHistory::FeatureCall FeatureCall; + + typedef std::vector<HLT::TriggerElement::FeatureAccessHelper> FeatureVec; + typedef HLT::TriggerElement::FeatureAccessHelper Feature; + + bool operator== (const std::vector<TriggerElement*>& roite) const; + bool operator== (const TriggerElement* te) const; + + CacheEntry(const TriggerElement* cacheHolder ) + : m_rois(TrigNavStructure::getRoINodes(cacheHolder).begin(), TrigNavStructure::getRoINodes(cacheHolder).end()), + m_cacheHolder(cacheHolder), + m_begin(0), + m_end(0) { + } + + /* + CacheEntry(const std::vector<TriggerElement*>& rois, const TriggerElement* cacheHolder=0 ) + : m_rois(rois.begin(), rois.end()), + m_cacheHolder(cacheHolder), + m_begin(0), + m_end(0) { + + // std::cout << "setsize" << m_rois.size() << "\n"; + // std::set<const TriggerElement*>(m_rois.begin(), m_rois.end()); + // for ( std::set<const TriggerElement*>::const_iterator is = m_rois.begin(); is != m_rois.end(); ++is) + // std::cout << *is << " creset \n"; + } + */ + + + void start(unsigned int begin) { m_begin = m_end = begin; } //!< record moment just before execution when no feature was yet attached + void finish(unsigned int end) { m_end = end; } //!< record moment just after execution when no more featuresd are attached + + void add(const FeatureCallVec &qvec) { m_questions = qvec; } + + unsigned int begin() const { return m_begin; } //!< + unsigned int end() const { return m_end; } + + const TriggerElement* holder() { return m_cacheHolder; } + void holder(const TriggerElement* te) { m_cacheHolder = te; } + unsigned int size() const { return m_end - m_begin; } //!< gets number of objects attaced by algo + + private: + + std::set<const TriggerElement*> m_rois; //!< handy varaible to keep all RoIs of given TE + const TriggerElement* m_cacheHolder; //!< the first TE processed in given RoI (from it the objects will be copied to all cached TEs) + FeatureCallVec m_questions; + + unsigned int m_begin; + unsigned int m_end; + }; + + std::vector<struct CacheEntry> m_caches; //!< caches for all RoIs + }; +} + +#endif //#ifndef TRIGNAVIGATION_ROICACHEHELPER_H diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/RoICacheHistory.h b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/RoICacheHistory.h new file mode 100644 index 0000000000000000000000000000000000000000..e3f3a7497b9061cbd2bdd45f63b19ebb72aae3f3 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/RoICacheHistory.h @@ -0,0 +1,114 @@ +// -*- c++ -*- + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGNAVIGATION_ROICACHEHISTORY_H +#define TRIGNAVIGATION_ROICACHEHISTORY_H + +#include <vector> +#include <string> + +#include "CLIDSvc/CLASS_DEF.h" +#include "TrigNavigation/TriggerElement.h" + +namespace HLT { + + class NavigationCore; + + class RoICacheHistory { + public: + class FeatureCall { + public: + FeatureCall(const TriggerElement* work, + const TriggerElement* te, CLID clid, const std::string& label, + bool issingle, bool isget); + FeatureCall(); + + void addAnswer( const TriggerElement* te, const TriggerElement::FeatureAccessHelper&); + + const TriggerElement::FeatureVec& getAnswers() const { return m_answers; } + + + const TriggerElement* getInitTE() const { return m_init; } + const TriggerElement* getWorkTE() const { return m_work; } + + bool isValid() const; + void reset(); + const std::string& label() const { return m_label; } + CLID clid() const {return m_clid; } + bool issingle() const {return m_issingle; } + bool isget() const {return m_isget; } + + + private: + + const TriggerElement* m_init; // place where the first query starts from + const TriggerElement* m_work; // current TE on which algorithm is working + CLID m_clid; + std::string m_label; + TriggerElement::FeatureVec m_answers; + bool m_issingle; + bool m_isget; + }; + + + class QuestionScope { + public: + QuestionScope(const TriggerElement *te, CLID clid, const std::string& label, NavigationCore *navig, bool issingle=false); + QuestionScope(); + ~QuestionScope(); + private: + const TriggerElement *m_start; + }; + + class RememberAttachFeature { + public: + RememberAttachFeature(const TriggerElement* te, CLID clid, const std::string& label, + NavigationCore* navig, TriggerElement::ObjectIndex& idx); + }; + + + + static RoICacheHistory& instance(); + + + void startHistory(const TriggerElement* te) { m_collect = true; m_questions.clear(); m_work = te; } + void stopHistory() { m_collect = false; m_questions.clear(); } + + bool collectHistory() const { return m_collect; } + + void setCurrentFeatureCall(const FeatureCall &curr, NavigationCore *navig); + const FeatureCall& getCurrentFeatureCall() const { return m_current; } + + void addAnswer(const TriggerElement* te, const TriggerElement::FeatureAccessHelper&); + + + void stopCurrentFeatureCall(); + + NavigationCore* getNavigation() const { return m_navigation; } + const TriggerElement* getWorkTE() const { return m_work; } + const std::vector<FeatureCall>& getFeatureCalls() const { return m_questions; } + + private: + + RoICacheHistory() + : m_collect(false), m_navigation(0), m_work(0) {} + ~RoICacheHistory(){} + + RoICacheHistory(const RoICacheHistory&); + RoICacheHistory& operator=(const RoICacheHistory&); + + private: + + FeatureCall m_current; + std::vector<FeatureCall> m_questions; + bool m_collect; + + NavigationCore *m_navigation; + const TriggerElement *m_work; + }; +} + +#endif diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TrigEDMSizes.h b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TrigEDMSizes.h new file mode 100644 index 0000000000000000000000000000000000000000..ba6578b54f088f40ab37b86de3da7d667416e169 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TrigEDMSizes.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGNAVIGATION_TRIGEDMSIZES_H +#define TRIGNAVIGATION_TRIGEDMSIZES_H +#include <string> +#include <vector> +#include "GaudiKernel/ClassID.h" +#include "CLIDSvc/CLASS_DEF.h" +namespace HLT { + /** + * Class used to pass around information about the sizes of the EDM obejcts. + * + **/ + + class TrigEDMSizes { + public: + TrigEDMSizes(); + + struct EDMObjectInfo { + EDMObjectInfo(const std::string& c, const std::string& l, unsigned w, unsigned cut); + bool isTruncated(unsigned size_after_serialization) const; + std::string collection; + std::string label; + unsigned int words; + unsigned int cutsize; + }; + + typedef std::vector<EDMObjectInfo> EDMEventInfo; + const EDMEventInfo& info() const; + + void addObject(const std::string& c, const std::string& label, unsigned words, unsigned cutsize); + const EDMObjectInfo& lastNotTruncated(unsigned size_after_truncation) const; + + + private: + EDMEventInfo m_objects; + }; + + +} + +CLASS_DEF( HLT::TrigEDMSizes , 190211077 , 1 ) + +#endif diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TrigFeatureLink.h b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TrigFeatureLink.h new file mode 100644 index 0000000000000000000000000000000000000000..6b70b67dbe2e91ca68faf848f02a9fe9b1d11a59 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TrigFeatureLink.h @@ -0,0 +1,34 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TrigNavigation_TrigFeatureLink +#define TrigNavigation_TrigFeatureLink +#include <stdint.h> + +#include "GaudiKernel/ClassID.h" + + +class TrigFeatureLink { + + public: + TrigFeatureLink(CLID clid, uint16_t subtype, uint32_t index); + TrigFeatureLink(); + bool isValid() const { return m_clid != 0; } + + CLID clid() const { return m_clid; } + uint16_t subTypeIndex() const { return m_subTypeIndex; } + uint32_t index() const { return m_index; } + + private: + + CLID m_clid; + uint16_t m_subTypeIndex; + uint32_t m_index; +}; + +//TrigFeatureLink getFeatureLink( const TriggerElement* te, const std::string& label, const T* object, const C* container) +//const T* getFeature(TrigFeatureLink*) + + +#endif diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TrigNavigationDict.h b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TrigNavigationDict.h new file mode 100644 index 0000000000000000000000000000000000000000..e12a82f1ef812aa1b7eb1db07d6cff3d524005e6 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TrigNavigationDict.h @@ -0,0 +1,19 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +#include "GaudiKernel/IConversionSvc.h" +#include "TrigNavigation/NavigationCore.h" +#include "TrigNavigation/NavigationCore.icc" + +#include "TrigNavigation/TriggerElement.h" +#include "TrigNavigation/AccessProxy.h" +//#include "TrigNavigation/Holder.h" + +struct dummy { + std::vector<HLT::TriggerElement*> te_vec; + std::vector<const HLT::TriggerElement*> te_const_vec; + // HLT::NavigationCore nc; +}; + diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TriggerElement.h b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TriggerElement.h new file mode 100644 index 0000000000000000000000000000000000000000..1807040b49fe09ad074a2340d449c4b2a967d7cd --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TriggerElement.h @@ -0,0 +1,18 @@ +// -*- c++ -*- + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGNAVIGATION_TRIGGERELEMENT_H +#define TRIGNAVIGATION_TRIGGERELEMENT_H + + +#include "TrigNavStructure/TriggerElement.h" + +#include "GaudiKernel/MsgStream.h" + + +MsgStream& operator<< ( MsgStream& m, const HLT::TriggerElement& te ); +MsgStream& operator<< ( MsgStream& m, const HLT::TriggerElement::ObjectIndex& i ); +#endif //TRIGGERELEMENT_H diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TriggerElement.icc b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TriggerElement.icc new file mode 100644 index 0000000000000000000000000000000000000000..0264758a6542a6a139c7e4a914087c433b1cb3e7 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TriggerElement.icc @@ -0,0 +1,18 @@ +// Dear Emacs this is -*- c++ -*- + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * IMPROVEMENT TO BE DONE: + * find firs having the same CLID + * after that go ahead until different CLID and copy to objects + * that would be an optimization step + * for that the features should be inserted in stable manner + */ +/* + The features manegement was moved to Navigation.icc. No templated code in TriggerElement now. + Will delete this file as soon as the idea behind current development will get validated. +*/ +// EOF diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TypeMaps.h b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TypeMaps.h new file mode 100644 index 0000000000000000000000000000000000000000..39fcc756cb2b97d2436916e670c00e654a72aa27 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TypeMaps.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#pragma once +#include <map> +#include <string> + +#include "GaudiKernel/ClassID.h" + +#include "TrigNavigation/Holder.h" +#include "TrigNavigation/TypeProxy.h" + +namespace HLT { + class TypeMaps { + public: + typedef std::map<CLID, HLTNavDetails::ITypeProxy*> CLIDtoTypeProxyMap; + static CLIDtoTypeProxyMap& proxies(); + + typedef std::map<CLID, HLTNavDetails::IHolder*> CLIDtoHolderMap; + static CLIDtoHolderMap& holders(); + + typedef std::map<std::string, CLID> NametoCLIDMap; + static NametoCLIDMap& type2clid(); //!< translate class name to CLID + + template<class T> + static void registerType() { + HLT::TypeMaps::proxies()[ClassID_traits<T>::ID()] = new HLTNavDetails::TypeProxy<T>(); + HLT::TypeMaps::type2clid()[ ClassID_traits<T>::typeName() ] = ClassID_traits<T>::ID(); + } + + + template<class T, class C> + static void registerFeatureContainer() { + HLT::TypeMaps::holders()[ClassID_traits<T>::ID()] = new HLTNavDetails::HolderImp<T, C>(); + HLT::TypeMaps::registerType<T>(); + HLT::TypeMaps::registerType<C>(); + } + + }; +} diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TypeProxy.h b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TypeProxy.h new file mode 100644 index 0000000000000000000000000000000000000000..08adf27cd1ea3a9a6ceae5d697bb06d3f17d6f97 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TypeProxy.h @@ -0,0 +1,261 @@ +// Dear emacs, this is -*- c++ -*- + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: TypeProxy.h 610936 2014-08-08 14:17:56Z tbold $ +#ifndef TRIGNAVIGATION_TYPEPROXY_H +#define TRIGNAVIGATION_TYPEPROXY_H + +// Boost include(s): +#include <boost/type_traits/is_base_of.hpp> + +// Gaudi/Athena include(s): +#include "GaudiKernel/ClassID.h" +#include "GaudiKernel/StatusCode.h" +#include "SGTools/DataProxy.h" +#include "SGTools/ClassID_traits.h" +#include "StoreGate/StoreGateSvc.h" +#include "AthenaKernel/errorcheck.h" +#include "AthContainers/AuxVectorBase.h" + +// Forward declaration(s): +namespace SG { + class IAuxStore; +} + +namespace HLTNavDetails { + + /** + * @short Interface to the TypeProxy<...> objects created at runtime + * + * It's not really a pure interface, but to simplify the class + * structure, let's keep this naming... + * + * @author Tomasz Bold <Tomasz.Bold@cern.ch> + * @author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch> + * + * $Revision: 610936 $ + * $Date: 2014-08-08 16:17:56 +0200 (Fri, 08 Aug 2014) $ + */ + class ITypeProxy { + + public: + /// Default constructor + ITypeProxy(); + /// Virtual destructor, to make vtable happy... + virtual ~ITypeProxy() {} + + /// Make a new object + virtual StatusCode create() = 0; + /// Save proxied object in DG (record) + virtual StatusCode reg( StoreGateSvc* sg, const std::string& key ) = 0; + /// SG retrieve, and fill the proxy + virtual StatusCode sync( StoreGateSvc* sg, const std::string& key ); + /// Remove the object from SG and make the pointer null + virtual StatusCode clear( StoreGateSvc* sg ) = 0; + + /// @name Cast operations for xAOD decorations + /// Actual implementation rely in boost::is_base_of to avoid dynamic_cast + /// @{ + + /// Return a pointer to the SG::AuxVectorBase base class of the object if + /// possible + SG::AuxVectorBase* castAuxVectorBase(); + /// Return a pointer to the SG::IAuxStore base class of the object if + /// possible + SG::IAuxStore* castIAuxStore(); + + virtual void syncTypeless() = 0; + + /// @} + + /// Check whether StoreGate contains an object of this type and with + /// the specified key + bool contains( StoreGateSvc* sg, const std::string& key ) const; + + /// Check whether StoreGate contains a modifyable object of this type + /// and with the specified key + bool transientContains( StoreGateSvc* sg, const std::string& key ) const; + + /// True if proxy has not yet made object or not synced to any yet + /// (0 pointer) + bool empty() const; + + /// This is how typed proxy is obtained + virtual ITypeProxy* clone() const = 0; + + /// The CLID of the object being proxied + CLID clid() const; + + /// The type name of the object being proxied + const std::string& typeName() const; + + const void* cptr() const { return m_pointer; } + + protected: + CLID m_clid; ///< The CLID of the type being proxied + std::string m_typeName; ///< The type name of the object being proxied + std::string m_key; ///< StoreGate key of the proxied object + SG::DataProxy* m_proxy; ///< StoreGate proxy for the object + void* m_ncPointer; ///< Non-const pointer to the proxied object + const void* m_pointer; ///< Const pointer to the proxied object + /// Does the proxied type inherit from SG::AuxVectorBase? + bool m_isAuxVectorBase; + + }; // class ITypeProxy + + + /** + * @short Type specific implementation of ITypeProxy + * + * @author Tomasz Bold <Tomasz.Bold@cern.ch> + * @author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch> + * + * $Revision: 610936 $ + * $Date: 2014-08-08 16:17:56 +0200 (Fri, 08 Aug 2014) $ + */ + template< class T > + class TypeProxy : public ITypeProxy { + + public: + /// Convenience type declaration + typedef T value_type; + /// Convenience type declaration + typedef T* pointer_type; + + /// Default constructor + TypeProxy(); + /// Constructor pointing to an existing object + TypeProxy( pointer_type t ); + + /// Make a new object + virtual StatusCode create(); + /// Save proxied object in DG (record) + virtual StatusCode reg( StoreGateSvc* sg, const std::string& key ); + /// SG retrieve, and fill the proxy + virtual StatusCode sync( StoreGateSvc* sg, const std::string& key ); + /// Remove the object from SG and make the pointer null + virtual StatusCode clear( StoreGateSvc* sg ); + + virtual void syncTypeless(){ + m_ncPointer = m_data; + m_pointer = m_data; + } + + /// This is how typed proxy is obtained + virtual ITypeProxy* clone() const { return new TypeProxy<T>(); } + + /// Pointer to the exact object type + pointer_type data() { return m_data; } + /// Constant pointer to the exact object type + const pointer_type& data() const { return m_data; } + /// Reference to the exact object type pointer + pointer_type& data_ref() { return m_data; } + + private: + pointer_type m_data; ///< Non-const pointer to the proxied object + + }; // class TypeProxy + + /// Default constructor + template< class T > + TypeProxy< T >::TypeProxy() + : ITypeProxy(), m_data( 0 ) { + + // Set the properties of the base class: + m_clid = ClassID_traits< T >::ID(); + m_typeName = ClassID_traits< T >::typeName(); + m_isAuxVectorBase = boost::is_base_of< SG::AuxVectorBase, T >::value; + } + + /// Constructor pointing to an existing object + /// + /// Notice that this constructor delegates much of the work to the default + /// constructor. (C++11 magic...) + /// + template< class T > + TypeProxy< T >::TypeProxy( pointer_type t ) + : TypeProxy() { + + // Set the properties of this class: + m_data = t; + + // Set the properties of the base class: + m_ncPointer = m_data; + m_pointer = m_data; + } + + template< class T > + StatusCode TypeProxy< T >::create() { + + // Check if we already proxy some object. Then this should not be called + // again... + if( m_data ) { + REPORT_MESSAGE( MSG::ERROR ) + << "Object is already being proxied"; + return StatusCode::FAILURE; + } + + // Create the new object: + m_data = new T(); + + // Fill the base class's variables: + m_ncPointer = m_data; + m_pointer = m_data; + + // Return gracefully: + return StatusCode::SUCCESS; + } + + template< class T > + StatusCode TypeProxy< T >::reg( StoreGateSvc* sg, const std::string& key ) { + + // Record the object: + CHECK( sg->record( m_data, key ) ); + + // Fill some variables in the base class: + m_key = key; + m_proxy = sg->proxy( m_clid, m_key ); + + return StatusCode::SUCCESS; + } + + /** + * Unfortunately the typeless removeProxy functions of StoreGateSvc are all + * private. Although I would've loved to implement this function in a + * non-template way as well... :-/ + */ + template< class T > + StatusCode TypeProxy< T >::clear( StoreGateSvc* sg ) { + + // Do the deed: + CHECK( sg->remove( m_data ) ); + + // Clear the object: + m_data = 0; + m_proxy = 0; + m_ncPointer = 0; + m_pointer = 0; + + // Return gracefully: + return StatusCode::SUCCESS; + } + + template< class T > + StatusCode TypeProxy< T >::sync( StoreGateSvc* sg, const std::string& key ) { + + // First let the base class do its own thing: + CHECK( ITypeProxy::sync( sg, key ) ); + + // Get the object out of the proxy: + m_data = SG::DataProxy_cast< T >( m_proxy ); + + // Return gracefully: + return StatusCode::SUCCESS; + } + +} // namespace HLTNavDetails + +#endif // not TRIGNAVIGATION_TYPEPROXY_H diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TypeRegistration.h b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TypeRegistration.h new file mode 100644 index 0000000000000000000000000000000000000000..e77353418c43d97ce1efad13d01cf11122021ab9 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/TypeRegistration.h @@ -0,0 +1,80 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TrigNavigation/NavigationInit.h" +#include "TrigStorageDefinitions/EDM_TypeInfo.h" + +#include <iostream> + +template<typename CONTAINER> +struct register_feature{ + template<class FEATURE> + void do_it() const { + //std::cout << "\t\t registering feature: " << typeid(FEATURE).name() << " -> "; + //std::cout << "container: " << typeid(CONTAINER).name() << std::endl; + + HLT::RegisterFeatureContainerTypes<FEATURE,CONTAINER>::instan(); + } +}; + + +template<class AUX> +struct register_aux{ + static void do_it() { + HLT::RegisterAuxType<AUX>::instan(); + } +}; + + +template<> +struct register_aux<HLT::TypeInformation::no_aux>{ + static void do_it() {} +}; + + + + +struct registertype{ + template<class typeinfo_element> + void do_it() const { + typedef typename typeinfo_element::list_of_features FEATURES; + typedef typename typeinfo_element::container CONTAINER; + typedef typename typeinfo_element::aux AUX; + + //std::cout << "list of features for contaier " << typeid(CONTAINER).name() << " "; + //HLT::TypeInformation::for_each_type<FEATURES,HLT::TypeInformation::simple_printer >::do_it(); + //std::cout<< std::endl; + + HLT::TypeInformation::for_each_type<FEATURES,register_feature<CONTAINER> >::do_it(); + register_aux<AUX>::do_it(); + } +}; + +//we want to exectute a function upon loading of a library (i.e. 'static'). since this is not possible +//per se, we take a detour via a default constructor. we declare a class with a static data member +//and initizalize that static member. This will call the default ctor of this member type during +//which we can register all kinds of types to the navigation. This also uses the looping functionality +//of the typemap + + +template <typename TYPELIST> +struct a_default_ctor{ + a_default_ctor(){ + //std::cout << "registering package with navi, packae typelist has size: " << TYPELIST::last_index + 1 << std::endl; + //we need to do this by hand unfortunately because we hit the template instantiaton depth of 99 + HLT::TypeInformation::for_each_type<typename TYPELIST::template range< 0, 9>::type,registertype>::do_it(); + HLT::TypeInformation::for_each_type<typename TYPELIST::template range<10,19>::type,registertype>::do_it(); + HLT::TypeInformation::for_each_type<typename TYPELIST::template range<20,29>::type,registertype>::do_it(); + } +}; + +template <typename TYPELIST> +struct a_class_that_calls_default_ctor{ + static a_default_ctor<TYPELIST> member; +}; + +#define REGISTER_PACKAGE_WITH_NAVI(name)\ +template<> a_default_ctor<class_##name::map>\ +a_class_that_calls_default_ctor<class_##name::map>::member = \ +a_default_ctor<class_##name::map>(); diff --git a/Trigger/TrigEvent/TrigNavigation/TrigNavigation/selection.xml b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/selection.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e6f34cf4a10841cd030bc26ea0c8f077c62315 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/TrigNavigation/selection.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<lcgdict> +<!-- <class name="HLT::Navigation" /> --> + <!-- <class name="HLT::NavigationCore" /> --> + + <exclusion> + <class pattern="HLT::TypeInformation::*"/> + <class pattern="TypeInfo_*"> + <field name="*" /> + <method name="*"/> + </class> + </exclusion> + + <class name="HLT::TriggerElement"> + <field name="m_relations" transient="true"/> + </class> + <class name="std::vector<HLT::TriggerElement*>" /> + <class name="std::vector<const HLT::TriggerElement*>" /> + <!-- <exclusion> + <class name="HLT::TriggerElement"> + <method name="activeState"/> + <method name="addFeature"/> + <method pattern="*serialize"/> + <method name="getFeatureAccessHelpers"/> + <method name="getRelated"/> + <method name="inquireId"/> + <method name="nofwdState"/> + <method name="relate"/> + <method name="reset"/> + <method pattern="*Relation"/> + <method pattern="set*"/> + </class> + </exclusion> --> + <!-- <class name="HLT::FeatureDescriptor" /> + <class name="std::vector< HLT::FeatureDescriptor >" /> --> + + <class name="HLT::TriggerElement::FeatureAccessHelper" /> + +</lcgdict> diff --git a/Trigger/TrigEvent/TrigNavigation/cmt/requirements b/Trigger/TrigEvent/TrigNavigation/cmt/requirements new file mode 100644 index 0000000000000000000000000000000000000000..35a06248021d1aaf9ce796a21b5df910296dd883 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/cmt/requirements @@ -0,0 +1,58 @@ +package TrigNavigation +author Tomasz.Bold@cern.ch + +use AtlasPolicy AtlasPolicy-* + +use AtlasBoost AtlasBoost-* External +use AtlasROOT AtlasROOT-* External +use GaudiInterface GaudiInterface-* External +use CLIDSvc CLIDSvc-* Control +use StoreGate StoreGate-* Control +use SGTools SGTools-* Control +use DataModel DataModel-* Control +use AthContainers AthContainers-* Control +use AthenaKernel AthenaKernel-* Control +use AthenaBaseComps AthenaBaseComps-* Control +use TrigStorageDefinitions TrigStorageDefinitions-* Trigger/TrigEvent +use TrigNavStructure TrigNavStructure-* Trigger/TrigEvent + +private +use TrigSerializeResult TrigSerializeResult-* Trigger/TrigDataAccess +use AthContainersInterfaces AthContainersInterfaces-* Control + + +public +apply_pattern dual_use_library files=*.cxx +#library TrigNavigation *.cxx +#apply_pattern installed_library +#apply_pattern declare_non_standard_include name=doc +apply_pattern declare_python_modules files="*.py" + + +private +use TrigConfHLTData TrigConfHLTData-* Trigger/TrigConfiguration +use xAODCore xAODCore-* Event/xAOD # for tests only +use TrigSerializeCnvSvc TrigSerializeCnvSvc-* Trigger/TrigDataAccess +use AtlasReflex AtlasReflex-* External -no_auto_import + + + + +# UnitTest programs +apply_pattern declare_joboptions files="test.txt navigation2dot.py" + +use TestTools TestTools-* AtlasTest +apply_pattern UnitTest_run unit_test=TriggerElement extrapatterns=".*" +apply_pattern UnitTest_run unit_test=Holder extrapatterns=".*" +apply_pattern UnitTest_run unit_test=Registration extrapatterns=".*" + +apply_pattern UnitTest_run unit_test=Ownership extrapatterns=".*" + +apply_pattern UnitTest_run unit_test=HLTNavigation extrapatterns=".*" +apply_pattern UnitTest_run unit_test=RoICache extrapatterns=".*" + + + + +apply_pattern lcgdict dict=TrigNavigation selectionfile=selection.xml headerfiles="../TrigNavigation/TrigNavigationDict.h" +end_private diff --git a/Trigger/TrigEvent/TrigNavigation/doc/mainpage.h b/Trigger/TrigEvent/TrigNavigation/doc/mainpage.h new file mode 100644 index 0000000000000000000000000000000000000000..b01797bfe5cbcf31f93027fa4ce63ec80c3d887b --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/doc/mainpage.h @@ -0,0 +1,23 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + + +@mainpage TrigNavigation Package + +@section TrigSteeringEventIntro Introduction + +This package contains the new(rel 13) Trigger Navigation structure: + - HLT::TriggerElement: which is node of navigation structure graph + - HLT::Navigation: is collection of accessor methods for the whole navigation structure + - HLT::RoICacheHelper: which is helper class used in FEX algorithms to do so called "caching". + + + +Notice little dependency. It is a core package. +@htmlinclude used_packages.html + + +*/ diff --git a/Trigger/TrigEvent/TrigNavigation/python/TrigNavigationConfig.py b/Trigger/TrigEvent/TrigNavigation/python/TrigNavigationConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..1b6d7e0ce52de5fb9099a1b3b28d6dd5210b41c0 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/python/TrigNavigationConfig.py @@ -0,0 +1,58 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +from TrigNavigation.TrigNavigationConf import HLT__Navigation + + + +class HLTNavigation ( HLT__Navigation ): + __slots__ = [] + + def __init__(self, name = 'Navigation' ):# , offline=None): + super( HLTNavigation, self ).__init__( name ) # + # self.Serializer = Serializer() + from TrigSerializeResult.TrigSerializeResultConf import TrigTSerializer + from AthenaCommon.AppMgr import ToolSvc + ToolSvc += TrigTSerializer() + + def appendToPayload(self, classname ): + if classname not in self.ClassesToPayload: + self.ClassesToPayload += [ classname ] + + def removeFromPayload(self, classname ): + self.ClassesToPayload.remove ( classname ) + + + +class HLTNavigationOffline ( HLTNavigation ): + __slots__ = [] + def __init__(self, name = 'Navigation' ): + super( HLTNavigationOffline, self ).__init__( name ) + + def setDefaults(self, handle): + handle.ReferenceAllClasses = True + handle.ClassesToPayload = [] + + + + +class HLTNavigationOnline ( HLTNavigation ): + __slots__ = [] + def __init__(self, name = 'Navigation' ): + super( HLTNavigationOnline, self ).__init__( name ) + + def setDefaults(self, handle): + handle.ReferenceAllClasses = False + handle.ClassesToPayload = [] + + + +class TestingHLTNavigationOffline ( HLTNavigation ): + __slots__ = [] + def __init__(self, name = 'Navigation' ): + super( TestingHLTNavigationOffline, self ).__init__( name ) + + def setDefaults(self, handle): + handle.ReferenceAllClasses = True + handle.ClassesToPayload = [] + from AthenaCommon.Constants import VERBOSE + handle.OutputLevel = VERBOSE diff --git a/Trigger/TrigEvent/TrigNavigation/python/__init__.py b/Trigger/TrigEvent/TrigNavigation/python/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..c87c7b03a3cfa86ac617897ff933ff867e5f75a1 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/python/__init__.py @@ -0,0 +1,8 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +# File: TrigNavigation/__init__.py +# Author: Tomasz.Bold@cern.ch + +__version__ = '1.0.0' +__author__ = 'Tomasz.Bold@cern.ch' +__all__ = [ 'TrigNavigationConfig' ] diff --git a/Trigger/TrigEvent/TrigNavigation/share/HLTNavigation_test.ref b/Trigger/TrigEvent/TrigNavigation/share/HLTNavigation_test.ref new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Trigger/TrigEvent/TrigNavigation/share/Holder_test.ref b/Trigger/TrigEvent/TrigNavigation/share/Holder_test.ref new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Trigger/TrigEvent/TrigNavigation/share/Registration_test.ref b/Trigger/TrigEvent/TrigNavigation/share/Registration_test.ref new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Trigger/TrigEvent/TrigNavigation/share/RoICache_test.ref b/Trigger/TrigEvent/TrigNavigation/share/RoICache_test.ref new file mode 100644 index 0000000000000000000000000000000000000000..93e06b516dcbdf13f38eb5c956238574761985d0 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/share/RoICache_test.ref @@ -0,0 +1,191 @@ +Athena::getMessageSvc: WARNING MessageSvc not found, will use std::cout +RoICache_test INFO LINE:77 Start of the test: RoIcaching test + + +Initializing Gaudi ApplicationMgr using job opts ../share/test.txt +JobOptionsSvc INFO # =======> /afs/cern.ch/user/t/tbold/workarea/devval/Trigger/TrigEvent/TrigNavigation/run/../share/test.txt +JobOptionsSvc INFO # (2,1): ApplicationMgr.DLLs += ["StoreGate", "TrigNavigation", "TrigSerializeCnvSvc"] +JobOptionsSvc INFO # (3,1): ApplicationMgr.ExtSvc += ["ClassIDSvc"] +JobOptionsSvc INFO # (4,1): ApplicationMgr.ExtSvc += ["TrigSerializeCnvSvc"] +JobOptionsSvc INFO # (5,1): ApplicationMgr.ExtSvc += ["StoreGateSvc", "StoreGateSvc/DetectorStore", "StoreGateSvc/HistoryStore"] +JobOptionsSvc INFO # (6,1): ApplicationMgr.ExtSvc += ["ActiveStoreSvc"] +JobOptionsSvc INFO # (7,1): ApplicationMgr.ExtSvc += ["ToolSvc"] +JobOptionsSvc INFO # (8,1): AuditorSvc.Auditors += ["AlgContextAuditor"] +JobOptionsSvc INFO # (9,1): StoreGateSvc.OutputLevel = 1 +JobOptionsSvc INFO # (10,1): StoreGateSvc.ActivateHistory = 0 +JobOptionsSvc INFO # (11,1): CLIDSvc.OutputLevel = 1 +JobOptionsSvc INFO # (12,1): ClassIDSvc.OutputLevel = 1 +JobOptionsSvc INFO # (13,1): MessageSvc.OutputLevel = 1 +JobOptionsSvc INFO # (14,1): MessageSvc.useColors = 0 +JobOptionsSvc INFO # (35,1): Holder_test.OutputLevel = 1 +JobOptionsSvc INFO # (36,1): RoICache_test.OutputLevel = 3 +JobOptionsSvc INFO Job options successfully read in from ../share/test.txt +ApplicationMgr DEBUG Getting my own properties +ApplicationMgr INFO Application Manager Configured successfully +ServiceManager DEBUG Initializing service IncidentSvc +ServiceManager DEBUG Initializing service ClassIDSvc +ClassIDSvc DEBUG Service base class initialized successfully +ClassIDSvc VERBOSE ServiceLocatorHelper::service: found service IncidentSvc +ServiceManager DEBUG Initializing service TrigSerializeCnvSvc +TrigSerializeCn... INFO initialize() +ServiceManager DEBUG Initializing service StoreGateSvc +StoreGateSvc DEBUG Service base class initialized successfully +StoreGateSvc VERBOSE ServiceLocatorHelper::service: found service IncidentSvc +EventPersistenc... DEBUG Service base class initialized successfully +StoreGateSvc VERBOSE ServiceLocatorHelper::service: found service EventPersistencySvc +StoreGateSvc VERBOSE ServiceLocatorHelper::service: found service ClassIDSvc +ProxyProviderSvc VERBOSE ServiceLocatorHelper::service: found service EventPersistencySvc +ProxyProviderSvc DEBUG Service base class initialized successfully +StoreGateSvc VERBOSE ServiceLocatorHelper::service: found service ProxyProviderSvc +ServiceManager DEBUG Initializing service DetectorStore +DetectorStore DEBUG Service base class initialized successfully +DetectorStore VERBOSE ServiceLocatorHelper::service: found service IncidentSvc +DetectorStore VERBOSE ServiceLocatorHelper::service: found service EventPersistencySvc +DetectorStore VERBOSE ServiceLocatorHelper::service: found service ClassIDSvc +DetectorStore VERBOSE ServiceLocatorHelper::service: found service ProxyProviderSvc +ServiceManager DEBUG Initializing service HistoryStore +HistoryStore DEBUG Service base class initialized successfully +HistoryStore VERBOSE ServiceLocatorHelper::service: found service IncidentSvc +HistoryStore VERBOSE ServiceLocatorHelper::service: found service EventPersistencySvc +HistoryStore VERBOSE ServiceLocatorHelper::service: found service ClassIDSvc +HistoryStore VERBOSE ServiceLocatorHelper::service: found service ProxyProviderSvc +ServiceManager DEBUG Initializing service ActiveStoreSvc +ActiveStoreSvc DEBUG Service base class initialized successfully +ActiveStoreSvc VERBOSE ServiceLocatorHelper::service: found service StoreGateSvc +ServiceManager DEBUG Initializing service ToolSvc +ToolSvc DEBUG Service base class initialized successfully +ServiceManager DEBUG Initializing service AppMgrRunable +AppMgrRunable DEBUG Service base class initialized successfully +ServiceManager DEBUG Initializing service EventLoopMgr +EventLoopMgr DEBUG Service base class initialized successfully +EventDataSvc DEBUG Service base class initialized successfully +EventDataSvc VERBOSE ServiceLocatorHelper::service: found service IncidentSvc +EventLoopMgr WARNING Unable to locate service "EventSelector" +EventLoopMgr WARNING No events will be processed from external input. +HistogramDataSvc DEBUG Service base class initialized successfully +HistogramDataSvc VERBOSE ServiceLocatorHelper::service: found service IncidentSvc +HistogramPersis... DEBUG 'CnvServices':[ 'RootHistSvc' ] +HistogramPersis... DEBUG Service base class initialized successfully +HistogramPersis...WARNING Histograms saving not required. +HistogramDataSvc VERBOSE ServiceLocatorHelper::service: found service HistogramPersistencySvc +ApplicationMgr INFO Application Manager Initialized successfully +ApplicationMgr Ready +ToolSvc.Navigat...VERBOSE ServiceLocatorHelper::service: found service StoreGateSvc +NavigationCore....VERBOSE ServiceLocatorHelper::service: found service TrigSerializeCnvSvc +RoICache_test INFO LINE:106 Test progress fine: OK navigation tool retrieved +RoICache_test INFO LINE:109 Test progress fine: OK navigation casted +RoICache_test INFO LINE:153 Test progress fine: Navigation structure built +RoICache_test:calo INFO LINE:34 Start of the test: One algorithm test calo +RoICache_test:calo INFO REGTEST executing on 11 +RoICache_test:calo INFO REGTEST REAL execution needed on 11 +RoICache_test:calo INFO LINE:56 End of the test: One algorithm test calo +RoICache_test:calo INFO LINE:34 Start of the test: One algorithm test calo +RoICache_test:calo INFO REGTEST executing on 12 +RoICache_test:calo INFO REGTEST CACHED execution needed on 12 +RoICache_test:calo INFO LINE:56 End of the test: One algorithm test calo +RoICache_test:calo INFO LINE:34 Start of the test: One algorithm test calo +RoICache_test:calo INFO REGTEST executing on 13 +RoICache_test:calo INFO REGTEST CACHED execution needed on 13 +RoICache_test:calo INFO LINE:56 End of the test: One algorithm test calo +RoICache_test:calo INFO LINE:34 Start of the test: One algorithm test calo +RoICache_test:calo INFO REGTEST executing on 14 +RoICache_test:calo INFO REGTEST CACHED execution needed on 14 +RoICache_test:calo INFO LINE:56 End of the test: One algorithm test calo +RoICache_test:calo INFO LINE:34 Start of the test: One algorithm test calo +RoICache_test:calo INFO REGTEST executing on 1200 +RoICache_test:calo INFO REGTEST REAL execution needed on 1200 +RoICache_test:calo INFO LINE:56 End of the test: One algorithm test calo +RoICache_test INFO LINE:178 Test progress fine: Executed calo on clusters +RoICache_test:caux INFO LINE:34 Start of the test: One algorithm test caux +RoICache_test:caux INFO REGTEST executing on 13 +RoICache_test:caux INFO REGTEST REAL execution needed on 13 +RoICache_test:caux INFO LINE:56 End of the test: One algorithm test caux +RoICache_test:caux INFO LINE:34 Start of the test: One algorithm test caux +RoICache_test:caux INFO REGTEST executing on 14 +RoICache_test:caux INFO REGTEST CACHED execution needed on 14 +RoICache_test:caux INFO LINE:56 End of the test: One algorithm test caux +RoICache_test:c... INFO LINE:34 Start of the test: One algorithm test calo2 +RoICache_test:c... INFO REGTEST executing on 14 +RoICache_test:c... INFO REGTEST REAL execution needed on 14 +RoICache_test INFO LINE:210 Test progress fine: got back object -38 +RoICache_test:c... INFO LINE:56 End of the test: One algorithm test calo2 +RoICache_test:c... INFO LINE:34 Start of the test: One algorithm test calo2 +RoICache_test:c... INFO REGTEST executing on 13 +RoICache_test:c... INFO REGTEST CACHED execution needed on 13 +RoICache_test:c... INFO LINE:56 End of the test: One algorithm test calo2 +RoICache_test:c... INFO LINE:34 Start of the test: One algorithm test calo2 +RoICache_test:c... INFO REGTEST executing on 12 +RoICache_test:c... INFO REGTEST REAL execution needed on 12 +RoICache_test INFO LINE:210 Test progress fine: got back object -34 +RoICache_test:c... INFO LINE:56 End of the test: One algorithm test calo2 +RoICache_test:c... INFO LINE:34 Start of the test: One algorithm test calo2 +RoICache_test:c... INFO REGTEST executing on 11 +RoICache_test:c... INFO REGTEST CACHED execution needed on 11 +RoICache_test:c... INFO LINE:56 End of the test: One algorithm test calo2 +RoICache_test:c... INFO LINE:34 Start of the test: One algorithm test calo2 +RoICache_test:c... INFO REGTEST executing on 1200 +RoICache_test:c... INFO REGTEST REAL execution needed on 1200 +RoICache_test INFO LINE:210 Test progress fine: got back object -34 +RoICache_test:c... INFO LINE:56 End of the test: One algorithm test calo2 +RoICache_test INFO LINE:228 Test progress fine: Executed c2 on clusters +RoICache_test:trk INFO LINE:34 Start of the test: One algorithm test trk +RoICache_test:trk INFO REGTEST executing on 102 +RoICache_test:trk INFO REGTEST REAL execution needed on 102 +RoICache_test INFO LINE:251 Test progress fine: got back object -34 +RoICache_test:trk INFO LINE:56 End of the test: One algorithm test trk +RoICache_test:trk INFO LINE:34 Start of the test: One algorithm test trk +RoICache_test:trk INFO REGTEST executing on 104 +RoICache_test:trk INFO REGTEST CACHED execution needed on 104 +RoICache_test:trk INFO LINE:56 End of the test: One algorithm test trk +RoICache_test:trk INFO LINE:34 Start of the test: One algorithm test trk +RoICache_test:trk INFO REGTEST executing on 103 +RoICache_test:trk INFO REGTEST CACHED execution needed on 103 +RoICache_test:trk INFO LINE:56 End of the test: One algorithm test trk +RoICache_test:trk INFO LINE:34 Start of the test: One algorithm test trk +RoICache_test:trk INFO REGTEST executing on 101 +RoICache_test:trk INFO REGTEST CACHED execution needed on 101 +RoICache_test:trk INFO LINE:56 End of the test: One algorithm test trk +RoICache_test:trk INFO LINE:34 Start of the test: One algorithm test trk +RoICache_test:trk INFO REGTEST executing on 10100 +RoICache_test:trk INFO REGTEST REAL execution needed on 10100 +RoICache_test INFO LINE:251 Test progress fine: got back object -34 +RoICache_test:trk INFO LINE:56 End of the test: One algorithm test trk +RoICache_test INFO LINE:268 Test progress fine: Executed trk +RoICache_test:m... INFO LINE:34 Start of the test: One algorithm test matcher +RoICache_test:m... INFO REGTEST executing on 1001 +RoICache_test:m... INFO REGTEST REAL execution needed on 1001 +RoICache_test INFO LINE:295 Test progress fine: got back object 55 +RoICache_test:m... INFO LINE:56 End of the test: One algorithm test matcher +RoICache_test:m... INFO LINE:34 Start of the test: One algorithm test matcher +RoICache_test:m... INFO REGTEST executing on 1002 +RoICache_test:m... INFO REGTEST REAL execution needed on 1002 +RoICache_test INFO LINE:295 Test progress fine: got back object 77 +RoICache_test:m... INFO LINE:56 End of the test: One algorithm test matcher +RoICache_test:m... INFO LINE:34 Start of the test: One algorithm test matcher +RoICache_test:m... INFO REGTEST executing on 1003 +RoICache_test:m... INFO REGTEST CACHED execution needed on 1003 +RoICache_test:m... INFO LINE:56 End of the test: One algorithm test matcher +RoICache_test:m... INFO LINE:34 Start of the test: One algorithm test matcher +RoICache_test:m... INFO REGTEST executing on 1004 +RoICache_test:m... INFO REGTEST CACHED execution needed on 1004 +RoICache_test:m... INFO LINE:56 End of the test: One algorithm test matcher +RoICache_test:m... INFO LINE:34 Start of the test: One algorithm test matcher +RoICache_test:m... INFO REGTEST executing on 100100 +RoICache_test:m... INFO REGTEST REAL execution needed on 100100 +RoICache_test INFO LINE:295 Test progress fine: got back object 77 +RoICache_test:m... INFO LINE:56 End of the test: One algorithm test matcher +RoICache_test INFO LINE:313 Test progress fine: Executed ma on electron TEs +RoICache_test:o... INFO LINE:34 Start of the test: One algorithm test overlap +RoICache_test:o... INFO REGTEST executing on 222 +RoICache_test:o... INFO REGTEST REAL execution needed on 222 +RoICache_test:o... INFO LINE:56 End of the test: One algorithm test overlap +RoICache_test:o... INFO LINE:34 Start of the test: One algorithm test overlap +RoICache_test:o... INFO REGTEST executing on 223 +RoICache_test:o... INFO REGTEST CACHED execution needed on 223 +RoICache_test:o... INFO LINE:56 End of the test: One algorithm test overlap +RoICache_test:o... INFO LINE:34 Start of the test: One algorithm test overlap +RoICache_test:o... INFO REGTEST executing on 224 +RoICache_test:o... INFO REGTEST REAL execution needed on 224 +RoICache_test:o... INFO LINE:56 End of the test: One algorithm test overlap +RoICache_test INFO LINE:353 Test progress fine: Executed on topo TEs +RoICache_test INFO LINE:354 Test progress fine: ALLOK diff --git a/Trigger/TrigEvent/TrigNavigation/share/TriggerElement_test.ref b/Trigger/TrigEvent/TrigNavigation/share/TriggerElement_test.ref new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Trigger/TrigEvent/TrigNavigation/share/navigation2dot.py b/Trigger/TrigEvent/TrigNavigation/share/navigation2dot.py new file mode 100755 index 0000000000000000000000000000000000000000..44cbb51987ba43f1e12e2b8beb24a2a3192e3dd7 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/share/navigation2dot.py @@ -0,0 +1,339 @@ +#! /usr/bin/python +# Q? Send mail to Tomasz dot Bold at cern dot ch + +import string +from string import rstrip,atoi,replace +import sys +import commands +import os +import re + +teIdtoName = {'0':'0'} +featureCLIDtoName = {} + + + + + +if 'CMTROOT' not in os.environ.keys(): + print 'Can not find out graphviz binaries: ',GraphivizBinPath + print 'Have you setup CMT environmet? CMTROOT not set' + raise SystemExit + +else: + # setup lib + GraphivizPath = os.environ['CMTROOT']+'/../Grafviz/2.2' + GraphivizBinPath = GraphivizPath+'/bin/' + GraphivizLibPath = GraphivizPath+'/lib/graphviz' + + if 'LD_LIBRARY_PATH' not in os.environ.keys(): + os.environ['LD_LIBRARY_PATH'] = '' + os.environ['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']+':'+GraphivizLibPath + + print "Graphviz programs from there: ", GraphivizBinPath + + +# global options driving grph drawing (switched by command line parser) +options = {'drawFeatures': False, + 'clid': True, + 'convert': False, + 'program': 'dot', + 'event': None, + 'raw': False, + 'regex': re.compile('.*')} + + +def featureClassName(clid): + """ converts the CLID to ClassName in C++. If falied then CLID instead. + The CLIDS to name is taken from CLID Svc dump.""" + if clid in featureCLIDtoName.keys(): + return featureCLIDtoName[clid] + else: + if options['clid'] is False: + return str(clid) + else: # use CLID DB clid command to get it) + name = commands.getoutput( 'clid '+clid).split(' ')[1] + featureCLIDtoName[clid] = name + return name + +def teName(teid): + if teid in teIdtoName.keys(): + return teIdtoName[teid] + else: + print "TE id: ", teid, " unknown" + return teid + +class TE: + def __init__(self, s): + # print s + # this si typical line it has to deal with: id:0;active:1;error:0;ptr:0x9606b98;#seeds:4,0x9606ce0 0x9607338 0x96075b0 0x96077e8 #seededBy:0;#RoI:0;#features:1 CLID:242645981 idx:0:0:1 label:"OPI_L2"; + tok = s.split(';') + #print tok + self.tename = teName(tok[0].split(':')[1]) + self.active = bool(int(tok[1].split(':')[1])) + self.error = bool(int(tok[2].split(':')[1])) + self.ptr = tok[3].split(':')[1] + self.roi = tok[5].split(':')[1] + # find out relations + self.relations = [] + self.terminal = False + seeds = tok[4].split(',')[0].split(':')[1] + if seeds is '0': + self.terminal = True + else: + self.relations = tok[4].split(',')[1].split(' ')[0:-1] + + # find out features attached + #print tok + self.features = [] + global options + passed=False + if options['drawFeatures']: + for part in tok: + if 'keyprints' in part: + passed=True + clid = 0 + label = '' + idx='' + for field in part.split(" "): + if field.find("CLID") is not -1: + clid = field.split(":")[1].lstrip(' ').lstrip(' ') + elif field.find("label") is not -1: + label = field.split(":")[1].rstrip("\"").lstrip("\"") + elif field.find("idx") is not -1: + idx=field + if clid is not 0: + #print (featureClassName(clid), label, idx, passed) + self.features.append( (featureClassName(clid), label, idx, ('','*')[passed]) ) + + # print self.features + + # print self.tename, self.active, self.ptr, self.relations + + def node(self): + """ Draws node of the graph. """ + global options + + if options['regex'].search(self.tename) == None and self.tename != '0': + # print "rejecting TE which of name ", self.tename, ' due to regex' + return None + + nodename = 'X'+ str(self.ptr) + line = nodename +' [ label="{TE: ' + self.tename + + line += reduce(lambda x,y: x + "|"+y[0]+ "(" +y[1] + ' '+ y[2]+str(y[3])+")", self.features, "") + line += '}", style=filled, ' + + # special nodes + if self.tename is '0': + line += 'fillcolor=pink, ' + else: + if self.active: + line += 'color=green, ' + else: + line += 'color=plum, ' + + # error color scheme + if self.error: + line += 'fillcolor=red, ' + else: + line += 'fillcolor=palegreen, ' + + + + + line += 'shape=record' + line += ']\n' + return line + + def edges (self): + """ Draws node and edges. """ + line = '' + for rel in self.relations: + line += 'X'+self.ptr + ' -> X' + rel + '\n' + return line + + def __str__(self): + r = self.node() + if r: + return r + self.edges() + else: + return "" + + +def nav2dot(nav, eventId, level): + """ converts""" + global options + inputTEs = nav.split('\n') + stringTEs = [] + for te in inputTEs: + if te is not '': + stringTEs.append(te.lstrip(' |\_')) + + # unique + uniqueTEs = [] + for ste in stringTEs: + if ste not in uniqueTEs: + uniqueTEs.append(ste) + # print "LEN :" + str(len(stringTEs)) + "-->" + str(len(uniqueTEs)) + + objectTEs = map( lambda x: TE(x), uniqueTEs) + dot = 'digraph Menu {\n'\ + +'\n'\ + +'graph [ rankdir = "TR"];'\ + +'node [ shape=polygon, fontname=Helvetica ]\n'\ + +'edge [ fontname=Helvetica ]\n' + dot += reduce(lambda x,y: x+str(y), objectTEs, '') + dot += '\n}' + + fname = 'navigationEvent-'+level+'-'+str(eventId) + if options['event'] is None or str(options['event']) == str(eventId): + print 'writing file: '+fname+'.dot' + f = file('temp.dot','w') + f.write(dot) + f.close() + #print commands.getoutput(GraphivizBinPath+'unflatten -l4 -f -c2 -o '+ fname+ '.dot temp.dot') + print commands.getoutput('mv -f temp.dot '+fname+'.dot') + print commands.getoutput('/bin/rm -f temp.dot') + if options['convert']: + print 'converting file: '+fname+'.dot to graphics' + global GraphivizBinPath + print commands.getoutput(GraphivizBinPath+options['program']+' ' + fname +'.dot -Tpng -o '+fname+'.png') + # delete dot file + print commands.getoutput('rm -f '+fname+'.dot') +# nav2dot(navex) + +def parseLog(file): + eventNumber = -1 + navigationStarted=False + nav = "" + step = 0 + stepToLevel = ["L2", "EFunpacking", "EF"] + + for line in file: + if line.find("- --") is not -1: + # print line + if line.find("inputTEs") is not -1: # we spoted input TE in sequence printout + try: + teId = line.split(" ")[5] + teId = string.strip(teId, "(), \"\n") + teId = rstrip(teId, ",") + teName = line.split(" ")[4] + teName = string.strip(teName, "(), \"\n") + teIdtoName[teId] = teName + except: + pass + if line.find(" outputTE : (") is not -1: + teId = line.split(" ")[7] + teId = string.strip(teId, "() \n") + teName = line.split(" ")[6] + teName = string.strip(teName, "()\",\n") + teIdtoName[teId] = teName + + # catch the navigation printout + if line.find("start processing event #") is not -1: + eventId = line.split("#")[1].split(",")[0] + step=0 + print "scanning event: ",eventId + + + if line.find("Start of HLT Processing in L2") is not -1: + step = 0 + + if line.find("Start of HLT Processing in EF") is not -1: + step = 1 + + if line.find("TrigSteer_EF.ResultBuilder") is not -1: + step = 2 + + # catch navigation block + if line.find("\\_") is not -1: + if navigationStarted is False: + navigationStarted=True + nav += line + else: + if navigationStarted is True: + navigationStarted=False + nav2dot(nav, eventId, stepToLevel[step] ) + + nav = "" + + +def parseCLIDs(): + + if options['clid'] is False: + clids = file("CLIDDBout.txt") + for line in clids: + clid = line.split(" ")[0] + name = line.split(" ")[1].rstrip("\n") + featureCLIDtoName[clid] = name + # print featureCLIDtoName + + + +def parseOpt(): + global options + stat = True + + if '-f' in sys.argv: + options['drawFeatures'] = True + print "OPTION: will draw features" + + if '-d' in sys.argv: + options['clid'] = True + print "OPTION: will use clid command to get class names (slower)" + if '-x' in sys.argv: + options['regex'] = re.compile(sys.argv[sys.argv.index('-x')+1]) + print "OPTION: will use only TEs accepted by regex", sys.argv[sys.argv.index('-x')+1] + if '-e' in sys.argv: + import string + options['event'] = string.atoi(sys.argv[sys.argv.index('-e')+1]) + print "OPTION: will only draw event: ", options["event"] + + if '-c' in sys.argv: + options['convert'] = True; + print "OPTION: will convert to graphics on the fly" + + if '-p' in sys.argv: + options['program'] = sys.argv[sys.argv.index('-p')+1] + print "OPTION: will convert to graphics on the fly using ", options['program'] + + if '-r' in sys.argv: + options['raw'] = True + options['configdump'] = sys.argv[sys.argv.index('-r')+2] + options['navigationdump'] = sys.argv[sys.argv.index('-r')+1] + + + if '-h' in sys.argv: + print "OPTION: Help needed? Here it is:" + print """ + Files generated by this utility can be viewed by programs like 'dotty'. + Thay can be converted to graphics using probram 'dot': + dot nav_event_123.dot -o nav123.png -Tpng + + -h -- this help + -f -- draw freatures atteched to TE (with lables) + -d -- use clid command instead of CLIDDBout.txt to get human class names rather than CLIDs + -e X -- writeout only event (X) + -x regex -- use the regex to select only wanted TEs + -c -- convert graphs to png on the fly using dot program + -p prog -- use other program(neato, twopi, circo, fdp) + -r navigationfile configfile -- take files with the navigation dump and the configuration dump (rather than plain log) + """ + stat = False + return stat +# main script + +if parseOpt(): + if not options['raw']: + logname = sys.argv[-1] + log = file(logname) + parseCLIDs() + parseLog(log) + else: + conflog = file(options['configdump']) + parseLog(conflog) + navlog = file(options['navigationdump']) + parseLog(navlog) + + #print teIdtoName diff --git a/Trigger/TrigEvent/TrigNavigation/share/test.txt b/Trigger/TrigEvent/TrigNavigation/share/test.txt new file mode 100644 index 0000000000000000000000000000000000000000..1824074540c594b678203e897c36f734b221bbc9 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/share/test.txt @@ -0,0 +1,36 @@ +//ApplicationMgr.DLLs += { "StoreGate", "CLIDSvc", "TrigNavigation" }; +ApplicationMgr.DLLs += { "StoreGate", "TrigNavigation", "TrigSerializeCnvSvc" }; +ApplicationMgr.ExtSvc += { "ClassIDSvc" }; +ApplicationMgr.ExtSvc += { "TrigSerializeCnvSvc" }; +ApplicationMgr.ExtSvc += { "StoreGateSvc", "StoreGateSvc/DetectorStore", "StoreGateSvc/HistoryStore" }; +ApplicationMgr.ExtSvc += { "ActiveStoreSvc" }; +ApplicationMgr.ExtSvc += { "ToolSvc" }; +AuditorSvc.Auditors += { "AlgContextAuditor"}; +StoreGateSvc.OutputLevel = 1; +StoreGateSvc.ActivateHistory = false; +CLIDSvc.OutputLevel = 1; +ClassIDSvc.OutputLevel = 1; +MessageSvc.OutputLevel = 1; +MessageSvc.useColors = false; + +//StoreGateSvc.FolderNameList = { "MyFolder", "YourFolder" }; +//MyFolder.ItemList = {"Foo#Bla", "Bar#*"}; +//YourFolder.ItemList = {"8101", "8107#", "Baricco#*"}; + +//#include "IOVSvc/IOVSvc.txt" +//ApplicationMgr.DLLs += { "IOVSvc" }; + +//ApplicationMgr.ExtSvc += { "IOVSvc" }; + +//EventPersistencySvc.CnvServices += { "TrigSerializeCnvSvc" } + +// +//Navigation.ReferenceAllClasses = 1 +//ApplicationMgr.DLLs += { "TrigCaloEvent" }; +ToolSvc.Navigation.ReferenceAllClasses = 1; +ToolSvc.Navigation.ClassesToPreregister = {"TestA#EverEmptyButPresent", "TestA#AgainPresentButEmpty", "TestA#","TestBContainer#BContainer1", "TestBContainer#BContainer2", "TestDContainer#DContainer1"}; +//ToolSvc.Navigation.AuxClasses = {"TestAuxA#EverEmptyButPresent", "TestAuxB#BContainer2"}; + +ToolSvc.Navigation.OutputLevel=4; +Holder_test.OutputLevel=1; +RoICache_test.OutputLevel=3; diff --git a/Trigger/TrigEvent/TrigNavigation/src/Holder.cxx b/Trigger/TrigEvent/TrigNavigation/src/Holder.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e1be3adad899ad469df70a311ca195981b5dde4c --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/src/Holder.cxx @@ -0,0 +1,110 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include <sstream> +#include <boost/regex.hpp> + +#include "TrigNavigation/Holder.h" +#include "TrigSerializeResult/StringSerializer.h" +#include "TrigSerializeResult/ITrigSerializerToolBase.h" + +using namespace HLTNavDetails; + +/***************************************************************************** + * + * INNER CLASS (fatures handling) + * + *****************************************************************************/ +IHolder::IHolder() + : m_serialized(0), + m_log(0), + m_storeGate(0), + m_serializer(0), + m_label(""), + m_subTypeIndex(0), + m_aux(0), + m_uniqueCounter(0) +{} + +IHolder::~IHolder() { + if ( m_aux ) { delete m_aux; } +} + +void IHolder::prepare(MsgStream* log, HLT::AccessProxy* sg) { + m_storeGate = sg; + m_log = log; +} + +bool IHolder::serialize(std::vector<uint32_t>& output) const { + if ( m_log->level()<=MSG::DEBUG ) + *m_log << MSG::DEBUG << "Holder<T> serialize, " << *this << endreq; + // if feature to be forgotten then indication of it is simply 0 size of serialized vector + + output.push_back( typeClid() ); + output.push_back( m_subTypeIndex ); + + // label + std::vector<uint32_t> serializedLabel; + StringSerializer ss; + ss.serialize( m_label, serializedLabel ); + output.push_back( serializedLabel.size() ); + output.insert(output.end(), serializedLabel.begin(), serializedLabel.end()); + return true; +} + +bool IHolder::enquireSerialized(const std::vector<uint32_t>& blob, + std::vector<uint32_t>::const_iterator& it, + CLID& c, std::string& label, uint16_t& subtypeIndex ) { + + if ( it == blob.end() ) return false; + + c = *it++; + if ( it == blob.end() ) return false; + + subtypeIndex = *it++; + if ( it == blob.end() ) return false; + + unsigned labelSize = *it++; + if ( it == blob.end() ) return false; + if ( it+labelSize > blob.end() ) return false; + + std::vector<uint32_t> tmp(it, it+labelSize); + it += labelSize; + + StringSerializer s; + s.deserialize(tmp, label); + return true; +} + + + +std::string IHolder::generateAliasKey(CLID c, uint16_t sti, const std::string& label, unsigned size) { + std::ostringstream ss; + ss << "HLTAutoKey_" << label << "_" << c << "_" << sti << "_" << (size == 0xffffffff ? "back" : "to") << "_" << m_uniqueCounter; + std::string st = ss.str(); + if ( m_log->level()<=MSG::DEBUG ) + *m_log << MSG::DEBUG << "IHolder::generateAliasKey generated key: " << st << endreq; + m_uniqueCounter++; + return st; +} + +void IHolder::print(MsgStream& m) const { + m << "CLID: " << typeClid() << " label: \"" << label() << "\" subTypeIndex: " << subTypeIndex(); +} + +MsgStream& HLTNavDetails::operator<< ( MsgStream& m, const HLTNavDetails::IHolder& h ) { + h.print (m); + return m; +} + +std::string HLTNavDetails::formatSGkey(const std::string& prefix, const std::string& containername, const std::string& label){ + std::string cleaned = containername; + boost::regex rx1("_v[0-9]+$"); + cleaned = boost::regex_replace(cleaned,rx1,std::string("")); + boost::regex rx2("::"); + cleaned = boost::regex_replace(cleaned,rx2,std::string("__")); + return prefix+"_"+cleaned+(label.size() ? "_"+label : ""); +} + + diff --git a/Trigger/TrigEvent/TrigNavigation/src/Navigation.cxx b/Trigger/TrigEvent/TrigNavigation/src/Navigation.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a465506065b1157ed2ae2059ba6cc52e036b76f5 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/src/Navigation.cxx @@ -0,0 +1,250 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include <sstream> +#include <iostream> +#include <algorithm> +#include <iterator> // remove it (it is here to help with debugging) + + + +//#include <boost/cstdint.hpp> +//#include <stdint.h> +#include <boost/lexical_cast.hpp> + +#include "AthenaKernel/getMessageSvc.h" +#include "GaudiKernel/System.h" +//#include "GaudiKernel/IClassManager.h" +//#include "GaudiKernel/SmartIF.h" + +#include "TrigNavigation/Navigation.h" +using namespace HLT; +using namespace HLTNavDetails; + + +//std::map<CLID, IHolder* > Navigation::m_types; + + + +//Navigation::Navigation( TriggerElementFactory& factory ) +Navigation::Navigation( const std::string& type, const std::string& name, + const IInterface* parent ) + : AthAlgTool(type, name, parent), + m_serializerServiceHandle("TrigSerializeCnvSvc", name), + m_storeGateHandle("StoreGateSvc", name) +{ + + declareProperty("ReferenceAllClasses", m_referenceAllClasses=false, + "Flag anabling all features referenceing."); + + declareProperty("ClassesToPayload", m_classesToPayloadProperty, + "List of classes which need to be serialized together with the Navigation."); + + declareProperty("ClassesFromPayload", m_classesFromPayloadProperty, + "List of classes which need to be de-serialized together with the Navigation."); + + declareProperty("ClassesToPayload_DSonly", m_classesToPayloadProperty_DSonly, + "List of classes which need to be serialized together with the Navigation (Only in DataScouting collection)."); + + declareProperty("ClassesToPreregister", m_classesToPreregisterProperty, + "List of classes which need to be put in SG independently if they appear in event."); + + // declareProperty("SerializeSpaceLimit", m_serializeSpaceLimit=8000000, + // "Limit of the size which navigation can use once serialized."); + + declareProperty("Dlls", m_dlls, "Libraries to load (with trigger EDM)"); + declareProperty("ObjectsKeyPrefix", m_objectsKeyPrefix="HLT", "The prefix which all Trigger EDM objects will get, by default it is HLT"); + declareProperty("ObjectsIndexOffset", m_objectsIndexOffset=0, "The offset with which the objects idx is be shifted."); + declareProperty("EvtStore", m_storeGateHandle); + + declareInterface<Navigation>(this); +} + +Navigation::~Navigation() {} + + +/***************************************************************************** + * + * INITIALIZATION and FINALIZATION + * + *****************************************************************************/ +StatusCode Navigation::initialize() { + // message log + delete m_log; + m_log = new MsgStream(msgSvc(), name() ); + + // factor of TEs + /* in CORE m_factory = new TriggerElementFactory; + if ( m_factory->listOfProduced().size() != 0 ) { + *m_log << MSG::FATAL << "Navigation::Navigation(), factory size not 0 but: " + << m_factory->listOfProduced().size() << endreq; + return StatusCode::FAILURE; + } + + */ + // get StoreGate + StatusCode sc = m_storeGateHandle.retrieve(); + if(sc.isFailure()) { + (*m_log) << MSG::FATAL << "Unable to get pointer to StoreGate Service: " + << m_storeGateHandle << endreq; + return StatusCode::FAILURE; + } + // m_storeGate = m_storeGateHandle.operator->(); + // AccessProxy* ap = new AccessProxy(0, m_storeGateHandle.operator->()); + setAccessProxy(m_storeGateHandle.operator->()); + + // create the Serializer + // m_serializer = NULL; + /* + if ( m_serializerToolHandle.retrieve().isFailure() ) { + (*m_log) << MSG::FATAL << "failed to retrieve serializer tool: " + << m_serializerToolHandle<< endreq; + return StatusCode::FAILURE; + } else { + (*m_log) << MSG::DEBUG << "successfully retrieved serializer tool: " + << m_serializerTool << endreq; + // m_serializer = m_serializerTool.operator->(); + } + m_serializerTool = m_serializerToolHandle.operator->(); + */ + + StatusCode scnv = m_serializerSvc.retrieve(); + if (scnv.isFailure()){ + *m_log << MSG::FATAL << "Navigation::initialize() cannot get TrigSerializeCnvSvc" + << endreq; + } else { + if (m_log->level() <= MSG::DEBUG ) + *m_log << MSG::DEBUG << "Navigation::initialize() got TrigSerializeCnvSvc" + << endreq; + } + + // payload def + if ( classKey2CLIDKey(m_classesToPayloadProperty, m_classesToPayload).isFailure() ) { + (*m_log) << MSG::FATAL << "failed to decode property ClassesToPayload: " + << m_classesToPayloadProperty << endreq; + return StatusCode::FAILURE; + } + + if ( classKey2CLIDKey(m_classesToPayloadProperty_DSonly, m_classesToPayload_DSonly).isFailure() ) { + (*m_log) << MSG::FATAL << "failed to decode property ClassesToPayload: " + << m_classesToPayloadProperty_DSonly << endreq; + + return StatusCode::FAILURE; + } + + // initialize converters + for (size_t icl=0; icl<m_classesToPayload.size(); icl++){ + CLID cl = m_classesToPayload.at(icl).first; + StatusCode stmp = m_serializerSvc->addConverter(cl); + if (stmp.isFailure()) + *m_log << MSG::WARNING << "Initialization of a converter for CLID=" << cl << " failed" << endreq; + } + + + // preregistration def + if ( classKey2CLIDKey(m_classesToPreregisterProperty, m_classesToPreregister).isFailure() ) { + (*m_log) << MSG::FATAL << "failed to decode property ClassesToPreregister: " + << m_classesToPreregisterProperty << endreq; + return StatusCode::FAILURE; + } + + + // create string specific serializer + //in CORE m_stringSerializer = new StringSerializer(); + + // print out registered holders + HLT::TypeMaps::CLIDtoHolderMap::const_iterator holderIt; + if (m_log->level() <= MSG::VERBOSE ) { + for ( holderIt = HLT::TypeMaps::holders().begin(); holderIt != HLT::TypeMaps::holders().end(); ++holderIt ) { + if(!holderIt->second){ + (*m_log) << MSG::FATAL << "static type information not intialized. Holder is null pointer" << endreq; + } + (*m_log) << MSG::VERBOSE << *(holderIt->second) << endreq; + } + } + + // load libraries + std::vector<std::string>::const_iterator dlIt; + for ( dlIt = m_dlls.begin(); dlIt != m_dlls.end(); ++dlIt ) { + System::ImageHandle handle = 0; + if ( System::loadDynamicLib( *dlIt, &handle) != 1 ) { + (*m_log) << MSG::WARNING << "failed to load " << *dlIt << endreq; + } else { + if (m_log->level() <= MSG::DEBUG ) + (*m_log) << MSG::DEBUG << "forcibly loaded library " << *dlIt << endreq; + } + } + + // translate Class names into CLID numbers + if (m_log->level() <= MSG::DEBUG ) + (*m_log) << MSG::DEBUG << " successfully initialized Navigation " + << endreq; + + return StatusCode::SUCCESS; +} + +StatusCode +Navigation::classKey2CLIDKey(const std::vector<std::string> property, + std::vector<std::pair<CLID, + std::string> >& decoded ) { + // translate Class names into CLID numbers + IClassIDSvc* clidSvc; + if( service("ClassIDSvc", clidSvc).isFailure() ) { + (*m_log) << MSG::FATAL << "Unable to get pointer to CLIDSvc Service" << endreq; + return StatusCode::FAILURE; + } + + std::vector<std::string>::const_iterator it; + for ( it = property.begin(); it != property.end(); ++it ) { + CLID clid; + std::string key; + std::string type; + + if ( it->find("#") != std::string::npos ) { + type = it->substr(0, it->find("#") ); + key = it->substr(it->find("#")+1 ); + } else { + type = *it; + key = ""; + } + + if ( clidSvc->getIDOfTypeName(type, clid).isFailure() ) { + (*m_log) << MSG::FATAL << "Unable to get CLID for class: " << *it + << " check property" << endreq; + return StatusCode::FAILURE; + } + + if (m_log->level() <= MSG::DEBUG ) + (*m_log) << MSG::DEBUG << "Recognized CLID : " << type << " and key: " << key + << endreq; + + decoded.push_back(std::make_pair(clid, key)); + } + return StatusCode::SUCCESS; +} + +StatusCode Navigation::finalize() { + if (m_log->level() <= MSG::DEBUG ) + *m_log << MSG::DEBUG << "Navigation finalize" << endreq; + // reset(); + + /* in CORE elete m_stringSerializer; + delete m_factory; + delete m_log; + */ + /* + for (std::map< CLID, std::vector<uint32_t>* > ::iterator it = m_serializedFeatures.begin(); + it != m_serializedFeatures.end(); ++it) { + delete it->second; + } + */ + return StatusCode::SUCCESS; +} + + + +MsgStream& HLT::operator<< ( MsgStream& m, const Navigation& nav ) { + m << (NavigationCore&)nav; + return m; +} diff --git a/Trigger/TrigEvent/TrigNavigation/src/NavigationCore.cxx b/Trigger/TrigEvent/TrigNavigation/src/NavigationCore.cxx new file mode 100644 index 0000000000000000000000000000000000000000..9f95c652171e70bc47b57039917750b9183dbc1f --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/src/NavigationCore.cxx @@ -0,0 +1,1201 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include <sstream> +#include <iostream> +#include <algorithm> +#include <iterator> // remove it (it is here to help with debugging) + + + +//#include <boost/cstdint.hpp> +//#include <stdint.h> +#include <boost/lexical_cast.hpp> +#include "GaudiKernel/IConversionSvc.h" +#include "AthenaKernel/getMessageSvc.h" +#include "SGTools/DataBucketBase.h" + + +#include "TrigNavigation/TriggerElement.h" + +#include "TrigConfHLTData/HLTUtils.h" + +#include "TrigNavigation/TrigEDMSizes.h" +#include "TrigNavigation/RoICacheHistory.h" + +#include "TrigSerializeCnvSvc/TrigStreamAddress.h" +#include "TrigSerializeResult/StringSerializer.h" + + +#include "TrigNavigation/NavigationCore.h" + + +//#define MLOG(x) if (m_log->level()<=MSG::x+m_msgLvlOffset) *m_log << (m_msgLvlOffset+MSG::x) +#define MLOG(x) if (m_log->level()<=MSG::x) *m_log << MSG::x + +using namespace HLT; +using namespace HLTNavDetails; + + +template<typename T> +std::ostream& operator<<( std::ostream& s, const std::vector<T>& v) +{ + s<< "[";for(auto i:v){s << i << ", ";} s << "]"; + return s; +} + + + + +std::string NavigationCore::m_unspecifiedLabel = ""; +const TriggerElement* NavigationCore::m_unspecifiedTE = 0; + + + +NavigationCore::NavigationCore() + : TrigNavStructure(), m_log(0), m_serializerSvc("TrigSerializeCnvSvc","NavigationCore"), + m_storeGate(0), + //m_serializeSpaceLimit(8000000), + m_objectsKeyPrefix("HLT"), + m_objectsIndexOffset(0), + m_referenceAllClasses(true) { + + m_log = new MsgStream(Athena::getMessageSvc(), "NavigationCore"); + + m_stringSerializer = new StringSerializer(); +} + +NavigationCore::~NavigationCore() { + + + MLOG(VERBOSE) << "~NavigationCore: cleaning static type information" << endreq; + { + HLT::TypeMaps::CLIDtoTypeProxyMap::iterator it; + for ( it = HLT::TypeMaps::proxies().begin(); it != HLT::TypeMaps::proxies().end(); ++it ) { + delete it->second; it->second = 0; + } + HLT::TypeMaps::proxies().clear(); + } + { + HLT::TypeMaps::CLIDtoHolderMap::iterator it; + for ( it = HLT::TypeMaps::holders().begin(); it != HLT::TypeMaps::holders().end(); ++it ) { + delete it->second; it->second = 0; + } + HLT::TypeMaps::holders().clear(); + } + + delete m_stringSerializer; + delete m_log; +} + + + + + + +/***************************************************************************** + * + * PREATY PRINTING + * + *****************************************************************************/ + +MsgStream& HLT::operator<< ( MsgStream& m, const NavigationCore& nav ) { + std::string str; + nav.printASCIIArt(str); + + m << str; + return m; +} + + +bool NavigationCore::addBlob(std::vector<uint32_t>& output, + const std::vector<uint32_t>& blob1, + const std::vector<uint32_t>& blob2) const { + output.push_back(blob1.size()+blob2.size()); + output.insert(output.end(), blob1.begin(), blob1.end()); + output.insert(output.end(), blob2.begin(), blob2.end()); + // copy(blob.begin(), blob.end(), std::ostream_iterator<int>(std::cerr, " A ")); + // std::cerr << std::endl; + return true; +} + + +bool NavigationCore::extractBlob(const std::vector<uint32_t>& input, std::vector<uint32_t>::const_iterator& it, std::vector<uint32_t>& blob) const { + blob.clear(); + if ( it == input.end() ) + return false; + + unsigned sizeOfBlob = *it; + // MLOG(DEBUG) << "blob size is: " << sizeOfBlob << endreq; + std::vector<uint32_t>::const_iterator begin = it; + ++begin; + std::vector<uint32_t>::const_iterator end = it; + ++end; + advance(end, sizeOfBlob); + + if ( end <= input.end()) { + blob.reserve(end-begin); + blob.insert(blob.end(), begin, end); + // copy(blob.begin(), blob.end(), std::ostream_iterator<int>(std::cerr, " X ")); + // std::cerr << std::endl; + it = end; // update iterator + return true; + } + return false; // failed to get blob +} + +bool doSingleHolderSerialization(std::vector<uint32_t>& headerBlob, std::vector<uint32_t>& dataBlob, HLTNavDetails::IHolder* holder, const ServiceHandle<IConversionSvc>& serializerSvc, bool dataSerialization ) { + holder->serialize( headerBlob ); + + if (dataSerialization) { + DataObject* dobj = holder->getDataObject(); + TrigStreamAddress* addr(0); + if ( serializerSvc->createRep(dobj, *pp_cast<IOpaqueAddress>(&addr) ).isSuccess() ) { + REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"NavigationCore") << "serialization of feature (object) successful, blob size: " << addr->get().size(); + dataBlob.push_back(addr->get().size()); + dataBlob.insert(dataBlob.end(), addr->get().begin(), addr->get().end()); + // above should be optimized (need to know if in case of failed serialization addr->get() contains empty data vector) + } + else{ + REPORT_MESSAGE_WITH_CONTEXT(MSG::ERROR,"NavigationCore") << "Container serialization Failure" << endreq; + return false; + } + //dobj->addRef(); + DataBucketBase* dobjBase = static_cast<DataBucketBase*>(dobj); + if ( dobjBase ) { + dobjBase->relinquish(); + REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"NavigationCore") << "serialization giving up the ownership"; + } + delete dobj; + delete addr; + + DataObject* dobjaux = holder->getAuxDataObject(); + TrigStreamAddress* auxaddr(0); + if(dobjaux){ + REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"NavigationCore") << "AuxStore serialization" << endreq; + if(serializerSvc->createRep(dobjaux,*pp_cast<IOpaqueAddress>(&auxaddr) ).isSuccess() ){ + REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"NavigationCore") << "aux conversion success! aux blob has size: " << auxaddr->get().size(); + dataBlob.push_back(auxaddr->get().size()); + dataBlob.insert(dataBlob.end(), auxaddr->get().begin(), auxaddr->get().end()); + } + else{ + REPORT_MESSAGE_WITH_CONTEXT(MSG::ERROR,"NavigationCore") << "AuxStore serialization Failure" << endreq; + return false; + } + DataBucketBase* dobjBaseAux = static_cast<DataBucketBase*>(dobjaux); + if ( dobjBaseAux ) { + dobjBaseAux->relinquish(); + REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"NavigationCore") << "serialization giving up the ownership of Aux"; + } + delete dobjaux; + delete auxaddr; + } + } + + REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"NavigationCore") << "finished serializing dumping blobs. header size: " + << headerBlob.size() << " data size: " << dataBlob.size(); + // std::cout << "[";for(auto i:headerBlob){std::cout << i << ", ";} std::cout << "]" << std::endl; + // std::cout << "[";for(auto i:dataBlob){std::cout << i << ", ";} std::cout << "]" << std::endl; + + return true; +} + +bool doSingleHolderDeserialization(const std::vector<uint32_t>& dataBlob, HLTNavDetails::IHolder* holder, const ServiceHandle<IConversionSvc>& serializerSvc, StoreGateSvc* /*storegate*/, const std::string& sgkey, CLID clid, int version){ + REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"NavigationCore") << "deserializing a data blob of size " << dataBlob.size() << " navi version is " << version; + + typedef std::vector<uint32_t>::const_iterator it_type; + it_type it = std::begin(dataBlob); + + if(!dataBlob.size()) return false; + + + std::vector<uint32_t> first; + std::vector<uint32_t> second; + + if(version == 4){ + auto firstsize = *(it++); + REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"NavigationCore") << "first part has size: " << firstsize; + + first = std::vector<uint32_t>(it,it+firstsize); + + std::advance(it,firstsize); + + if(!(it!=dataBlob.end())){ + REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"NavigationCore") << "this datablob only has a first part (non xAOD case)"; + } + else{ + auto secondsize = *(it++); + REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"NavigationCore") << "second part has size: " << secondsize; + second = std::vector<uint32_t>(it,it+secondsize); + } + } + else{ + first = std::vector<uint32_t>(dataBlob.begin(),dataBlob.end()); + } + + TrigStreamAddress addr(clid, sgkey, "", 0, 0); + addr.add(first); + DataObject* dobj(0); + + if (serializerSvc->createObj((IOpaqueAddress*)&addr, dobj).isFailure() ){ + REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING,"NavigationCore") << "deserialize main: failed" << std::endl; + return false; + } + + bool setcontainer = holder->setDataObject(dobj); + if(!setcontainer) return false; + + DataObject* dobjaux(0); + if(!second.empty()){ + std::string sgkeyaux = sgkey+"Aux."; + REPORT_MESSAGE_WITH_CONTEXT(MSG::VERBOSE,"NavigationCore") << "aux clid was deduced to be: " << holder->auxClidOrZero(); + TrigStreamAddress auxaddr(holder->auxClidOrZero(), sgkeyaux, "", 0, 0); + auxaddr.add(second); + + if (serializerSvc->createObj((IOpaqueAddress*)&auxaddr, dobjaux).isFailure() ){ + REPORT_MESSAGE_WITH_CONTEXT(MSG::WARNING,"NavigationCore") << "Aux Store deserialization failed"; + return false; + } + bool setaux = holder->setAuxDataObject(dobjaux); + if(!setaux) return false; + } + + + + return true; +} + + +bool NavigationCore::serialize( std::vector<uint32_t>& output, std::vector<unsigned int>& cuts ) const { + std::vector<std::pair<CLID, std::string> > clid_name; + clid_name.clear(); + return serialize(output, cuts, clid_name); +} + +bool NavigationCore::serialize( std::vector<uint32_t>& output, std::vector<unsigned int>& cuts, std::vector<std::pair<CLID, std::string> >& clid_name ) const { + + const std::vector<TriggerElement*>& fullList = m_factory.listOfProduced(); + std::vector<TriggerElement*> all; + for(std::vector<TriggerElement*>::const_iterator iter = fullList.begin(); iter != fullList.end(); ++iter) { + if(! (*iter)->transient() ) { + all.push_back( *iter ); + } + } + + cuts.clear(); + clid_name.clear(); + + // version + unsigned int version=4; + output.push_back(version); + + MLOG(DEBUG) << "NavigationCore::serialize: serializing with version " << version << endreq; + + unsigned int totalSizeIndex = output.size(); + output.push_back(0); // reserve one word (accessible under the index totalSize), it is 0 if there was truncation here + // and != output.size() if truncation using cuts + + cuts.push_back(output.size()); // mark a cut place + + unsigned int endSizeIndex = output.size(); + output.push_back(0); // reserve one word (accessible under the index startSize) + + + // reserve space (in order to be efficient it should not be resized any more, this can be studied probably later to find optimum) + output.reserve(10*all.size()); + + // SERIALZE NAVIGATION STRUCTURE + // size (measured in elements) + output.push_back(all.size()); + + // helper keys + std::map<TriggerElement*, uint16_t> keys; + + const TriggerElement* previous = 0; + std::vector<TriggerElement*>::const_iterator it; + uint16_t indexForTe = 0; + for ( it = all.begin(); it != all.end(); ++it ) { + // first we stream pointer as it (this is already an unique key for this TE) + // output.push_back((unsigned int)(*it)); + (*it)->serialize(output, keys, previous); + previous = *it; + keys[*it] = indexForTe; + indexForTe++; + } + unsigned int endSize = output.size(); + + MLOG(DEBUG) << "serialize: Sizes start: " << endSizeIndex << " end: " << endSize << + " TEs: " << m_factory.listOfProduced().size() << endreq; + output[endSizeIndex] = endSize; // one can use it for cutting out all features + + cuts.push_back(output.size()); // mark a cut place + + + // SERIALIZE FEATURES + std::vector<uint32_t> headerBlob; + std::vector<uint32_t> dataBlob; + + + if ( m_classesToPayload.empty() ) { // this is offline case + FeaturesStructureLabelIndexed::const_iterator clidIt; + for ( clidIt = m_featuresByLabel.begin(); clidIt != m_featuresByLabel.end(); ++clidIt ) { + std::map<std::string, IHolder*>::const_iterator holderIt; + for ( holderIt = clidIt->second.begin(); holderIt != clidIt->second.end(); ++holderIt ) { + + MLOG(DEBUG) << "serialization of featue attempting : " << clidIt->first << " " << holderIt->first << endreq; + + IHolder *holder = holderIt->second; + if ( ! holder ) { + MLOG(DEBUG) << "serialization of feature skipped, nothing know on this objects" << endreq; + continue; + } + MLOG(DEBUG) << "serialization of feature: " << holder->typeClid() << " label: " << holder->label() + << " size of payload: " << output.size() << endreq; + + headerBlob.clear(); + dataBlob.clear(); + bool status = doSingleHolderSerialization(headerBlob, dataBlob, holder, m_serializerSvc, false ); + addBlob( output, headerBlob, dataBlob ); + clid_name.push_back(std::pair < CLID, std::string> (holder->typeClid(), holder->label())); + cuts.push_back(output.size()); // mark truncation point + MLOG(DEBUG) << "serialization of feature: " << holder->typeClid() << " label: " << holder->label() + << " size of blob: " << headerBlob.size()+dataBlob.size() << " done with status: " << status << endreq; + } + } + } else { // this is online case when list of classes to payload is not empty + // prepare sizes object + // + std::string name_TrigEDMSizes("TrigEDMSizes"); + + // check if SG contains a previously registered TrigEDMSizes object + // reuse it and update it + // this is an issue when running L2 and EF together in athena + TrigEDMSizes* sizes(0); + if ( m_storeGate->transientContains(ClassID_traits<HLT::TrigEDMSizes>::ID(), name_TrigEDMSizes) ) { + MLOG(DEBUG) << "A previously registered object of type = (HLT::TrigEDMSizes) and name = " << name_TrigEDMSizes << " was found in SG." << endreq; + const TrigEDMSizes* sizesSG(0) ; + if ( m_storeGate->retrieve(sizesSG, name_TrigEDMSizes).isFailure() ) { + MLOG(WARNING) << "There was an error when retrieving the old object of type = (HLT::TrigEDMSizes) and name = " << name_TrigEDMSizes << " from SG." << endreq; + } else { + sizes = const_cast<TrigEDMSizes*>(sizesSG); + } + } else { + if ( m_storeGate->contains(ClassID_traits<HLT::TrigEDMSizes>::ID(), name_TrigEDMSizes) ) { + MLOG(DEBUG) << "An object of type = (HLT::TrigEDMSizes) and name = " << name_TrigEDMSizes << " accessible through SG was found." << endreq; + const TrigEDMSizes* sizesSG(0) ; + if ( m_storeGate->retrieve(sizesSG, name_TrigEDMSizes).isFailure() ) { + MLOG(WARNING) << "There was an error when retrieving the object contained in SG of type = (HLT::TrigEDMSizes) and name = " << name_TrigEDMSizes << "." << endreq; + } else { + sizes = const_cast<TrigEDMSizes*>(sizesSG); + } + } else { + sizes = new TrigEDMSizes(); + m_storeGate->record(sizes, name_TrigEDMSizes).setChecked(); // + MLOG(DEBUG) << "A new object of type = (HLT::TrigEDMSizes) and name = " << name_TrigEDMSizes << " was registered in SG." << endreq; + } + } + + MLOG(DEBUG) << "serialization: number of classes to payload: " << m_classesToPayload.size() << endreq; + + std::vector<std::pair<CLID, std::string> >::const_iterator cl; + for ( cl = m_classesToPayload.begin(); cl != m_classesToPayload.end(); ++cl ) { + CLID clid = cl->first; + std::string key = cl->second; + MLOG(DEBUG) << "serialization (ordered) of featue attempting : " << clid << " " << key << endreq; + FeaturesStructureLabelIndexed::const_iterator clidIt = m_featuresByLabel.find(clid); + if ( clidIt != m_featuresByLabel.end() ) { + std::map<std::string, IHolder*>::const_iterator holderIt = clidIt->second.find(key); + if ( holderIt != clidIt->second.end() ) { + IHolder *holder = holderIt->second; + if ( ! holder ) { + MLOG(DEBUG) << "serialization (ordered) of feature skipped, nothing know on this objects" << endreq; + continue; + } + MLOG(DEBUG) << "serialization (ordered) of feature: " << holder->typeClid() << " label: " << holder->label() + << " size of payload: " << output.size() << endreq; + headerBlob.clear(); + dataBlob.clear(); + bool status = doSingleHolderSerialization(headerBlob, dataBlob, holder, m_serializerSvc, true ); + addBlob( output, headerBlob, dataBlob ); + clid_name.push_back(std::pair < CLID, std::string> (holder->typeClid(), holder->label())); + cuts.push_back(output.size()); // mark truncation point + MLOG(DEBUG) << "serialization of feature: " << holder->typeClid() << " label: " << holder->label() + << " size of blob: " << headerBlob.size()+dataBlob.size() << " done with status: " << status << endreq; + if (sizes) sizes->addObject(holder->collectionName(), holder->label(), dataBlob.size(), output.size() ); + } + } + } + } + + MLOG(DEBUG) << "serialization done" << endreq; + + output[totalSizeIndex] = output.size(); + return true; +} + +bool NavigationCore::serialize_DSonly( std::vector<uint32_t>& output, std::vector<unsigned int>& cuts, std::vector<std::pair<CLID, std::string> >& clid_name ) const { + + cuts.clear(); + clid_name.clear(); + + cuts.push_back(output.size()); // mark a cut place + + std::vector<uint32_t> headerBlob; + std::vector<uint32_t> dataBlob; + + std::vector<std::pair<CLID, std::string> >::const_iterator cl_DS; + for ( cl_DS = m_classesToPayload_DSonly.begin(); cl_DS != m_classesToPayload_DSonly.end(); ++cl_DS ) { + CLID clid = cl_DS->first; + std::string key = cl_DS->second; + MLOG(DEBUG) << "serialization (ordered) of feature attempting : " << clid << " " << key << endreq; + FeaturesStructureLabelIndexed::const_iterator clidIt = m_featuresByLabel.find(clid); + if ( clidIt != m_featuresByLabel.end() ) { + std::map<std::string, IHolder*>::const_iterator holderIt = clidIt->second.find(key); + if ( holderIt != clidIt->second.end() ) { + IHolder *holder = holderIt->second; + if ( ! holder ) { + MLOG(DEBUG) << "serialization (ordered) of feature skipped, nothing know on this objects" << endreq; + continue; + } + MLOG(DEBUG) << "serialization (ordered) of feature: " << holder->typeClid() << " label: " << holder->label() + << " size of payload: " << output.size() << endreq; + headerBlob.clear(); + dataBlob.clear(); + bool status = doSingleHolderSerialization(headerBlob, dataBlob, holder, m_serializerSvc, true ); + addBlob( output, headerBlob, dataBlob ); + clid_name.push_back(std::pair < CLID, std::string> (holder->typeClid(), holder->label())); + cuts.push_back(output.size()); // mark truncation point + MLOG(DEBUG) << "serialization of feature: " << holder->typeClid() << " label: " << holder->label() + << " size of blob: " << headerBlob.size()+dataBlob.size() << " done with status: " << status << endreq; + //if (sizes) sizes->addObject(holder->collectionName(), holder->label(), dataBlob.size(), output.size() ); + } + } + } + return true; +} + + +/***************************************************************************** + * + * DESERIALIZATION + * + *****************************************************************************/ + +bool NavigationCore::deserialize( const std::vector<uint32_t>& input ) { + using namespace std; + std::vector<uint32_t>::const_iterator inputIt = input.begin(); + + if (input.size()==0) { + MLOG(WARNING) << "Cannot work on empty payload" << endreq; + return false; + } + unsigned int version = *inputIt++; // ignore version + + MLOG(DEBUG) << "deserialize: the serialized input has versions " << version << endreq; + + + if ( version != 3 and version !=4 ) { + MLOG(WARNING) << "No backward compatibility beyond version 3 possible; data was serialized with V: " << version + << " while we are in version 4" << endreq; + return true; + } + // version += 0; // this is to shut up gcc + MLOG(DEBUG) << "deserialize: deserialization of Navigation version: " << version << endreq; + + unsigned int totalSize = *inputIt++; // total size + if ( totalSize != input.size() ) + MLOG(WARNING) << "deserialize: the navigation is truncated: " << input.size() + << " while should be: " << totalSize << endreq; + + if ( input.size() == 2 ) { // there was only space for version and size + MLOG(WARNING) << "deserialize: the navigation is truncated badly, no recovery possible " << endreq; + return false; + } + + unsigned int endOfChunk = *inputIt++; // size of the chunk + // std::cerr << "Deserialization ot the chunk: " << endOfChunk << std::endl; + + unsigned int size = *inputIt++; + MLOG(DEBUG) << "deserialize: Number of TEs: " << size << endreq; + TriggerElement* previous = 0; + std::map<uint16_t, TriggerElement* > keys; + + for ( unsigned int i = 0; i < size; ++i ) { + + // create new TE + + TriggerElement* te = m_factory.produce(TriggerElement::enquireId(inputIt)); // + te->deserialize(inputIt, keys, previous); + previous = te; + // keys table for deserialization of other TEs + keys[i] = te; + + } + + if ( not m_factory.empty() ) { + + // rebuild sameRoI relations (this can't be done by TEs deserialization) + TriggerElement* initialNode = getInitialNode(); + std::vector<TriggerElement*>::const_iterator roiTEit; + for ( roiTEit = getDirectSuccessors(initialNode).begin(); + roiTEit != getDirectSuccessors(initialNode).end(); ++roiTEit ) { + fillSameRoIRelation((*roiTEit), (*roiTEit)); + } + } else { + MLOG(INFO) << "deserialize: the navigation TEs structure is empty, initial Node is missing" << endreq; + return false; + } + + + // EOF TEs deserialization + // deserialize Features + std::vector<uint32_t>::const_iterator it=input.begin(); + advance(it, endOfChunk ); + std::vector<uint32_t> blob; + while ( extractBlob(input, it, blob) ) { + + CLID clid; + uint16_t idx; + std::string label; + // IHolder::SerializationMethod sm; + std::vector<uint32_t>::const_iterator blobIt= blob.begin(); + + IHolder::enquireSerialized(blob, blobIt, clid, label, idx); + MLOG(VERBOSE) << "deserialize: extracted blob CLID: " << clid << " of size: " << blob.size() + << " SubTypeIndex: " << idx << " Label: " << label << endreq; + + + IHolder *holder(0); + if (! createHolder(holder, clid, label, idx) ) { + MLOG(ERROR) << "deserialize: Could not create holder for CLID " << clid + << " this probably means that the package holding the class for this CLID was not compiled against the TrigNavigation package in use!" + << endreq; + continue; + //return false; + } + + registerHolder(holder); // ??? check status + + // now we have the blobIt pointing to the place where objects may start + // if so we ought to do deserialization + if ( blob.end() != blobIt ) { + if ( m_storeGate->transientContains(holder->containerClid(), holder->key()) ) { + + MLOG(DEBUG) << "deserialize: while working on: " << holder->collectionName() + << " and key: " << holder->key() + << " from serialized form found it in SG already, OK if running transient BS job, SG has priority" << endreq; + + // remove obj from SG + holder->syncWithSG(); + holder->clearSG(); + } + + { + std::vector<uint32_t>::const_iterator constEnd = blob.end(); + std::vector<uint32_t> blobpart2(blobIt, constEnd); + // std::vector<uint32_t>::const_iterator bit; + + // for ( bit = blobIt; bit != blob.end(); ++it ) { + // blobpart2.push_back(*bit); + // } + MLOG(DEBUG) << "deserialize: going to deserialize clid: " << clid << " from its collection: " + << holder->containerClid() << endreq; + + if (holder->containerClid()<1) + MLOG(WARNING) << "deserialize: cannot map to a collection type by holder->containerClid()" << endreq; + + doSingleHolderDeserialization(blobpart2,holder,m_serializerSvc,m_storeGate,holder->key(),holder->containerClid(),version); + } + if ( !holder->syncWithSG() ) { + MLOG(WARNING) << "deserialize: after deserialization obejct not accessible though SG" << endreq; + } + } + + + } + return true; +} + + + + + + + + + + + + + + + + + + + + + + +bool NavigationCore::merge(const NavigationCore& l2) { + // we need to pick the holders which are at L2 and move them to EF + FeaturesStructureLabelIndexed::const_iterator clidIt; + + for ( clidIt = l2.m_featuresByLabel.begin(); clidIt != l2.m_featuresByLabel.end(); ++clidIt ) { + CLID c = clidIt->first; + std::map<std::string, IHolder*>::const_iterator labelIt; + for ( labelIt = clidIt->second.begin(); labelIt != clidIt->second.end(); ++labelIt ) { + IHolder *l2holder = labelIt->second; + if ( m_log->level()<=MSG::DEBUG ) + *m_log << MSG::DEBUG << "will add holder " << *l2holder << endreq; + std::string label(l2holder->label()); + IHolder* efholder = getHolder(c, label); + if ( efholder != 0 ) { + if ( (efholder->label() != l2holder->label()) + || (efholder->subTypeIndex() != l2holder->subTypeIndex()) ) { + + if ( m_log->level()<=MSG::DEBUG ) + *m_log << MSG::DEBUG << "fixing bug for " << *efholder << endreq; + // bug which we need to fix (some week of data in autumn 2008) + // we have to delete current holder + // and replace it by L2 one + // + // efholder->setSubTypeIndex(l2holder->subTypeIndex()); + + if ( m_log->level()<=MSG::DEBUG ) + *m_log << MSG::DEBUG << "after fixing " << *efholder << endreq; + } + } else { + if ( m_log->level()<=MSG::DEBUG ) + *m_log << MSG::DEBUG << "cloning the holder from L2 " << *l2holder << endreq; + efholder = HLT::TypeMaps::holders()[c]->clone(l2holder->label(), l2holder->subTypeIndex()); + efholder->prepare(m_log, m_storeGate); + registerHolder(efholder); + } + } // over labels + } // over CLIDS + return true; +} + + + + + + + + + +/***************************************************************************** + * + * very important RESET + * + *****************************************************************************/ +void NavigationCore::reset() { + TrigNavStructure::reset(); + + // clear structure after previous event + FeaturesStructure::iterator featuresIt; + for ( featuresIt = m_featuresByIndex.begin(); featuresIt != m_featuresByIndex.end(); ++featuresIt ) { + + std::map<uint16_t, IHolder*>::iterator subTypeIt; + for ( subTypeIt = featuresIt->second.begin(); subTypeIt != featuresIt->second.end(); ++subTypeIt ) { + if ( m_log->level()<=MSG::DEBUG ) + *m_log << MSG::DEBUG << "Deleting holder for clid:" << featuresIt->first << " and sub type idx " << subTypeIt->first << endreq; + // m_log*(subTypeIt->second) << endreq; + delete subTypeIt->second; + subTypeIt->second = 0; + } + // featuresIt->second.clear(); + } + m_featuresByIndex.clear(); + m_featuresByLabel.clear(); + if ( m_log->level()<=MSG::DEBUG ) + *m_log << MSG::DEBUG << "Navigation reset done" << endreq; +} + +uint16_t NavigationCore::nextSubTypeIndex(CLID clid, const std::string& /*label*/) { + // this is tricky (we need to find next free slot (subTypeIndex) + // For that we look at the last registered holder in the map indexed by type + + // label actually does not matter here + // + if ( m_featuresByIndex[clid].size() == 0 ) + return m_objectsIndexOffset; + return (--m_featuresByIndex[clid].end())->first+1; +} + + + +HLTNavDetails::IHolder* NavigationCore::prepareOneHolder(CLID clid, const std::string& label) { + + MLOG( VERBOSE ) << "NavigationCore::prepare preregistering objects of clid: " << clid << " label: " << label << endreq; + IHolder *holder = getHolder(clid, label); + if ( holder ) { + MLOG( VERBOSE ) << "NavigationCore::prepare preregistering objects not executed as it already exists " << *holder << endreq; + return holder; + } + + uint16_t index = nextSubTypeIndex(clid, label); + if ( m_log->level() <= MSG::DEBUG ) + MLOG( VERBOSE ) << "NavigationCore::prepare creating handler for type (CLID): " << clid + << " label: " << label << " index: " << index << endreq; + + if ( !createHolder(holder, clid, label, index) ) { + MLOG( INFO ) << "NavigationCore::prepare Can't create storage for objects of CLID: " << clid << " as it is requested by configuration" << endreq; + return 0; + } + + MLOG( VERBOSE ) << "Holder created, registering " << holder << " " << *holder << endreq; + + if ( !registerHolder(holder) ) { + MLOG( WARNING ) << "Holder registration failed " << holder << " " << *holder << endreq; + return 0; + } + if ( !holder->syncWithSG() ) { + MLOG( WARNING ) << "Holder SG sync failed" << holder << " " << *holder << endreq; + return 0; + } + + return holder; +} + +void NavigationCore::prepare() { + + if ( m_log->level()<=MSG::DEBUG ) { + HLT::TypeMaps::CLIDtoHolderMap::const_iterator hIt; + for ( hIt = HLT::TypeMaps::holders().begin(); hIt != HLT::TypeMaps::holders().end(); ++hIt ) { + MLOG( VERBOSE ) << "NavigationCore::prepare Compile time known types : " << *(hIt->second) << endreq; + } + } + + MLOG( VERBOSE ) << "NavigationCore::prepare Preregistering objects #:" << m_classesToPreregister.size()<< endreq; + // populate structure with "must have" features + + std::vector<std::pair<CLID, std::string> >::const_iterator confIt; + for ( confIt = m_classesToPreregister.begin(); confIt != m_classesToPreregister.end() ; ++confIt ) { + CLID clid = confIt->first; + std::string label = confIt->second; + if ( prepareOneHolder(clid, label) == 0 ) { + MLOG( WARNING )<< "NavigationCore::prepare failed preparing the holder for CLID: " << clid << " and label " << label << endreq; + } + } + + MLOG( DEBUG )<< "NavigationCore::prepare Navigation structure prepared for next event" << endreq; +} + +bool NavigationCore::registerHolder(IHolder* holder) { + /* if ( syncWithSG ) + if ( ! holder->syncWithSG() ) { + *m_log << MSG::WARNING << "createHolder: super-container can't be recorded to SG for CLID:" << holder->typeClid() << " and label: " << holder->label() << " sub type index: " << holder->subTypeIndex() << endreq; + // return false; + } + */ + if ( m_featuresByLabel.count(holder->typeClid()) != 0 || m_featuresByIndex.count(holder->typeClid()) != 0 ) { + if (m_featuresByIndex[holder->typeClid()].count(holder->subTypeIndex()) != 0 + || m_featuresByLabel[holder->typeClid()].count(holder->label()) != 0 ) { + *m_log << MSG::WARNING << "registerHolder registration failing, there are already registered ones (in byIndex map): " + << m_featuresByIndex[holder->typeClid()].count(holder->subTypeIndex()) + << " OR (byLabel map): " << m_featuresByLabel[holder->typeClid()].count(holder->label()) << endreq; + return false; + } + } + + m_featuresByIndex[holder->typeClid()][holder->subTypeIndex()] = holder; + m_featuresByLabel[holder->typeClid()][holder->label()] = holder; + m_lookupLabels[holder->typeClid()][holder->subTypeIndex()] = holder->label(); + *m_log << MSG::DEBUG << "registerHolder for OK " << *holder << endreq; + return true; +} + + + +bool NavigationCore::createHolder( IHolder*& holder, CLID clid, const std::string& label, uint16_t index) { + if ( HLT::TypeMaps::holders().count(clid) == 0 ) { + if (m_log->level()<=MSG::ERROR) + *m_log << MSG::ERROR << "createHolder: holder can't be done, no predefined storage found for CLID: " << clid << endreq; + // throw std::runtime_error("Can not find predefined storage of clid: " + boost::lexical_cast<std::string>(clid) +" and label: " + label ); + return false; + } + + holder = HLT::TypeMaps::holders()[clid]->clone(label, index); + // holder->prepare(m_log, m_storeGate, getAux(label)); + holder->prepare(m_log, m_storeGate); + holder->setObjectsKeyPrefix(m_objectsKeyPrefix); + + if (m_log->level()<=MSG::DEBUG) + *m_log << MSG::DEBUG << "createHolder: holder prepared " << *holder << endreq; + + + return true; +} + + + + +IHolder* NavigationCore::getHolder(CLID clid, uint16_t subTypeIndex) const { + FeaturesStructure::const_iterator clidIt = m_featuresByIndex.find(clid); + if ( clidIt == m_featuresByIndex.end() ) + return 0; + std::map<uint16_t, IHolder*>::const_iterator indexIt = clidIt->second.find(subTypeIndex); + if ( indexIt == clidIt->second.end() ) { + return 0; + } + return indexIt->second; +} + +IHolder* NavigationCore::getHolder(CLID clid, const std::string& label) const { + FeaturesStructureLabelIndexed::const_iterator clidIt = m_featuresByLabel.find(clid); + if ( clidIt == m_featuresByLabel.end() ) + return 0; + std::map<std::string, IHolder*>::const_iterator labelIt = clidIt->second.find(label); + if ( labelIt == clidIt->second.end() ) { + return 0; + } + return labelIt->second; +} + +bool NavigationCore::toBePutToPayload(const HLTNavDetails::IHolder* holder) const { + std::string option = holder->typeName()+"#"+holder->key(); + //std::string option = holder->typeName(); + std::vector<std::string>::const_iterator it; + it = find(m_classesToPayloadProperty.begin(), m_classesToPayloadProperty.end(), option); + if (it != m_classesToPayloadProperty.end() ) + return true; + return false; +} + +void NavigationCore::tweakMsgLvl(int newOffset) { + // m_msgLvlOffset = newOffset; + m_log->setLevel(newOffset); +} + +void NavigationCore::testMsgService() const { + if (m_log) { + MLOG(DEBUG) << "MLOG printout" << endreq; + *m_log << MSG::FATAL << "MSG::FATAL" << MSG::FATAL << endreq; + *m_log << MSG::ERROR << "MSG::ERROR " << MSG::ERROR << endreq; + *m_log << MSG::WARNING << "MSG::WARNING " << MSG::WARNING << endreq; + *m_log << MSG::INFO << "MSG::INFO " << MSG::INFO << endreq; + *m_log << MSG::DEBUG << "MSG::DEBUG " << MSG::DEBUG << endreq; + *m_log << MSG::VERBOSE << "MSG::VERBOSE " << MSG::VERBOSE <<endreq; + *m_log << MSG::INFO << "MSG level()=" << m_log->level() << endreq; + } else { + std::cerr << "ERROR -> No MessageSvc available !" << std::endl; + } +} + + + +uint32_t NavigationCore::string2hash( const std::string& s, const std::string& category) { + return TrigConf::HLTUtils::string2hash(s, category); +} + +void NavigationCore::getAllOfType ( const std::string& id, std::vector< HLT::TriggerElement* >& output, + const bool activeOnly) const { + if ( id == "" ) + return getAll(output, activeOnly); + + return TrigNavStructure::getAllOfType( string2hash(id, "TE"), output, activeOnly); +} + + +/* +std::vector< std::string > +NavigationCore::getFeatureSGLabelAndPosition( std::string featureClassName, const TriggerElement* te, + const std::string& label) +{ + return getFeatureSGLabelAndPosition( HLT::TypeMaps::type2clid()[featureClassName], te, label); +} + +std::vector< std::string > +NavigationCore::getFeatureSGLabelAndPosition( unsigned int clid, const TriggerElement* te, + const std::string& label) +{ + std::vector< std::string > result; + + MLOG(DEBUG) << "got CLID: " << clid << endreq; + // now look into the TriggerElement to get from it AccessHelpers (look only at features reated to this TE) + // bool found = false; + std::vector< TriggerElement::FeatureAccessHelper >::const_iterator it; + for ( it = te->getFeatureAccessHelpers().begin(); it != te->getFeatureAccessHelpers().end(); ++it ) { + MLOG(DEBUG) << "got Feature ObjectIndex " << *it << endreq; + + if ( it->getCLID() == clid ) { // CLID is matching + // remember an index (in holder vector) + //uint16_t subTypeIndex = TriggerElement::ObjectIndex(it->getIndex()).subTypeIndex(); + + uint16_t subIndex = it->getIndex().subTypeIndex(); + + MLOG(DEBUG) << "found label = " << m_lookupLabels[clid][subIndex] << endreq; + + if ( label == m_lookupLabels[clid][subIndex] or label =="") { + // insert all entries: + for (unsigned int i = it->getIndex().objectsBegin(); + i < it->getIndex().objectsEnd(); ++i ) { + std::ostringstream ss; + ss << "HLT_" << m_lookupLabels[clid][subIndex] << "::" << i; + result.push_back( ss.str() ); + } + // found = true; + } + + } + } + return result; +} + +std::vector< std::string > +NavigationCore::getRecentFeatureSGLabelAndPosition( unsigned int clid, const TriggerElement* te, + const std::string& label) +{ + // start from given TriggerElement + std::vector< std::string > result = getFeatureSGLabelAndPosition(clid, te, label); + + if ( !result.empty() ) { + MLOG(DEBUG) << "getRecentFeatureSGLabelAndPosition: found one in: " << te->getId() << endreq; + return result; // end of our search + } + if ( isRoINode(te) ) { + return result; // do not search deeper + } else { // here the logic needed if the feature was not found attached to the current TE + std::vector<TriggerElement*>::const_iterator it; + for ( it = getDirectPredecessors(te).begin(); it != getDirectPredecessors(te).end(); ++it ) { + MLOG(DEBUG) << "getRecentFeatureSGLabelAndPosition: searching deeper in TE: " << (*it)->getId() << endreq; + + std::vector< std::string > result2 = getRecentFeatureSGLabelAndPosition(clid, *it, label ); + + if ( !result2.empty() ) + return result2; // found feature in subtree of one of the predecessors + } + } + return result; +} + +std::vector< std::string > +NavigationCore::getRecentFeatureSGLabelAndPosition( std::string featureClassName, const TriggerElement* te, + const std::string& label) +{ + return getRecentFeatureSGLabelAndPosition( type2clid()[featureClassName], te, label); +} + + + +std::vector< unsigned int > +NavigationCore::getFeatureContainerPosition( unsigned int clid, const TriggerElement* te, + const std::string& label) +{ + std::vector<unsigned int > result; + + MLOG(DEBUG) << "got CLID: " << clid << endreq; + // now look into the TriggerElement to get from it AccessHelpers (look only at features reated to this TE) + // bool found = false; + std::vector< TriggerElement::FeatureAccessHelper >::const_iterator it; + for ( it = te->getFeatureAccessHelpers().begin(); it != te->getFeatureAccessHelpers().end(); ++it ) { + MLOG(DEBUG) << "got Feature ObjectIndex " << *it << endreq; + + if ( it->getCLID() == clid ) { // CLID is matching + // remember an index (in holder vector) + //uint16_t subTypeIndex = TriggerElement::ObjectIndex(it->getIndex()).subTypeIndex(); + + uint16_t subIndex = it->getIndex().subTypeIndex(); + + MLOG(DEBUG) << "found label = " << m_lookupLabels[clid][subIndex] << endreq; + + if ( label == m_lookupLabels[clid][subIndex] ) { + // insert all entries: + for (unsigned int i = it->getIndex().objectsBegin(); + i < it->getIndex().objectsEnd(); ++i ) + result.push_back( i ); + // found = true; + } + + } + } + return result; +} + +std::vector< unsigned int > +NavigationCore::getFeatureContainerPosition( std::string typeName, const TriggerElement* te, + const std::string& label) +{ + return getFeatureContainerPosition(type2clid()[typeName], te, label); +} + + +std::vector< HLT::FeatureDescriptor > +NavigationCore::getFeatureContainerPosition( unsigned int clid, const TriggerElement* te) +{ + std::vector< HLT::FeatureDescriptor > result; + + MLOG(DEBUG) << "got CLID: " << clid << endreq; + // now look into the TriggerElement to get from it AccessHelpers (look only at features reated to this TE) + // bool found = false; + std::vector< TriggerElement::FeatureAccessHelper >::const_iterator it; + for ( it = te->getFeatureAccessHelpers().begin(); it != te->getFeatureAccessHelpers().end(); ++it ) { + MLOG(DEBUG) << "got Feature ObjectIndex " << *it << endreq; + + if ( it->getCLID() == clid ) { // CLID is matching + // remember an index (in holder vector) + //uint16_t subTypeIndex = TriggerElement::ObjectIndex(it->getIndex()).subTypeIndex(); + // unsigned int index = it->getIndex(); + uint16_t subIndex = it->getIndex().subTypeIndex( ); + std::string label( m_lookupLabels[clid][subIndex] ); + + MLOG(DEBUG) << "found label = " << label << endreq; + + result.push_back( FeatureDescriptor(label, it->getIndex().objectsBegin(), + it->getIndex().objectsEnd()) ); + // found = true; + + } + } + return result; +} + + +std::vector< HLT::FeatureDescriptor > +NavigationCore::getFeatureContainerPosition( std::string typeName, const TriggerElement* te) +{ + return getFeatureContainerPosition(type2clid()[typeName], te); +} + + +std::pair<std::string, std::string> NavigationCore::getClassContainerNames(unsigned int clid) const +{ + IHolder* h = getHolder(clid, 0); + if (h) { + return std::make_pair( h->typeName(), h->collectionName() ); + } else { + return std::make_pair( "", "" ); + } +} +*/ + +void NavigationCore::testStaticMaps() +{ + *m_log << MSG::INFO << "print statis map: CLID -> class name " << endreq; + for ( static HLT::TypeMaps::NametoCLIDMap::const_iterator it = HLT::TypeMaps::type2clid().begin(); + it != HLT::TypeMaps::type2clid().end(); ++it) { + *m_log << MSG::INFO << "entry: " << (*it).first << " -> " << (*it).second << endreq; + } + + *m_log << MSG::INFO << "print statis map: CLID -> holder " << endreq; + for ( static HLT::TypeMaps::CLIDtoHolderMap::const_iterator it = HLT::TypeMaps::holders().begin(); + it != HLT::TypeMaps::holders().end(); ++it) { + *m_log << MSG::INFO << "entry: " << (*it).first << " -> " << (* (*it).second) << endreq; + } + +} + +void NavigationCore::setAccessProxy(AccessProxy* ap) { + m_storeGate = ap; +} + +AccessProxy* NavigationCore::getAccessProxy() const { + return m_storeGate; +} + +void NavigationCore::setObjKeyPrefix(const std::string& k) { + m_objectsKeyPrefix = k; +} + +bool NavigationCore::getFeatureAccessors( const TriggerElement* te, CLID clid, const std::string& label, + bool only_single_feature, + TriggerElement::FeatureVec& features, + bool with_cache_recording, + bool travel_backward_recursively, + const TriggerElement*& source, + std::string& sourcelabel ) { + + MLOG(VERBOSE) << "getFeatureAccessors: looking for:" << (only_single_feature ? "one object" : "many objects" ) << " of CLID: " << clid + << " label: \"" << label << "\"" + << " starting from TE: " << te->getId() << (with_cache_recording ? " with cache recording" : " without cache recording")<< endreq; + // start cache + + //std::auto_ptr<HLT::RoICacheHistory::QuestionScope> qscope( with_cache_recording ? new : 0); + HLT::RoICacheHistory::QuestionScope qscope( with_cache_recording + ? HLT::RoICacheHistory::QuestionScope(te, clid, label, this, only_single_feature) + : HLT::RoICacheHistory::QuestionScope() ); + + // record ending point (not this method is called recursivelly) + + int size = te->getFeatureAccessHelpers().size(), it; + + // loop the feature access helper in order depending of type of request (i.e. if single featyure needed then loop from back, if all then loop from the front) + for ( it = ( only_single_feature ? size-1 : 0 ); it != (only_single_feature ? -1 : size ); only_single_feature ? it--: it++ ) { + //for ( it = 0; it < size; ++it ) { + const TriggerElement::FeatureAccessHelper& fea = te->getFeatureAccessHelpers().at(it); + MLOG(VERBOSE) << "getFeatureAccessors: in a loop over FeatureAccessHelpers got ObjectIndex " << fea << endreq; + + + if ( fea.getCLID() == clid ) { // CLID is matching + // remember an index (in holder vector) + TriggerElement::ObjectIndex objectIndex(fea.getIndex()); + HLTNavDetails::IHolder *holder = getHolder(clid, objectIndex.subTypeIndex()); + if (! holder ) { + MLOG(WARNING) << "getFeatureAccessors: feature of clid: " << clid << " and index: " << objectIndex.subTypeIndex() + << " not available. Probably not recorded. Navigation structure inconsistent. " << endreq; + continue; + } + + // now do labels matching + // "" (empty) label means all match + // "!" in the label means the collection having exactly empty label + // otherwise if label is provided it needs to match exactly + if (label.empty() || (label == "!" && holder->label().empty()) || label == holder->label() ) { + sourcelabel = holder->label(); + source = te; + features.push_back(fea); + if ( with_cache_recording ) HLT::RoICacheHistory::instance().addAnswer(te, fea); + + MLOG(DEBUG) << "getFeatureAccessors: matching feature found in te: " << *te << " index: " << fea << endreq; + // now the ending (depends on the "single" flag) + if ( only_single_feature ) + break; + } + } + } // end of loop over feature access helpers of this TE + + if ( ! travel_backward_recursively ) { + return true; + } + + // stop digging deeper if this is an RoI node already + if ( isRoINode(te) ) { + return true; + } + + // return if a feature(s) is/are found + if ( ! features.empty() ) { + return true; + } + + + // recurse deeper + + + // but recurse only when unambiguous + //if ( (label.empty() || only_single_feature ) && getDirectPredecessors(te).size() > 1 ) { + bool recursion_status = true; + for( TriggerElement* predecessor: getDirectPredecessors(te) ) { + + TriggerElement::FeatureVec features_in_branch; + recursion_status = recursion_status && getFeatureAccessors( predecessor, clid, label, only_single_feature, features_in_branch, + with_cache_recording, travel_backward_recursively, source, sourcelabel); + features.insert(features.end(), features_in_branch.begin(), features_in_branch.end()); + } + + if ( only_single_feature && ( features.size() > 1 || recursion_status == false) ) { + MLOG(DEBUG) << "getFeatureAccessors: looking for object of CLID: " << clid + << " label: \"" << label << "\"" << " found several objects matching criteria while can only return back one, this is ambiguous" << endreq; + + if ( getDirectPredecessors(te).size() > 1 ) // mark bifurcation point as to where one can start again + source = te; + + return false; + } + return true; +} + +#undef MLOG diff --git a/Trigger/TrigEvent/TrigNavigation/src/RoICacheHelper.cxx b/Trigger/TrigEvent/TrigNavigation/src/RoICacheHelper.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a7dd989f0c9bb92b5a6245fa489f7c08f3872742 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/src/RoICacheHelper.cxx @@ -0,0 +1,295 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TrigConfHLTData/HLTTriggerElement.h" +#include "TrigNavigation/Navigation.h" +#include "AthenaKernel/getMessageSvc.h" + +#include "TrigNavigation/RoICacheHelper.h" + +/***************************************************************************** + * + * CACHING + * + *****************************************************************************/ + + +using namespace HLT; +enum RoICacheHelper::CachingMode RoICacheHelper::s_cachingMode=RoICacheHelper::HistoryBased; + +bool RoICacheHelper::cache ( TriggerElement* te ) { + std::vector<struct CacheEntry>::iterator it; + + // look into cache entries for cache holding same RoI + it = find(m_caches.begin(), m_caches.end(), te); // we have overloaded operator== + + // nothing found, we run on this RoI for the first time (while we shouldn't) + if ( m_caches.end() == it ) { // we need to start up new cache but we can't do so here + return false; + } else { + if ( it->holder() == 0 ) { + return false; + } + // do caching + // real caching happens here + //std::vector< TriggerElement::FeatureAccessHelper >::const_iterator b = it->holder()->getFeatureAccessHelpers().begin(); + // advance(b, it->begin()); + + // std::vector< TriggerElement::FeatureAccessHelper >::const_iterator e = it->holder()->getFeatureAccessHelpers().begin(); + // advance(e, it->end()); + + // std::cerr << "caching now: " << it->begin() << " " << it->end() << std::endl; + const TriggerElement::FeatureVec& fvec = it->holder()->getFeatureAccessHelpers(); + + if ( fvec.size() < it->end() || it->begin() > it->end() ) { + return false; + } + + for ( unsigned int i = it->begin() ; i < it->end(); i++ ) { + te->addFeature(it->holder()->getFeatureAccessHelpers()[i]); + } + // te->getFeatureAccessHelpers().insert(te->getFeatureAccessHelpers().end(), b, e); + // te->featuresKeyPrint().insert(te->featuresKeyPrint().end(), b, e); + // std::cerr << "after caching size: " << te->getFeatureAccessHelpers().size() << std::endl; + } + + return true; +} + + +bool RoICacheHelper::isInputAccepted ( const TriggerElement* te ) { + std::vector<struct CacheEntry>::iterator it; + it = find(m_caches.begin(), m_caches.end(), te); + if ( m_caches.end() != it ) { + if (it->holder()) + return true; + return false; + } + return false; +} + +bool RoICacheHelper::needsExecution ( const TriggerElement* te ) { + std::vector<struct CacheEntry>::iterator it; + it = find(m_caches.begin(), m_caches.end(), te); + if ( m_caches.end() == it ) { + m_caches.push_back( CacheEntry(te) ); + return true; + } + return false; +} + + +bool RoICacheHelper::startCaching( const TriggerElement* te ) { + // we have to start caching, last entry (back()) in m_caches is the right place to do that + if ( te != m_caches.back().holder() ) + return false; + + RoICacheHistory::instance().startHistory(te); + + m_caches.back().start( te->getFeatureAccessHelpers().size() ); + return true; +} + +bool RoICacheHelper::stopCaching( const TriggerElement* te ) { + // we have to save cache, last entry (back()) in m_caches is the started cache + CacheEntry &cache = m_caches.back(); + + if ( te != cache.holder() ) + return false; + + cache.add(RoICacheHistory::instance().getFeatureCalls()); + /* + // print the history + std::vector<RoICacheHistory::Question>::const_iterator histIt; + for ( histIt = RoICacheHistory::instance().getQuestions().begin(); histIt != RoICacheHistory::instance().getQuestions().end(); ++histIt ) { + std::cout << "Objects access HISTORY: label: " << histIt->label() + << " work: " << histIt->getWorkTE() << std::endl; + if (histIt->getAnswers().empty()) + std::cout << "Objects access HISTORY: got back nothing for clid: " << histIt->clid() << " and label " << histIt->label() << std::endl; + TriggerElement::FeatureVec::const_iterator feaIt; + for ( feaIt = histIt->getAnswers().begin(); feaIt != histIt->getAnswers().end(); ++feaIt ) { + const TriggerElement::FeatureAccessHelper& fea = *feaIt; + std::cout << "Objects access HISTORY: got back: " << fea << std::endl; + } + } + */ + RoICacheHistory::instance().stopHistory(); + + cache.finish( te->getFeatureAccessHelpers().size() ); + return true; +} + +void RoICacheHelper::reset() { + m_caches.clear(); +} + +/* +void printObjects(MsgStream* mlog, const TriggerElement* cache, const TriggerElement* te) { + if (mlog && mlog->level( ) <= MSG::DEBUG) { + std::string l1; + TrigConf::HLTTriggerElement::getLabel(te->getId(), l1); + std::string l2; + TrigConf::HLTTriggerElement::getLabel(cache->getId(), l2); + + (*mlog) << MSG::DEBUG << "found objects in querried TE: " << l1 << " in already executed (cache): " << l2 << endreq; + (*mlog) << MSG::DEBUG << "cache had : " <<cache->getPreviousFeatures().size() + << " while TE has: " << te->getPreviousFeatures().size() << endreq; + unsigned int i; + for ( i = 0 ; i < te->getPreviousFeatures().size(); ++i ) { + (*mlog) << MSG::DEBUG + << (te->getPreviousFeatures()[i] == cache->getPreviousFeatures()[i] ? "==": "!!") + << "this TE " << te->getPreviousFeatures()[i] << " in cache: " << cache->getPreviousFeatures()[i] + << endreq; + } + } +} +*/ +// cache entry methods + +bool RoICacheHelper::CacheEntry::operator== (const std::vector<TriggerElement*>& roite) const { + return m_rois == std::set<const TriggerElement*>(roite.begin(), roite.end()); +} +/* +void xx_print( MsgStream& log, const TriggerElement::FeatureVec& fe, const std::string& prefix) { + + TriggerElement::FeatureVec::const_iterator i; + for ( i = fe.begin(); i != fe.end(); ++i ) { + log << MSG::DEBUG << prefix << " " << *i << endreq; + } +} +*/ + +bool RoICacheHelper::CacheEntry::operator== (const TriggerElement* curr) const { + if (s_cachingMode == None) + return false; + + + // check if set of RoIs is identical + const std::vector<TriggerElement*> &tvec = TrigNavStructure::getRoINodes(curr); + if ( m_rois != std::set<const TriggerElement*>(tvec.begin(), tvec.end()) ) { + return false; + } + if ( s_cachingMode == RoIOnly ) + return true; + + // Strict check: use all features in previous TEs + if ( s_cachingMode == AllObjects ) { + if (curr->getPreviousFeatures().size() != m_cacheHolder->getPreviousFeatures().size() - (m_cacheHolder->getFeatureAccessHelpers().size() - begin()) ) { + return false; + } + + if ( std::equal(curr->getPreviousFeatures().begin(), curr->getPreviousFeatures().end(), + m_cacheHolder->getPreviousFeatures().begin()) ) { + return true; + } + + return false; + } + + // History based check + if ( s_cachingMode != HistoryBased ) + return false; + + // No history... no future + if(m_questions.empty()) { + // MsgStream log(Athena::getMessageSvc(), "RoICacheHelper"); + // log << MSG::DEBUG << "No history available in this RoI, algorithms did not request any objecrs, safer not to cache" << endreq; + return false; + } + + // The big loop below is repeating the same querries (getFeture(s) calls) + // as on RoI as were done originaly by the running algorithm. + // This querries were recorded together with answers. + // When repeated now, any divergence in answering the same questions is good reason to run algorithm again. + // When the loop goes to the end it means all the answers were identical as when we run for the first time. + // Then thre is no reason to run algorithm again and only objects should be reattached. + + + // Need navigation to answer questions + NavigationCore *navig = RoICacheHistory::instance().getNavigation(); + if(!navig) return false; + + const std::vector<TriggerElement*> &pvec = TrigNavStructure::getDirectPredecessors(curr); + + // Start of the loop over previoisly asked quiestions. + for(FeatureCallVec::const_iterator it = m_questions.begin(); it != m_questions.end(); ++it) { + if ( !it->isget() ) + continue; + + FeatureVec fvec; + + + if(it->getInitTE() == it->getWorkTE()) { + // History starts at the same TE (i.e. getFeature was called on outputTE in Fex) + // We ask again the same question (giving the same clid and label) + navig->getFeatureAccessors(curr, it->clid(), it->label(), it->issingle(), fvec, false, true); + } else if(pvec.size() == 1) { + // Check relationship at cached TE + const std::vector<TriggerElement*> &iwvec = TrigNavStructure::getDirectPredecessors(it->getWorkTE()); + if(iwvec.size() != 1 || iwvec[0] != it->getInitTE()) { + // Should never happen - answers always come from single pred. + return false; + } + + // History starts at the previous TE (i.e. getFeature was called on inputTE in Fex) + navig->getFeatureAccessors(pvec[0], it->clid(), it->label(), it->issingle(), fvec, false, true); + } else { + // Previous history not unique (i.e. the navigaiton tree was traversed in some custom way in Fex) + return false; + } + + // check if getFeature was called rather than getFeature*s* + if ( it->issingle()) { + + if( it->getAnswers().empty() ) { + // the answer in first case was empty - it means no feature was found + // It is fine if the answer was also empty this time. + if ( fvec.empty() ) { + continue; + } else { + // Else we need running. In first pass Fex could not get this object while now can. Clearly it would do different thing now. + return false; + } + } else { + if (fvec.empty()) + return false; // This is inverted situation, frist time we got answer, but not this case, again we need to to run. + + // Now we need to do fancy check + // In first pass and now we got some answers (features found) we need to check if they would be the same ... + // but not compleetly, i.e. only as many objects as were of interest first time (i.e. one) + if ( !std::equal(it->getAnswers().begin(), it->getAnswers().end(), fvec.begin()) ) { + return false; + // MsgStream log(Athena::getMessageSvc(), "RoICacheHelper"); + // log << MSG::DEBUG << "single history differs: " << fvec.size() << " " << it->getAnswers().size() << endreq; + // xx_print(log, fvec, "questions"); + // xx_print(log, it->getAnswers(), "in cache "); + } + } + } else { + // This is case for getFeature*s* (many features requested) + // First of all need to check if the number of objects is the same. + if( fvec.size() != it->getAnswers().size() ) { + // MsgStream log(Athena::getMessageSvc(), "RoICacheHelper"); + // log << MSG::DEBUG << "history sizes incompatible this time: " << fvec.size() << " " << it->getAnswers().size() << endreq; + // xx_print(log, fvec, "questions"); + // xx_print(log, it->getAnswers(), "in cache "); + return false; + } + + // if number of objects is the same we need to check if the answers (features) we obtain now woudl be the same as in first pass + if ( fvec != it->getAnswers() ) { + // MsgStream log(Athena::getMessageSvc(), "RoICacheHelper"); + // log << MSG::DEBUG << "history differs" << endreq; + // xx_print(log, fvec, "questions"); + // xx_print(log, it->getAnswers(), "in cache "); + return false; + } + } + + } + // MsgStream log(Athena::getMessageSvc(), "RoICacheHelper"); + // log << MSG::DEBUG << "history the same, yesss" << endreq; + + return true; +} diff --git a/Trigger/TrigEvent/TrigNavigation/src/RoICacheHistory.cxx b/Trigger/TrigEvent/TrigNavigation/src/RoICacheHistory.cxx new file mode 100644 index 0000000000000000000000000000000000000000..0c6d20c2da87bbfa3d4ab15057f6635a97dc2aab --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/src/RoICacheHistory.cxx @@ -0,0 +1,168 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include <stdexcept> +#include <boost/lexical_cast.hpp> + +#include "TrigNavigation/RoICacheHistory.h" + +//----------------------------------------------------------------------------- +HLT::RoICacheHistory& HLT::RoICacheHistory::instance() { + static RoICacheHistory instance; + return instance; +} + +//----------------------------------------------------------------------------- +void HLT::RoICacheHistory::addAnswer(const TriggerElement* te, const TriggerElement::FeatureAccessHelper &f) +{ + if ( m_collect ) { + if ( m_current.isValid() ) { + m_current.addAnswer(te, f); + } else { + throw std::runtime_error("HLT caching problem: " + boost::lexical_cast<std::string>(te->getId()) ); + } + } +} + +//----------------------------------------------------------------------------- +void HLT::RoICacheHistory::stopCurrentFeatureCall() +{ + if ( m_collect ) { + if ( ! m_current.isValid() ) { + throw std::runtime_error("HLT caching problem: invalid current question" ); + } else { + // std::cout << "RoICacheHistory stopping feature call: " << m_current.isget() << std::endl; + if ( !m_current.isget() ) { + m_questions.push_back(m_current); + } else { + // traverse back the questions + bool local = false; + for ( unsigned i = 0, j = m_questions.size(); i < j ; i++ ) { + // std::cout << "RoICacheHistory traversing back local history isget: " <<m_questions[i].isget() << std::endl; + if ( !m_questions[i].isget()) { + // std::cout << "RoICacheHistory encountered algo dooing attach before get" << std::endl; + if ( m_current.getAnswers() == m_questions[i].getAnswers()){ + local = true; + // std::cout << "RoICacheHistory algorithm asking for object which is creating itself, ignoring" << std::endl; + break; + } + } + } + if (!local) + m_questions.push_back(m_current); + } + m_current.reset(); + } + } else { + throw std::runtime_error("HLT caching problem: question not collected" ); + } +} + +//----------------------------------------------------------------------------- +void HLT::RoICacheHistory::setCurrentFeatureCall(const FeatureCall &curr, NavigationCore *navig) +{ + if(m_current.isValid()) { + throw std::runtime_error("HLT caching problem: current question is valid" ); + } else { + m_current = curr; + m_navigation = navig; + } +} + +//----------------------------------------------------------------------------- +HLT::RoICacheHistory::FeatureCall::FeatureCall(const TriggerElement* work, const TriggerElement* te, CLID clid, const std::string& label, bool issingle, bool isget) + :m_init(te), + m_work(work), + m_clid(clid), + m_label(label), + m_issingle(issingle), + m_isget(isget) { +} + +//----------------------------------------------------------------------------- +HLT::RoICacheHistory::FeatureCall::FeatureCall() + :m_init(0), + m_clid(0), + m_issingle(false), + m_isget(false) { +} + +//----------------------------------------------------------------------------- +void HLT::RoICacheHistory::FeatureCall::addAnswer(const TriggerElement* /*te*/, const TriggerElement::FeatureAccessHelper&f) +{ + m_answers.push_back(f); +} + +//----------------------------------------------------------------------------- +void HLT::RoICacheHistory::FeatureCall::reset() +{ + // Complete reset + m_init = 0; + m_label.clear(); + m_answers.clear(); +} + +//----------------------------------------------------------------------------- +bool HLT::RoICacheHistory::FeatureCall::isValid() const { + return m_init; +} + +HLT::RoICacheHistory::RememberAttachFeature::RememberAttachFeature(const TriggerElement* te, CLID clid, const std::string& label, + NavigationCore* navig, TriggerElement::ObjectIndex& idx) { + HLT::RoICacheHistory& roih = HLT::RoICacheHistory::instance(); + if(!roih.collectHistory()) return; + // std::cout << "RoICacheHistory recording also attach feature" << std::endl; + roih.setCurrentFeatureCall(HLT::RoICacheHistory::FeatureCall(roih.getWorkTE(), te, clid, label, true, false), navig); + roih.m_current.addAnswer(te, TriggerElement::FeatureAccessHelper(clid, idx)); + roih.stopCurrentFeatureCall(); +} + + +//----------------------------------------------------------------------------- +HLT::RoICacheHistory::QuestionScope::QuestionScope(const TriggerElement* te, + CLID clid, + const std::string& label, + NavigationCore *navig, bool issingle) + : m_start(te) +{ + HLT::RoICacheHistory& roih = HLT::RoICacheHistory::instance(); + + // Are we event collecting history? + if(!roih.collectHistory()) return; + + if(roih.getCurrentFeatureCall().isValid()) { + return; + } else { + // Create current question + roih.setCurrentFeatureCall(HLT::RoICacheHistory::FeatureCall(roih.getWorkTE(), te, clid, label, issingle, true), navig); + } +} + +HLT::RoICacheHistory::QuestionScope::QuestionScope() + : m_start(0) +{} + + +//----------------------------------------------------------------------------- +HLT::RoICacheHistory::QuestionScope::~QuestionScope() +{ + if ( !m_start ) + return; + + HLT::RoICacheHistory& roih = HLT::RoICacheHistory::instance(); + + // Are we event collecting history? + if(!roih.collectHistory()) return; + + // Alway see valid question + if(!roih.getCurrentFeatureCall().isValid()) { + throw std::runtime_error("HLT caching problem: logic error in history"); + } + + // Return out of scope for first call + if(roih.getCurrentFeatureCall().getInitTE() == m_start) { + roih.stopCurrentFeatureCall(); + } +} + diff --git a/Trigger/TrigEvent/TrigNavigation/src/TrigEDMSizes.cxx b/Trigger/TrigEvent/TrigNavigation/src/TrigEDMSizes.cxx new file mode 100644 index 0000000000000000000000000000000000000000..681237cab62215fc4020e0dcd7e3bed5aeb6967f --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/src/TrigEDMSizes.cxx @@ -0,0 +1,46 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TrigNavigation/TrigEDMSizes.h" + +#include <boost/foreach.hpp> + +using namespace HLT; +TrigEDMSizes::TrigEDMSizes(){} + + +TrigEDMSizes::EDMObjectInfo::EDMObjectInfo(const std::string& coll, const std::string& l, unsigned w, unsigned cut) + : collection(coll), label(l), words(w), cutsize(cut) +{} + +bool TrigEDMSizes::EDMObjectInfo::isTruncated(unsigned size_after_serialization) const { + if (cutsize > size_after_serialization) + return true; + return false; +} + +void TrigEDMSizes::addObject(const std::string& coll, const std::string& label, unsigned words, unsigned cutsize) { + m_objects.push_back(TrigEDMSizes::EDMObjectInfo(coll, label, words, cutsize)); +} + +const TrigEDMSizes::EDMEventInfo& TrigEDMSizes::info() const { + return m_objects; +} + +const TrigEDMSizes::EDMObjectInfo& TrigEDMSizes::lastNotTruncated(unsigned size_after_truncation) const { + bool foundTruncated = false; + bool foundNotTruncated = false; + + BOOST_REVERSE_FOREACH( const TrigEDMSizes::EDMObjectInfo& oi, m_objects) { + if ( foundTruncated && foundNotTruncated ) + return oi; + + if ( oi.isTruncated(size_after_truncation) ) { + foundTruncated = true; + } else { + foundNotTruncated = true; + } + } + return m_objects.front(); +} diff --git a/Trigger/TrigEvent/TrigNavigation/src/TrigFeatureLink.cxx b/Trigger/TrigEvent/TrigNavigation/src/TrigFeatureLink.cxx new file mode 100644 index 0000000000000000000000000000000000000000..0db0bff2eb49cccfddc0f0334a169569aec8360b --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/src/TrigFeatureLink.cxx @@ -0,0 +1,19 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TrigNavigation/TrigFeatureLink.h" + +TrigFeatureLink::TrigFeatureLink(CLID clid, uint16_t subtype, uint32_t index) + : m_clid(clid), + m_subTypeIndex(subtype), + m_index(index) +{} + +TrigFeatureLink::TrigFeatureLink() + : m_clid(0), + m_subTypeIndex(0), + m_index(0) +{} + + diff --git a/Trigger/TrigEvent/TrigNavigation/src/TriggerElement.cxx b/Trigger/TrigEvent/TrigNavigation/src/TriggerElement.cxx new file mode 100644 index 0000000000000000000000000000000000000000..bfe86ee344abe3b2e8cf098dac7395cf5975da6a --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/src/TriggerElement.cxx @@ -0,0 +1,15 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TrigNavigation/TriggerElement.h" + +MsgStream& operator<< ( MsgStream& m, const HLT::TriggerElement::ObjectIndex& i ) { + m << "SubTypeIdx: " << i.subTypeIndex() << " begin: " << i.objectsBegin() << " end: " << i.objectsEnd(); + return m; +} + +MsgStream& operator<< ( MsgStream& m, const HLT::TriggerElement& te ) { + m << "TE id: " << te.getId() << " ac: " << te.getActiveState() << " err: " << te.getErrorState(); + return m; +} diff --git a/Trigger/TrigEvent/TrigNavigation/src/TypeMaps.cxx b/Trigger/TrigEvent/TrigNavigation/src/TypeMaps.cxx new file mode 100644 index 0000000000000000000000000000000000000000..0da8fee433dabd31ff8bc417a000adcb3baa6853 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/src/TypeMaps.cxx @@ -0,0 +1,52 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TrigNavigation/TypeMaps.h" +namespace HLT { + TypeMaps::CLIDtoTypeProxyMap& TypeMaps::proxies() + { + static CLIDtoTypeProxyMap map; + return map; + } + + TypeMaps::CLIDtoHolderMap& TypeMaps::holders() + { + static CLIDtoHolderMap map; + return map; + } + + + TypeMaps::NametoCLIDMap& TypeMaps::type2clid() + { + static NametoCLIDMap type2clid; + return type2clid; + } +} + + +namespace HLTNavDetails { + class TypeMapDeleter { + public: + ~TypeMapDeleter() { + /* + { + HLT::TypeMaps::CLIDtoTypeProxyMap::iterator i; + for ( i = HLT::TypeMaps::proxies().begin(); i != HLT::TypeMaps::proxies().end(); ++i) { + delete i->second; i->second = 0; + } + HLT::TypeMaps::proxies().clear(); + } + { + HLT::TypeMaps::CLIDtoHolderMap::iterator i; + for ( i = HLT::TypeMaps::holders().begin(); i != HLT::TypeMaps::holders().end(); ++i) { + delete i->second; i->second = 0; + } + HLT::TypeMaps::holders().clear(); + } + */ + } + }; + TypeMapDeleter typeMapDeleter; // this objects is created in the file scope so at the deletion it can clean up the static types map +} + diff --git a/Trigger/TrigEvent/TrigNavigation/src/TypeProxy.cxx b/Trigger/TrigEvent/TrigNavigation/src/TypeProxy.cxx new file mode 100644 index 0000000000000000000000000000000000000000..6ac935e0ca7eb5a0daec096c63747be069b815d7 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/src/TypeProxy.cxx @@ -0,0 +1,85 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: TypeProxy.cxx 610817 2014-08-07 18:30:36Z lheinric $ + +// EDM include(s): +#include "AthContainersInterfaces/IAuxStore.h" + +// Local include(s): +#include "TrigNavigation/TypeProxy.h" + +namespace HLTNavDetails { + + ITypeProxy::ITypeProxy() + : m_clid( 0 ), m_typeName( "" ), m_key( "" ), m_proxy( 0 ), + m_ncPointer( 0 ), m_pointer( 0 ), m_isAuxVectorBase( false ) { + + } + + StatusCode ITypeProxy::sync( StoreGateSvc* sg, const std::string& key ) { + + // Get a proxy for this object: + m_proxy = sg->proxy( m_clid, key ); + if( ! m_proxy ) { + REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "HLTNavDetails::ITypeProxy::sync" ) + << "Couldn't get SG::DataProxy to the managed object"; + return StatusCode::FAILURE; + } + + // Get the pointers: + m_ncPointer = SG::DataProxy_cast( m_proxy, m_clid ); + m_pointer = m_ncPointer; + + // Remember this key: + m_key = key; + + // The rest is up to the code in the template class: + return StatusCode::SUCCESS; + } + + SG::AuxVectorBase* ITypeProxy::castAuxVectorBase() { + + if( m_isAuxVectorBase ) { + return static_cast< SG::AuxVectorBase* >( m_ncPointer ); + } else { + return 0; + } + } + + /// This cast can be done based on StoreGate, since SG::IAuxStore + /// has a CLID, as should the type that we're proxying + /// + SG::IAuxStore* ITypeProxy::castIAuxStore() { + + return static_cast< SG::IAuxStore* >( m_ncPointer ); + } + + bool ITypeProxy::contains( StoreGateSvc* sg, const std::string& key ) const { + + return sg->contains( m_clid, key ); + } + + bool ITypeProxy::transientContains( StoreGateSvc* sg, + const std::string& key ) const { + + return sg->transientContains( m_clid, key ); + } + + bool ITypeProxy::empty() const { + + return ( ( m_proxy == 0 ) && ( m_ncPointer == 0 ) ); + } + + CLID ITypeProxy::clid() const { + + return m_clid; + } + + const std::string& ITypeProxy::typeName() const { + + return m_typeName; + } + +} // namespace HLTNavDetails diff --git a/Trigger/TrigEvent/TrigNavigation/src/components/TrigNavigation_entries.cxx b/Trigger/TrigEvent/TrigNavigation/src/components/TrigNavigation_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..c1070f612731d1dc4c1f74df3104deba2a3b8df7 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/src/components/TrigNavigation_entries.cxx @@ -0,0 +1,10 @@ +#include "GaudiKernel/DeclareFactoryEntries.h" +#include "TrigNavigation/Navigation.h" + + +DECLARE_NAMESPACE_TOOL_FACTORY( HLT, Navigation ) + + +DECLARE_FACTORY_ENTRIES(TrigNavigation) { + DECLARE_NAMESPACE_ALGTOOL(HLT, Navigation) +} diff --git a/Trigger/TrigEvent/TrigNavigation/src/components/TrigNavigation_load.cxx b/Trigger/TrigEvent/TrigNavigation/src/components/TrigNavigation_load.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a310ec257dea861e85162cb051885ecefd63e3d5 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/src/components/TrigNavigation_load.cxx @@ -0,0 +1,12 @@ +#include "GaudiKernel/LoadFactoryEntries.h" + +LOAD_FACTORY_ENTRIES(TrigNavigation) + + //Notes: + // + //1. The argument to the LOAD_FACTORY_ENTRIES() is the name of the + // component library (libXXX.so). + // + // See Athena User Guide for more information + + diff --git a/Trigger/TrigEvent/TrigNavigation/test/HLTNavigation_test.cxx b/Trigger/TrigEvent/TrigNavigation/test/HLTNavigation_test.cxx new file mode 100644 index 0000000000000000000000000000000000000000..4a9ede39c72da58123036536d93740cefa8f552e --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/test/HLTNavigation_test.cxx @@ -0,0 +1,874 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include <sys/time.h> +#include <iostream> +#include <iterator> +#include "GaudiKernel/ClassID.h" +#include "GaudiKernel/MsgStream.h" +#include "StoreGate/StoreGate.h" +#include "StoreGate/StoreGateSvc.h" +#include "AthenaKernel/getMessageSvc.h" +#include "DataModel/ElementLinkVector.h" +#include "DataModel/ConstDataVector.h" + +#include "TestTools/initGaudi.h" + +#include "TrigNavigation/TriggerElement.h" + +#include "TrigNavigation/Navigation.h" +#include "TrigNavigation/Navigation.icc" +#include "TrigNavigation/RoICacheHelper.h" + +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/remove_const.hpp> +#include "TrigSerializeCnvSvc/TrigSerializeConverter.h" + +#include "TestTypes.h" +#include "TestUtils.h" + +double interval( struct timeval& begin, struct timeval& end) { + return (end.tv_sec - begin.tv_sec)*1000. + (end.tv_usec - begin.tv_usec)/1000.; +} +using namespace HLT; +/* +void blah( DataVector<B>::const_iterator ) {} + +void blah2() { + BContainer bb; + blah(bb.begin()); +} +*/ +///////////////////////////////////////////////////////////////////////////// +// +// features retrieval test +// +// +///////////////////////////////////////////////////////////////////////////// +template<class T, class C> +int testGetFeaturesOnDistinctTypes(MsgStream& log, Navigation* nav, TriggerElement* te, const std::string& label ) { + + + const T* singleFromGet = 0; + const T* singleFromGetRecent = 0; + std::vector<const T*> multipleFromGet; + std::vector<const T*> multipleFromGetRecent; + const T* singleRecentThroughEL(0); + std::vector<const T*> multipleRecentThroughELV; + + log << MSG::DEBUG << "testGetFeatures test for TE: " << te->getId() + << " and features of type " << ClassID_traits<T>::typeName() + << " with label " << label + << endreq; + + if ( nav->getFeature(te, singleFromGet, label) == false ) { + log << MSG::ERROR << "falied to get: singleFromGetFeature" << endreq; return -1; + } + + const TriggerElement* tsource(0); + std::string lsource; + if ( nav->getRecentFeature(te, singleFromGetRecent, label, tsource, lsource) ) { + if ( tsource == 0 && singleFromGetRecent != 0 ) { + log << MSG::ERROR << "falied to get: singleFromGetFeature no source found " << singleFromGetRecent << " " << tsource << endreq; + return -1; + } + if ( tsource ) { + log << MSG::INFO << "worked to get: endreq " << tsource->getId() << " label >" << label << "< back label >" << lsource << "< ptr: " << singleFromGetRecent << endreq; + + } + log << MSG::INFO << "falied to get: singleFromGetFeature" << endreq; + } else { + if ( !tsource ) { + log << MSG::ERROR << "in falied to get: singleFromGetFeature no source found " << tsource << endreq; + return -1; + } + } + + + + if ( nav->getFeatures(te, multipleFromGet, label) == false ) { + log << MSG::ERROR << "falied to get: multipleFromGet" << endreq; return -1; + } + if ( nav->getRecentFeatures(te, multipleFromGetRecent, label) == false ) { + if ( label != "" ) { + log << MSG::ERROR << "falied to get: multipleFromGetRecent" << endreq; return -1; + } else + log << MSG::INFO << "falied to get: multipleFromGetRecent but OK, label is empty string" << endreq; + } + + typedef ElementLink<C> CEL; + CEL el; + + if ( nav->getRecentFeatureLink<C, T>(te, el, label) == false ) { + log << MSG::INFO << "falied to get: singleRecentThroughEL" << endreq; + } + if (el.isValid()) + singleRecentThroughEL = *el; + + + typedef ElementLinkVector<C> CELV; + CELV elv; + typename CELV::iterator elvIt; + + if ( nav->getRecentFeaturesLinks<C, T>(te, elv, label) == false ) { + if ( label != "" ) { + log << MSG::ERROR << "falied to get: multipleRecentThroughELV" << endreq; return -1; + } else { + log << MSG::INFO << "falied to get: multipleRecentThroughELV" << endreq; + } + } + + for ( elvIt = elv.begin(); elvIt != elv.end(); ++elvIt ) { + el = *elvIt; + const T* t = *el; + multipleRecentThroughELV.push_back(const_cast<typename C::base_value_type *>(t)); + } + + log << MSG::DEBUG << "testGetFeatures passed features retrieval ... checking thier relations" << endreq; + + + // cross check ordering + if ( singleFromGet != 0 ) { + if ( multipleFromGet.size() < 1 ) { + log << MSG::ERROR << "singleFromGet & multipleFromGet give give inconsistent sizes " << multipleFromGet.size() << endreq; + return -1 ; + } + if ( singleFromGet != multipleFromGet.back() ) { + log << MSG::ERROR << "singleFromGet & multipleFromGet give wrong ordering" << endreq; + return -1 ; + } + } + + if ( singleFromGetRecent != 0 ) { + if ( singleFromGetRecent != multipleFromGetRecent.back() ) { + log << MSG::ERROR << "singleFromGetRecent & multipleFromGetRecent give wrong ordering" << endreq; + return -1 ; + } + } + + //cross check if EL based methog give the same + if ( singleFromGetRecent != singleRecentThroughEL ) { + log << MSG::ERROR << "singleFromGetRecent != singleRecentThroughEL" << endreq; + return -1 ; + } + + + if ( multipleRecentThroughELV.size() != multipleFromGetRecent.size() ) { + log << MSG::ERROR << "multipleRecentThroughELV.size() " << multipleRecentThroughELV.size() << " != multipleFromGetRecent.size() " <<multipleFromGetRecent.size() << endreq; + return -1 ; + } + + for ( unsigned i = 0; i < multipleRecentThroughELV.size() ; i++ ) { + if ( multipleRecentThroughELV[i] != multipleFromGetRecent[i] ) { + log << MSG::ERROR << "multipleRecentThroughELV[i] != multipleFromGetRecent[i] for i: " << i << endreq; + return -1; + } + } + + log << MSG::DEBUG << "testGetFeaturesOnDistinctTypes passed for TE: " << te->getId() + << " and features of type " << ClassID_traits<T>::typeName() + << " with label " << label + << " singleGet gave " << ( (singleFromGet) ? 1 : 0 ) + << " multipleGet gave " << multipleFromGet.size() + << endreq; + + return 0; +} + + + + + + + +///////////////////////////////////////////////////////////////////////////// +// the same as above but when collections are involved + + + +template<class T> +int testGetFeaturesOnSameTypes(MsgStream& log, Navigation* nav, TriggerElement* te, const std::string& label ) { + + const T* singleFromGet(0); + const T* singleFromGetRecent(0); + std::vector<const T*> multipleFromGet; + std::vector<const T*> multipleFromGetRecent; + T multipleRecentThroughELV; + multipleRecentThroughELV.clear(SG::VIEW_ELEMENTS); + T multipleRecentThroughPlain; + multipleRecentThroughPlain.clear(SG::VIEW_ELEMENTS); + + log << MSG::DEBUG << "testGetFeaturesOnSameTypes test for TE: " << te->getId() + << " and features of type " << ClassID_traits<T>::typeName() + << " with label " << label + << endreq; + + if ( nav->getFeature(te, singleFromGet, label) == false ) { + log << MSG::ERROR << "falied to get: singleFromGetFeature" << endreq; return -1; + } + if ( nav->getRecentFeature(te, singleFromGetRecent, label) == false ) { + log << MSG::INFO << "falied to get: singleFromGetRecentFeature" << endreq; + } + if ( nav->getFeatures(te, multipleFromGet, label) == false ) { + log << MSG::ERROR << "falied to get: multipleFromGet" << endreq; return -1; + } + if ( nav->getRecentFeatures(te, multipleFromGetRecent, label) == false ) { + log << MSG::INFO << "falied to get: multipleFromGetRecent" << endreq; + } + + typename std::vector<const T*>::const_iterator pIt; + for ( pIt = multipleFromGetRecent.begin(); pIt != multipleFromGetRecent.end(); ++pIt) { + multipleRecentThroughPlain.insert( multipleRecentThroughPlain.end(), (*pIt)->begin(), (*pIt)->end() ); + } + + typedef ElementLink<T> CEL; + CEL el; + + if ( nav->getRecentFeatureLink<T, T>(te, el, label) == true ) { + log << MSG::ERROR << "managed to get: singleRecentThroughEL this method for same types should return false" << endreq; return -1; + } + + typedef ElementLinkVector<T> CELV; + CELV elv; + typename CELV::iterator elvIt; + + if ( nav->getRecentFeaturesLinks<T, T>(te, elv, label) == false ) { + log << MSG::INFO << "falied to get: multipleRecentThroughELV" << endreq; + } + + for ( elvIt = elv.begin(); elvIt != elv.end(); ++elvIt ) { + el = *elvIt; + typedef typename T::base_value_type S; + const S* t = *el; + multipleRecentThroughELV.push_back((S*)t); + } + + log << MSG::DEBUG << "testGetFeatures passed features retrieval ... checking thier relations" << endreq; + + + // cross check ordering + if ( singleFromGet != 0 ) { + if ( multipleFromGet.size() < 1 ) { + log << MSG::ERROR << "singleFromGet & multipleFromGet give give inconsistent sizes " << multipleFromGet.size() << endreq; + return -1 ; + } + if ( singleFromGet != multipleFromGet.back() ) { + log << MSG::ERROR << "singleFromGet & multipleFromGet give wrong ordering" << endreq; + return -1 ; + } + } + + if ( singleFromGetRecent != 0 ) { + if ( singleFromGetRecent != multipleFromGetRecent.back() ) { + log << MSG::ERROR << "singleFromGetRecent & multipleFromGetRecent give wrong ordering" << endreq; + return -1 ; + } + } + + //cross check if EL based methog give the same + + + if ( multipleRecentThroughELV.size() != multipleRecentThroughPlain.size() ) { + log << MSG::ERROR << "multipleRecentThroughELV.size() != multipleRecentThroughPlain.size()" << endreq; + return -1 ; + } + + for ( unsigned i = 0; i < multipleRecentThroughELV.size() ; i++ ) { + if ( multipleRecentThroughELV[i] != multipleRecentThroughPlain[i] ) { + log << MSG::ERROR << "multipleRecentThroughELV[i] != multipleRecentThroughPlain[i] for i: " << i << endreq; + return -1; + } + } + + log << MSG::DEBUG << "testGetFeaturesOnSameTypes passed for TE: " << te->getId() + << " and features of type " << ClassID_traits<T>::typeName() + << " with label " << label + << " singleGet gave " << ( (singleFromGet) ? 1 : 0 ) + << " multipleGet gave " << multipleFromGet.size() + << endreq; + + return 0; +} + + +template<class T> +int testFindOwners(MsgStream& log, Navigation* nav, T* t, bool isRealyAttached=true) { + std::vector<const TriggerElement*> tes; + if (nav->findOwners(t, tes) == false) { + log << MSG::ERROR << "find owners failed for : " << t << " of type " << ClassID_traits<T>::typeName() << endreq; + return -1; + } + if ( isRealyAttached && tes.size() == 0 ) { + log << MSG::ERROR << "find owners found 0 TEs for : " << t << " of type " << ClassID_traits<T>::typeName() << endreq; + return -1; + } + + if ( (!isRealyAttached) && tes.size() != 0 ) { + log << MSG::ERROR << "find owners worked for : " << t << " of type " << ClassID_traits<T>::typeName() << endreq; + return -1; + } + return 0; +} + + + + +template<class T, class C> +int checkGetFeaturesOnAllTEsOnDistinctTypes(MsgStream& log, Navigation* nav, TriggerElement* te, const std::string& label) { + + + if ( testGetFeaturesOnDistinctTypes<T,C>(log, nav, te, label) != 0 ) + return -1; + + std::vector<TriggerElement*> succ = nav->getDirectSuccessors(te); + std::vector<TriggerElement*>::iterator i; + + log << MSG::DEBUG << "looping over successors " << succ.size() << endreq; + for ( i = succ.begin(); i != succ.end(); ++i ) { + + if ( checkGetFeaturesOnAllTEsOnDistinctTypes <T,C>(log, nav, *i, label) != 0 ) + return -1; + } + return 0; +} + + +template<class T> +int checkGetFeaturesOnAllTEsOnSameTypes(MsgStream& log, Navigation* nav, TriggerElement* te, const std::string& label) { + + + if ( testGetFeaturesOnSameTypes<T>(log, nav, te, label) != 0 ) + return -1; + + std::vector<TriggerElement*> succ = nav->getDirectSuccessors(te); + std::vector<TriggerElement*>::iterator i; + + log << MSG::DEBUG << "looping over successors " << succ.size() << endreq; + for ( i = succ.begin(); i != succ.end(); ++i ) { + + if ( checkGetFeaturesOnAllTEsOnSameTypes <T>(log, nav, *i, label) != 0 ) + return -1; + } + return 0; +} +//**************************************************************************************** +StatusCode construction_test(HLT::Navigation* hns) { + BEGIN_TEST("Construction"); + TriggerElement* initial = hns->getInitialNode(); + if ( not initial ) REPORT_AND_STOP("Can not get initial node"); + if ( not HLT::Navigation::isInitialNode(initial) ) REPORT_AND_STOP("Initial node not initial"); + + + TriggerElement* roi1 = hns->addRoINode(initial); //roi1->setId(1); // id are for the test only + TriggerElement* roi2 = hns->addRoINode(initial); //roi2->setId(2); + TriggerElement* roi3 = hns->addRoINode(initial); //roi3->setId(3); + if ( HLT::Navigation::isInitialNode(roi3) ) REPORT_AND_STOP("The RoI node considered as initial"); + + + TriggerElement* roi1eltr1 = hns->addNode(roi1, 11); + TriggerElement* roi1eltr2 = hns->addNode(roi1, 12); + TriggerElement* roi1eltr3 = hns->addNode(roi1, 13); + TriggerElement* roi1eltr4 = hns->addNode(roi1, 14); + + + TriggerElement* clu1 = hns->addNode(roi1eltr1, 111); + TriggerElement* track1 = hns->addNode(clu1, 1111); + TriggerElement* el1 = hns->addNode(track1, 11111); + // el1->attachFeature(new A); + + // another roi + TriggerElement* roi2mutr1 = hns->addNode(roi2, 21); + TriggerElement* roi2mutr2 = hns->addNode(roi2, 22); roi2mutr2->getId(); + + REPORT_AND_CONTINUE( "after adding inital nodes" ); + + // build big structure + std::vector<TriggerElement*> telist; + telist.push_back(roi2mutr1); + telist.push_back(track1); + TriggerElement* zz = hns->addNode(telist, 33301); + zz->setErrorState(true); + TriggerElement* zz2 = hns->addNode(telist, 33311); zz2->getId(); + TriggerElement* zz1 = hns->addNode(zz, 33321); + TriggerElement* zz1prim = hns->addNode(zz1, 33323); + TriggerElement* zz1prim2 = hns->addNode(telist, 33324, false, true); + + REPORT_AND_CONTINUE("RoIs made"); + + if ( ! HLT::Navigation::haveCommonRoI(roi1eltr1, roi1eltr2) ) + REPORT_AND_STOP( "this TEs (2 direct successors) should have indicate that they have common RoI" ); + + + if ( ! HLT::Navigation::haveCommonRoI(roi1, roi1eltr4) ) + REPORT_AND_STOP( "this TEs (RoI and direct successor) should have indicate that they have common RoI" ); + + + if ( ! HLT::Navigation::haveCommonRoI(roi1, clu1) ) + REPORT_AND_STOP( "this TEs (RoI and indirect successor) should have indicate that they have common RoI" ); + + + if ( ! HLT::Navigation::haveCommonRoI(roi1eltr3, el1) ) + REPORT_AND_STOP( "this TEs (2 indirect successors) should have indicate that they have common RoI" ); + + + if ( HLT::Navigation::haveCommonRoI(roi2mutr1, el1) ) + REPORT_AND_STOP( "this simple TEs (direct successor and indeirect successor) should have indicate that they have distinct RoI" ); + + + if ( HLT::Navigation::haveCommonRoI(roi2mutr1, roi1) ) + REPORT_AND_STOP( "this simple TEs (direct successor and RoI) should have indicate that they have distinct RoI" ); + + + if ( ! HLT::Navigation::haveDistinctRoI(roi3, zz) ) + REPORT_AND_STOP( "this simple TEs (RoI and Topo) should have indicate that they have distinct RoI" ); + + + if ( ! HLT::Navigation::haveDistinctRoI(roi1, roi2) ) + REPORT_AND_STOP( "this simple TEs (RoI and Topo) should have indicate that they have distinct RoI" ); + + + REPORT_AND_CONTINUE("RoIs Common/Distinct check made"); + + + // add ghost TES + TriggerElement* ghost; + ghost = hns->addNode(telist, 33399, true); ghost->setActiveState(false); + ghost = hns->addNode(telist, 33399, true); + ghost = hns->addNode(telist, 33399, true); + ghost = hns->addNode(telist, 33399, true); + ghost = hns->addNode(telist, 33399, true); + ghost = hns->addNode(telist, 33399, true); + ghost = hns->addNode(telist, 33399, true); + + // build one long branch + TriggerElement* te1 = roi1eltr1; + TriggerElement* te2; + int i; + for ( i = 0; i < 25; i++ ) { + te2 = hns->addNode(te1, 5000+i); + te1 = te2; + } + + // add many leafs to one of the RoI + for ( i = 0; i < 24; i++ ) { + te1 = hns->addNode(roi1, 50); + // bunch of inactive TEes + TriggerElement* te3 = hns->addNode(roi1, 60); + te3->setActiveState(false); + + // every of it has 5 leafs + telist.clear(); + for ( int j = 0; j < 5; j++ ) { + te2 = hns->addNode(te1, te1->getId()+100); + telist.push_back(te2); + } + // a big join + te1 = hns->addNode(telist, te1->getId()+1000); + } + + std::vector<TriggerElement*> typeVec; + hns->getAllOfType(50, typeVec); + if (! HLT::Navigation::haveCommonRoI( typeVec[0], typeVec[1] ) ) + REPORT_AND_STOP( "this simple TEs (2 sibling successors) should have indicate that they have distinct RoI" ); + + + END_TEST; +} + +//**************************************************************************************** +StatusCode counting_test(HLT::Navigation* hns) { + BEGIN_TEST("counting"); + + + + // test queries by type + std::vector<TriggerElement*> typeVec; + hns->getAllOfType(50, typeVec); + + if ( typeVec.size() != 24 ) + REPORT_AND_STOP( "Query by type incorrect, should have returned 25 TE: " << typeVec.size() ); + + + typeVec.clear(); + hns->getAllOfType(60, typeVec); + if ( typeVec.size() != 0 ) + REPORT_AND_STOP( "Query by type incorrect, should have returned 0 TE (all are inactive): " << typeVec.size() ) + + + hns->getAllOfType(60, typeVec, false); + if ( typeVec.size() != 24 ) + REPORT_AND_STOP( "Query by type incorrect, should have returned 0 TE (all are inactive, but shouldnot look at the status): " << typeVec.size() ); + + REPORT_AND_CONTINUE( "SUCCESS TEST of getAllOfType method" ); + + if ( hns->countAllOfType(33399) != 6 ) + REPORT_AND_STOP( "Count by type incorrect, got active only: " << hns->countAllOfType(33399) << " inestead of " << 6 ); + + + if ( hns->countAllOfType(33399, false) != 7 ) + REPORT_AND_STOP( "Count by type incorrect, got active and inactive: " << hns->countAllOfType(33399) << " inestead of " << 7 ); + + + END_TEST; + +} +//**************************************************************************************** +StatusCode seeding_test(HLT::Navigation* hns) { + BEGIN_TEST("seeding"); + + + + + END_TEST; + +} + +TriggerElement* getTE(Navigation* hns, int id) { + std::vector<TriggerElement*> tes; + hns->getAllOfType(id, tes); + if ( tes.size() == 1 ) + return tes[0]; + return 0; +} +bool all_not_null(const std::initializer_list<TriggerElement*>& all) { + for ( TriggerElement* te: all ) + if (te == 0) return false; + return true; +} + +//**************************************************************************************** +StatusCode topo_test(HLT::Navigation* hns) { + BEGIN_TEST("topo"); + TriggerElement* clu1 = getTE(hns, 111); + TriggerElement* zz = getTE(hns, 33301); + TriggerElement* roi1eltr1 = getTE(hns, 11); + TriggerElement* roi1eltr2 = getTE(hns, 12); + TriggerElement* roi2 = getTE(hns, 21); + TriggerElement* roi2mutr2 = getTE(hns, 22); + + if ( not all_not_null({clu1, zz, roi1eltr1, roi1eltr2, roi2}) ) + REPORT_AND_STOP("Some TEs are 0"); + + if ( HLT::Navigation::isTopological(clu1) != false ) + REPORT_AND_STOP ( "clu1 TE is recognized as topological while it is not" ); + + if ( HLT::Navigation::isTopological(zz) != true ) + REPORT_AND_STOP( "zz TE is not recognized as topological while it is " ); + + REPORT_AND_CONTINUE( "SUCCESS tests of isTopological method" ); + if ( ! HLT::Navigation::haveCommonSeed(roi1eltr1, roi1eltr2) ) + REPORT_AND_STOP( "this TEs (2 direct successors) should have indicate that they have common seed" ); + + + + if ( ! HLT::Navigation::haveDistinctSeed(roi1eltr1, roi2) ) + REPORT_AND_STOP( "this TEs (normal and RoI) should have indicate that they have distinct seed" ); + + + if ( HLT::Navigation::getSuccessor(clu1, 33301) != zz ) + REPORT_AND_STOP( "getSuccessor is failing to find right TE" ); + + + if ( HLT::Navigation::getSuccessor(roi2mutr2, 33301) != 0 ) + REPORT_AND_STOP ("getSuccessor fond TE which is wrong" ); + + + + REPORT_AND_CONTINUE( " of haveCommonSeed method" ); + + + + + END_TEST; + +} + +//**************************************************************************************** +StatusCode single_feature_test(HLT::Navigation* hns) { + BEGIN_TEST("single feature operations test"); + TriggerElement* clu1 = getTE(hns, 111); + TriggerElement* track1 = getTE(hns, 1111); + TriggerElement* el1 = getTE(hns, 11111); + + TestA* a1 = new TestA(1); + TestA* a2 = new TestA(2); + TestA* a3 = new TestA(3); + TestA* a4 = new TestA(4); + TestA* a5 = new TestA(5); + std::string key; + if ( hns->attachFeature(clu1, a1, Navigation::ObjectCreatedByNew, key, "Single") == false ) + REPORT_AND_STOP( "Attach feature returned false " ); + + if ( hns->attachFeature(clu1, a2, Navigation::ObjectCreatedByNew, key, "Single") == false ) + REPORT_AND_STOP( "Attach second feature failed" ); + + + std::vector<const TestA*> avec; + + hns->getFeatures(clu1, avec); + if ( avec.size() != 2 ) + REPORT_AND_STOP( "No. of attached features wrong (2): " << avec.size() ); + + + hns->getFeatures(track1, avec); + if ( avec.empty() ) + REPORT_AND_STOP( "attached features visible in other TEs" ); + + + + avec.clear(); + hns->attachFeature(clu1, a3, Navigation::ObjectCreatedByNew, key, "ToolTestA"); + hns->attachFeature(clu1, a4, Navigation::ObjectCreatedByNew, key, "ToolB"); + + + hns->getFeatures(clu1, avec); + if ( avec.size() != 4 ) + REPORT_AND_STOP ( "No. of attached features wrong, problem with labeled features (4): " << avec.size() ); + + + avec.clear(); + hns->getFeatures(clu1, avec, "ToolTestA" ); + if ( avec.size() != 1 ) + REPORT_AND_STOP( "No. of attached features wrong, does not regard labels (1): " << avec.size() ); + + avec.clear(); + hns->attachFeature(track1, a5, Navigation::ObjectCreatedByNew, key, "ToolB"); + hns->getFeaturesInRoI(el1, avec); + if ( avec.size() != 5 ) + REPORT_AND_STOP( "No. of attached features wrong, does not see all RoI: " << avec.size() ); + + std::vector<const TestA*> lastA; + hns->getRecentFeatures(el1, lastA ); + if ( lastA.empty() ) + REPORT_AND_STOP( "getLastFeature retrieves null" ); + + if ( lastA.back()->a != 5 ) + REPORT_AND_STOP( "getLastFeature retrieves wrong feature" ); + + lastA.clear(); + hns->getRecentFeatures(el1, lastA, "ToolTestA" ); + if ( lastA.empty() ) + REPORT_AND_STOP( "getLastFeature retrieves null" ); + if ( lastA.back()->a != 3 ) + REPORT_AND_STOP ( "getLastFeature retrieves wrong feature" ); + + REPORT_AND_CONTINUE("Get features worked fine"); + + END_TEST; +} + +//**************************************************************************************** +TestBContainer* makeTestB(int value, size_t size=3) { + TestBContainer * tb = new TestBContainer; + TestAuxB* aux = new TestAuxB; // this will leak memory but it is more convenient for testing + tb->setStore(aux); + for ( size_t i = 0; i < size; ++i ) + tb->push_back(new TestB(value)); + + return tb; +} + + +StatusCode container_feature_test(HLT::Navigation* hns) { + BEGIN_TEST("container feature operations test"); + TriggerElement* clu1 = getTE(hns, 111); + TriggerElement* track1 = getTE(hns, 1111); + TriggerElement* el1 = getTE(hns, 11111); + + TestBContainer *tb1 = makeTestB(1); + std::string key; + hns->attachFeature(clu1, tb1, HLT::NavigationCore::ObjectCreatedByNew, key, "Test1"); + + TestBContainer * tb2 = makeTestB(2, 2); + hns->attachFeature(clu1, tb2, HLT::NavigationCore::ObjectCreatedByNew, key, "BContainer2"); // this one has Aux + + // get from the derived TE + const TestBContainer *bret(0); + hns->getRecentFeature(el1, bret); + if ( bret == 0 ) + REPORT_AND_STOP( "Failed to get back last container container feature" ); + + if ( bret->size() != 2 ) + REPORT_AND_STOP( "Failed to get back correct last container container feature" ); + + // if ( bret->getStore() == 0 ) + // REPORT_AND_STOP( "What we got back for the decorated has no decoration" ); + + bret = 0; + hns->getRecentFeature(el1, bret, "Test1"); + if ( bret == 0) + REPORT_AND_STOP( "getRecentFeature does not respect labels" ); + + + END_TEST; +} + + + + +//**************************************************************************************** +StatusCode serialize_test(HLT::Navigation* hns, HLT::Navigation* newhns) { + BEGIN_TEST("serialize test"); + std::vector<uint32_t> serialized; + std::vector<unsigned> breaks; + hns->serialize(serialized, breaks); + + + newhns->deserialize(serialized); + REPORT_AND_CONTINUE( "serialize/deserialze sequence worked" ); + + + if ( not HLT::Navigation::isCompatibleTree(newhns->getInitialNode(), hns->getInitialNode() ) ) + REPORT_AND_STOP( "serialization/deserialization does not rebuild the the same structure" ); + + + END_TEST; +} + +StatusCode const_attach_test(HLT::Navigation* hns) { + BEGIN_TEST("const attach test"); + typedef ConstDataVector<TestBContainer> ConstTestBContainer; // this is container of consts + ConstTestBContainer* cb = new ConstTestBContainer; + cb->push_back(new TestB(68)); + cb->push_back(new TestB(78)); + std::string key; + TriggerElement* el1 = getTE(hns, 11111); + + if ( hns->attachFeature(el1, cb, HLT::NavigationCore::ObjectCreatedByNew, key, "ConstBContainer") == false ) + REPORT_AND_STOP("attach of ConsTestBContainer failed"); + + const ConstTestBContainer* rcb{nullptr}; + if ( hns->getFeature(el1, rcb) == false ) + REPORT_AND_STOP("Retrieve of the ConstTestBContainer failed"); + + if ( rcb == nullptr ) + REPORT_AND_STOP("Retrieve of the ConstTestBContainer failed, the pointer is 0"); + if ( rcb->at(0)->value() != 68 ) + REPORT_AND_STOP("Got incorrect container"); + + + // now try to reuse some TestB obect stored in another non-const container + const TestBContainer* tb2{nullptr}; + TriggerElement* clu1 = getTE(hns, 111); + const bool stat = hns->getFeature(clu1, tb2, "BContainer2"); + if ( stat == false ) + REPORT_AND_STOP("Can not get the non-const TestBContainer object, error"); + if ( tb2 == nullptr ) + REPORT_AND_STOP("Can not get the non-const TestBContainer object, pointer is null"); + + REPORT_AND_CONTINUE("Got the already attached container "<< tb2->size()); + + if ( tb2->size() != 2 ) + REPORT_AND_STOP("Can not get the non-const TestBContainer object, size is to small"); + ConstTestBContainer* cb2 = new ConstTestBContainer; + cb2->push_back(tb2->at(1)); + if ( cb2->size() != 1 ) + REPORT_AND_STOP("Can not push_back into the ConstTestBContainer"); + + REPORT_AND_CONTINUE("Prepared ConstTestBContainer wiht contnt already present in another non-cont container" ); + + if ( hns->attachFeature(el1, cb2, HLT::NavigationCore::ObjectCreatedByNew, key, "ConstBContainer2") == false ) + REPORT_AND_STOP("Can not attach ConstTestBContainer"); + + + END_TEST; +} + + +//**************************************************************************************** +int main () { + using std::cerr; + using std::endl; + using std::hex; + using std::dec; + // blah2(); + + // using namespace Athena_test; + + + ISvcLocator* pSvcLoc; + if (!Athena_test::initGaudi("test.txt", pSvcLoc)) { + cerr << "ERROR This test can not be run" << endl; + return 0; + } + assert(pSvcLoc); + + + MsgStream log(Athena::getMessageSvc(), "HLTNavigation_test"); + msglog = &log; + + + StoreGateSvc* pStore(0); + + + if( pSvcLoc->service("StoreGateSvc", pStore, true).isSuccess() ) { + log << MSG::DEBUG << "SG pointer: " << pStore << endreq; + } else REPORT_AND_STOP( "no SG available" ); + + + IToolSvc* toolSvc; + + if( pSvcLoc->service("ToolSvc", toolSvc, true).isSuccess() ) { + log << MSG::DEBUG << "ToolSvc pointer: " << toolSvc << endreq; + } else + ABORT ( "no ToolSvc available" ); + + + HLT::Navigation* hns; + IAlgTool* algTool; + if ( toolSvc->retrieveTool("HLT::Navigation/Navigation", algTool).isSuccess() ) { + log << MSG::DEBUG << "OK navigation tool retrieved" << endreq; + hns = dynamic_cast< HLT::Navigation*>(algTool); + if ( hns ) { + log << MSG::DEBUG << "OK navigation casted" << endreq; + } else + ABORT( "navigation cast failed" ); + + } else ABORT ("navigation tool NOT retrieved" ); + + + hns->reset(); + + if ( construction_test(hns).isFailure() ) + ABORT("TEs construction test failed"); + + + if ( counting_test(hns).isFailure() ) + ABORT("Counting test failed"); + + + if ( topo_test(hns).isFailure() ) + ABORT("Topo test failed"); + + + if ( single_feature_test(hns).isFailure() ) + ABORT("Single feature manipulation"); + + if ( container_feature_test(hns).isFailure() ) + ABORT("Container feature manipulation"); + + if ( const_attach_test(hns).isFailure() ) { + ABORT("ConstDV attaching test failed"); + } + // log << MSG::DEBUG << pStore->dump() << endreq; + + + HLT::Navigation* newhns; + if ( toolSvc->retrieveTool("HLT::Navigation/Navigation2", algTool).isSuccess() ) { + REPORT_AND_CONTINUE( "OK navigation tool retrieved" ); + newhns = dynamic_cast< HLT::Navigation*>(algTool); + } + if ( serialize_test(hns, newhns).isFailure() ) + ABORT( "Serialization test failed" ); + + + + + REPORT_AND_CONTINUE( "SUCCESS test passed OK " ); + + + return 0; + +} + diff --git a/Trigger/TrigEvent/TrigNavigation/test/Holder_test.cxx b/Trigger/TrigEvent/TrigNavigation/test/Holder_test.cxx new file mode 100644 index 0000000000000000000000000000000000000000..7d53e2ad710587b85fab56a79503f57279613348 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/test/Holder_test.cxx @@ -0,0 +1,273 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "iostream" +#include "vector" + +#include "TestTools/initGaudi.h" +#include "AthenaKernel/getMessageSvc.h" +#include "GaudiKernel/MsgStream.h" +#include "StoreGate/StoreGate.h" +#include "StoreGate/StoreGateSvc.h" +#include "TrigNavigation/Holder.h" +#include "TrigNavigation/Holder.icc" + +#include "TrigNavigation/TriggerElement.h" + +#include "TestTypes.h" +#include "TestUtils.h" + +using namespace std; +using namespace HLTNavDetails; +// Hi-lock: (("REPORT_AND_STOP" (0 (quote hi-yellow) t))) + +//const int OK=1; +//const int FAILED=0; + +StoreGateSvc* pStore(0); + + + + + +template<class HTYPE> +StatusCode reg( HTYPE* full, const char* name, int idx, ITypeProxy* /*aux*/, typename HTYPE::base_type*& base_holder ) { + BEGIN_TEST("Registration"); + IHolder* iholder = full->clone(name, idx); + if ( ! iholder ) REPORT_AND_STOP ("Holder can't create IHolder" ); + + base_holder = dynamic_cast<typename HTYPE::base_type*>(iholder); // we do nto intend to do it but here it is to see if types realy fit + if ( ! base_holder ) REPORT_AND_STOP ("Holder can't create base holder" ); + + + iholder->prepare(msglog, pStore); + if ( iholder->syncWithSG() == false ) REPORT_AND_STOP( "can not sync wiht holder" ); + + END_TEST; +} + +//***************************************************************************** +StatusCode creation() { + BEGIN_TEST( "Creation of the holders Container <-> Container" ); + Holder<TestBContainer >* cc(0); + + if ( reg(new HolderImp<TestBContainer, TestBContainer >() , "creation0", 0, 0, cc).isFailure() ) REPORT_AND_STOP( "reg creation0" ); + + REPORT_AND_CONTINUE( "Creation of the holders Object <-> Container" ); + Holder<TestA>* oc(0); + if ( reg(new HolderImp<TestA, TestAContainer >(), "creation1", 1, 0, oc).isFailure() ) REPORT_AND_STOP("reg creation1") ; + + + ////////////////////////////////////////////////////////////////// + REPORT_AND_CONTINUE( "Creation of the holders Container <-> Container with details" ); + ITypeProxy* deco = HLT::TypeMaps::proxies()[ClassID_traits<TestAuxB>::ID()]->clone(); + Holder<TestBContainer >* cc_dec(0) ; + if ( reg(new HolderImp<TestBContainer, TestBContainer >(), "creation2", 2, deco, cc_dec).isFailure() ) REPORT_AND_STOP("reg creation2") ; + + + REPORT_AND_CONTINUE( "Creation of the holders Object <-> Container" ); + Holder<TestA>* oc_dec(0); + if ( reg(new HolderImp<TestA, TestAContainer >(), "creation3", 3, deco, oc_dec).isFailure() ) REPORT_AND_STOP("reg creation3") ; + + END_TEST; +} + +//***************************************************************************** +StatusCode add_operation(bool wihtAux) { + BEGIN_TEST ( "Simple test of Container <-> Container holder (add)" ); + ITypeProxy* deco(0); + if (wihtAux) + deco = HLT::TypeMaps::proxies()[ClassID_traits<TestAuxB>::ID()]->clone(); + + Holder<TestBContainer>* cch(0); + if ( reg( new HolderImp<TestBContainer, TestBContainer>(), "TestB", 11, deco, cch).isFailure() ) REPORT_AND_STOP("It should have failed before"); + + TestBContainer* dav0 = new TestBContainer;; + dav0->push_back(new TestB(6)); + REPORT_AND_CONTINUE( "adding simple vec" ); + HLT::TriggerElement::ObjectIndex single = cch->add(dav0, false); + + // BContainer dav(SG::OWN_ELEMENTS); + TestBContainer* dav = new TestBContainer; + dav->push_back(new TestB(1)); + dav->push_back(new TestB(2)); + + REPORT_AND_CONTINUE( "Added another ownership" ); + pStore->record(dav, "dav1").ignore(); + HLT::TriggerElement::ObjectIndex two = cch->add(dav, true); + + TestBContainer* dav2 = new TestBContainer; + dav2->push_back(new TestB(3)); + dav2->push_back(new TestB(4)); + + REPORT_AND_CONTINUE( "Added another ownership -with the hint" ); + pStore->record(dav2, "dav2").ignore(); + HLT::TriggerElement::ObjectIndex three = cch->add(dav2, true, "dav2"); + + REPORT_AND_CONTINUE( "Adding a VIEW container" ); + TestBContainer* dav3 = new TestBContainer; + dav3->clear(SG::VIEW_ELEMENTS); + dav3->push_back(new TestB(7)); + dav3->push_back(new TestB(7)); + + HLT::TriggerElement::ObjectIndex four = cch->add(dav3, false, "dav3"); + + // retieve back the information + { + const TestBContainer* getv(0); + cch->get(getv, single); + if ( (*getv)[0]->value() != 6 ) + REPORT_AND_STOP( "Content missing or reordered -single feature in the container)"); + } + { + const TestBContainer* getv(0); + cch->get(getv, two); + if ( getv->size() != 2 or (*getv)[0]->value() != 1 or (*getv)[1]->value() != 2 ) + REPORT_AND_STOP( "Content missing or reordered -single feature in the container)"); + } + + { + const TestBContainer* getv(0); + cch->get(getv, three); + if ( getv->size() != 2 or (*getv)[0]->value() != 3 or (*getv)[1]->value() != 4 ) + REPORT_AND_STOP( "Content missing or reordered - single feature in the container)"); + } + REPORT_AND_CONTINUE( "END Simple test of Container <-> Container holder -add-" ); + ///////////////////////////////////////////////////////////////////////////// + + REPORT_AND_CONTINUE( "END Simple test of Object <-> Container holder -add-" ); + Holder<TestA>* och(0); + if ( reg(new HolderImp<TestA, TestAContainer >(), "TestA", 12, deco, och).isFailure() ) REPORT_AND_STOP("reg TestA") ; + + TestA* an = new TestA(235); + HLT::TriggerElement::ObjectIndex coord = och->add(an, true); + // HLT::TriggerElement::ObjectIndex ancoord = coord; + const TestA* aback(0); + if ( och->get(aback, coord) == false ) + REPORT_AND_STOP ("Content missing of single feature" ); + + if ( aback == 0 ) REPORT_AND_STOP ("Content is none" ); + + if ( aback->value() != 235 ) REPORT_AND_STOP ( "Content is different" ); + + END_TEST; +} + +//***************************************************************************** +StatusCode contains_operations() { + BEGIN_TEST("Operations"); + Holder<TestBContainer>* cch(0); + if ( reg( new HolderImp<TestBContainer, TestBContainer>(), "TestB", 11, 0, cch).isFailure() ) REPORT_AND_STOP("It should have failed before"); + TestB* b0 = new TestB(67); + TestBContainer * t = new TestBContainer(); + t->push_back( new TestB(9) ); + t->push_back(b0); + t->push_back( new TestB(8) ); + if ( not cch->add(t, false, "whatever").valid() ) + REPORT_AND_STOP("adding failed"); + HLT::TriggerElement::ObjectIndex testidx; + if ( not cch->contains(t, testidx) ) + REPORT_AND_STOP("Holder should have this pointer"); + + TestBContainer * t2 = new TestBContainer(); + t2->push_back( new TestB()); + if ( cch->contains(t2, testidx) ) + REPORT_AND_STOP("Holder should not have this pointer"); + + END_TEST; +} + +//***************************************************************************** +StatusCode serialization() { + BEGIN_TEST("serialization"); + Holder<TestBContainer>* cch(0); + if ( reg( new HolderImp<TestBContainer, TestBContainer>(), "blu", 2, 0, cch).isFailure() ) REPORT_AND_STOP("It should have failed before"); + IHolder * realH = cch; + std::vector<uint32_t> blob; + + CLID c; + uint16_t idx; + string label; + + realH->serialize(blob); + + REPORT_AND_CONTINUE( "blob size " << blob.size() ); + std::vector<uint32_t>::const_iterator it = blob.begin(); + + + IHolder::enquireSerialized(blob, it, c, label, idx); + *msglog << MSG::DEBUG << "INFO clid : " << c << endreq; + *msglog << MSG::DEBUG << "INFO STidx : " << idx << endreq; + *msglog << MSG::DEBUG << "INFO label : " << label << endreq; + if ( label != "blu" || idx != 2 || c != ClassID_traits<TestBContainer>::ID() ) + REPORT_AND_STOP ( "serialization or inquire failed" ); + + END_TEST; +} +//***************************************************************************** +int main() { + + + ISvcLocator* pSvcLoc; + if (!Athena_test::initGaudi("test.txt", pSvcLoc)) { + cerr << "ERROR This test can not be run" << endl; + return 0; + } + assert(pSvcLoc); + MsgStream log(Athena::getMessageSvc(), "Holder_test"); + msglog = &log; + + if( pSvcLoc->service("StoreGateSvc", pStore, true).isSuccess() ) { + *msglog << MSG::DEBUG << "SG pointer: " << pStore << endreq; + } else { + ABORT( "ERROR no SG available" ); + } + + if ( creation().isFailure() ) + ABORT("Holders creation failed"); + + *msglog << MSG::DEBUG << pStore->dump(); + *msglog << endreq; + + pStore->clearStore(); + if ( add_operation(false).isFailure() ) + ABORT("Failed add_operation w/o Aux"); + + pStore->clearStore(); + *msglog << MSG::DEBUG << "Holders with decorations " << endreq; + if ( add_operation(true).isFailure() ) + ABORT("Failed add_operation with Aux"); + + pStore->clearStore(); + *msglog << MSG::DEBUG << "Contains and co. methods " << endreq; + if ( contains_operations().isFailure() ) + ABORT("Failed contains_operations"); + + + *msglog << MSG::DEBUG << "Serialization " << endreq; + if ( serialization().isFailure() ) + ABORT("Failed serialization"); + + + REPORT_AND_CONTINUE( "END all went fine" ); + return 0; + + + /* + + + + + + ////////////////////////////////////////////////////////////////// + *msglog << MSG::DEBUG << "Serialization test" << endreq; + std::vector<uint32_t> + + // pStore->clearStore(); + */ + *msglog << MSG::INFO << "SUCCESS " << endreq; + *msglog << MSG::DEBUG << "deleting messages below are related to scope exit " << endreq; + + return 0; +} diff --git a/Trigger/TrigEvent/TrigNavigation/test/Ownership_test.cxx b/Trigger/TrigEvent/TrigNavigation/test/Ownership_test.cxx new file mode 100644 index 0000000000000000000000000000000000000000..6f2f4e183dc53c85779aaaf61890bbeff65a0514 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/test/Ownership_test.cxx @@ -0,0 +1,187 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "iostream" +#include "vector" + +#include "TestTools/initGaudi.h" +#include "AthenaKernel/getMessageSvc.h" +#include "GaudiKernel/MsgStream.h" +#include "StoreGate/StoreGate.h" +#include "StoreGate/StoreGateSvc.h" +#include "TrigNavigation/Holder.h" +#include "TrigNavigation/Holder.icc" + +#include "TrigNavigation/TriggerElement.h" + +#include "TestTypes.h" +#include "TestUtils.h" + +using namespace std; +using namespace HLTNavDetails; +using namespace HLT; +// Hi-lock: (("REPORT_AND_STOP" (0 (quote hi-yellow) t))) + +//const int OK=1; +//const int FAILED=0; + +StoreGateSvc* pStore(0); +HLT::Navigation* hns; + + +template <class T> +std::string view_or_own (T* c) { + return ((c->ownPolicy() == SG::VIEW_ELEMENTS) ? "VIEW" : "OWN"); +} + +TriggerElement * makeTE(HLT::Navigation* hns) { + TriggerElement* initial = hns->getInitialNode(); + TriggerElement* roi = hns->addRoINode(initial); + TriggerElement* te = hns->addNode(roi, 23); + return te; +} + + +TestBContainer* makeContainer(SG::OwnershipPolicy policy, int initval) { + TestBContainer* c = new TestBContainer(); + c->clear(policy); + c->push_back(new TestB(initval)); + c->push_back(new TestB(initval)); + c->push_back(new TestB(initval+1)); + return c; + +} + +StatusCode noMixTest() { + BEGIN_TEST("noMixTest"); + pStore->clearStore(); + hns->reset(); + hns->prepare(); + + TestBContainer *b1 = makeContainer(SG::OWN_ELEMENTS, 2); + TestBContainer *b2 = makeContainer(SG::VIEW_ELEMENTS, 77); + TriggerElement* te = makeTE(hns); + REPORT_AND_CONTINUE("Objects prepared"); + std::string key_back; + + bool stat = hns->attachFeature(te, b1, Navigation::ObjectCreatedByNew, key_back, "BContainer1"); + if ( stat == false ) { + REPORT_AND_STOP("attachFeature failed"); + } + + REPORT_AND_CONTINUE("After attachFeture the container is " << view_or_own(b1)); + + stat = hns->attachFeature(te, b2, Navigation::ObjectCreatedByNew, key_back, "BContainer1"); + if ( stat == true ) { + REPORT_AND_STOP("attachFeature worked while it should not"); + } + REPORT_AND_CONTINUE("The attachFeature was unsuccesfull"); + + END_TEST; +} + +StatusCode firsInsertDecidesPolicy() { + BEGIN_TEST("testing if the insert operation on an empty container makes it a view container"); + pStore->clearStore(); + hns->reset(); + hns->prepare(); + + TestDContainer *b1 = new TestDContainer(); + b1->clear(SG::VIEW_ELEMENTS, SG::NEVER_TRACK_INDICES); + b1->push_back(new TestD(9)); + b1->push_back(new TestD(10)); + + TriggerElement* te = makeTE(hns); + REPORT_AND_CONTINUE("Objects prepared"); + std::string key_back; + + const TestDContainer* ewise(0); + if ( pStore->retrieve(ewise, "HLT_TestDContainer_DContainer1").isFailure() ) { + REPORT_AND_CONTINUE(pStore->dump()); + REPORT_AND_STOP("could not get the event-wise container from SG"); + } + + REPORT_AND_CONTINUE("Event wise container has ownership policy " << view_or_own(ewise)); + if ( view_or_own(ewise) != "OWN" ) { + REPORT_AND_STOP("At start the event wise container is not OWNing"); + } + + // tested code + bool stat = hns->attachFeature(te, b1, Navigation::ObjectCreatedByNew, key_back, "DContainer1"); + if ( stat == false ) { + REPORT_AND_STOP("attachFeature failed"); + } + + ewise = 0; + if ( pStore->retrieve(ewise, "HLT_TestDContainer_DContainer1").isFailure() ) { + REPORT_AND_STOP("could not get the event-wise container from SG"); + } + + REPORT_AND_CONTINUE("After attachFeture the container is " << view_or_own(ewise)); + if ( view_or_own(ewise) != "VIEW" ) { + REPORT_AND_STOP("At end the event wise container is not VIEW"); + } + + END_TEST; +} + + + +int main() { + + + ISvcLocator* pSvcLoc; + if (!Athena_test::initGaudi("test.txt", pSvcLoc)) { + cerr << "ERROR This test can not be run" << endl; + return 0; + } + assert(pSvcLoc); + MsgStream log(Athena::getMessageSvc(), "Ownership_test"); + msglog = &log; + + if( pSvcLoc->service("StoreGateSvc", pStore, true).isSuccess() ) { + *msglog << MSG::DEBUG << "SG pointer: " << pStore << endreq; + } else { + ABORT( "ERROR no SG available" ); + } + + IToolSvc* toolSvc; + + if( pSvcLoc->service("ToolSvc", toolSvc, true).isSuccess() ) { + log << MSG::DEBUG << "ToolSvc pointer: " << toolSvc << endreq; + } else + ABORT ( "no ToolSvc available" ); + + + + IAlgTool* algTool; + if ( toolSvc->retrieveTool("HLT::Navigation/Navigation", algTool).isSuccess() ) { + log << MSG::DEBUG << "OK navigation tool retrieved" << endreq; + hns = dynamic_cast< HLT::Navigation*>(algTool); + if ( hns ) { + log << MSG::DEBUG << "OK navigation casted" << endreq; + } else + ABORT( "navigation cast failed" ); + + } else ABORT("navigation tool NOT retrieved" ); + + if ( firsInsertDecidesPolicy().isFailure() ) + ABORT(""); + + + + if ( noMixTest().isFailure() ) + ABORT(""); + + + + + REPORT_AND_CONTINUE( "END all went fine" ); + return 0; + + *msglog << MSG::INFO << "SUCCESS " << endreq; + *msglog << MSG::DEBUG << "deleting messages below are related to scope exit " << endreq; + + return 0; +} diff --git a/Trigger/TrigEvent/TrigNavigation/test/Registration_test.cxx b/Trigger/TrigEvent/TrigNavigation/test/Registration_test.cxx new file mode 100644 index 0000000000000000000000000000000000000000..8ec41b76f767f76ab30acbabd7dbac11a9c4cb73 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/test/Registration_test.cxx @@ -0,0 +1,102 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include <sys/time.h> +#include <iostream> +#include <iterator> +#include "GaudiKernel/ClassID.h" +#include "GaudiKernel/MsgStream.h" +#include "StoreGate/StoreGate.h" +#include "StoreGate/StoreGateSvc.h" +#include "AthenaKernel/getMessageSvc.h" + +#include "TestTools/initGaudi.h" + + +#include "TrigNavigation/TypeMaps.h" +#include "TrigNavigation/TriggerElement.h" +#include "TrigNavigation/Navigation.h" +#include "TrigNavigation/RoICacheHelper.h" +#include "TrigNavigation/TrigFeatureLink.h" + + + +// tests hack +#include "TestTypes.h" +#include "TestUtils.h" + + +int main () { + + // using namespace Athena_test; + using namespace std; + using namespace HLT; + + + ISvcLocator* pSvcLoc; + if (!Athena_test::initGaudi("test.txt", pSvcLoc)) { + cerr << "ERROR This test can not be run" << endl; + return 0; + } + assert(pSvcLoc); + + + MsgStream log(Athena::getMessageSvc(), "Registration_test"); + msglog = &log; + + + + StoreGateSvc* pStore(0); + + + if( pSvcLoc->service("StoreGateSvc", pStore, true).isSuccess() ) { + log << MSG::DEBUG << "SG pointer: " << pStore << endreq; + } else + ABORT ( "ERROR no SG available" ); + + IToolSvc* toolSvc; + + if( pSvcLoc->service("ToolSvc", toolSvc, true).isSuccess() ) { + log << MSG::DEBUG << "ToolSvc pointer: " << toolSvc << endreq; + } else + ABORT( "ERROR no ToolSvc available" ); + + + HLT::Navigation* hns; + IAlgTool* algTool; + if ( toolSvc->retrieveTool("HLT::Navigation/Navigation", algTool).isSuccess() ) { + log << MSG::DEBUG << "OK navigation tool retrieved" << endreq; + hns = dynamic_cast< HLT::Navigation*>(algTool); + if ( hns ) { + log << MSG::DEBUG << "OK navigation casted" << endreq; + } else + ABORT( "ERROR navigation casted" ); + + } else + ABORT( "ERROR navigation tool NOT retrieved" ); + + + hns->reset( ); + hns->prepare(); + + + /* + TestC* c = new TestC(); + std::string key; + hns->attachFeature(hns->getInitialNode(), c, HLT::Navigation::ObjectCreatedByNew, key); + + TrigFeatureLink fl = hns->object2FeatureLink(hns->getInitialNode(), key, c ); + log << MSG::DEBUG << "fl " << fl.clid() << endreq; + const TestC* c_back = hns->featureLink2Object<TestC>(fl); + if ( c_back != c ) { + log << MSG::ERROR << "failing the TrigFeatureLink get/restore" << endreq; + } else { + log << MSG::DEBUG << "TrigFeatureLink worked ok" << endreq; + } + */ + + log << MSG::DEBUG << pStore->dump() << endreq; + REPORT_AND_CONTINUE ( "Test finished" ); + return 0; +} diff --git a/Trigger/TrigEvent/TrigNavigation/test/RoICache_test.cxx b/Trigger/TrigEvent/TrigNavigation/test/RoICache_test.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e072fe2ea3abb3e9ff5949b14639cba5294dc701 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/test/RoICache_test.cxx @@ -0,0 +1,363 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "GaudiKernel/ClassID.h" +#include "GaudiKernel/MsgStream.h" +#include "StoreGate/StoreGate.h" +#include "StoreGate/StoreGateSvc.h" +#include "AthenaKernel/getMessageSvc.h" + + + +#include "TestTools/initGaudi.h" + +#include "TrigNavigation/TriggerElement.h" + +#include "TrigNavigation/Navigation.h" +#include "TrigNavigation/RoICacheHelper.h" + +#include "TestUtils.h" + +#include "TestTypes.h" +#include "TestUtils.h" + +using namespace HLT; +HLT::Navigation* hns; + +template<class GET, class ATTACH> +class Alg : public RoICacheHelper { +public: + Alg(const std::string& name, GET get, ATTACH attach) + : m_s (name), m_get(get), m_attach(attach) {} + + + StatusCode execute(TriggerElement* output ) { + MsgStream log(Athena::getMessageSvc(), "RoICache_test:"+m_s); + MsgStream *msglog = &log; + BEGIN_TEST("One algorithm test "+m_s); + REPORT_REGTEST("executing on " << output->getId()); + if (needsExecution(output)) { + REPORT_REGTEST( "REAL execution needed on " << output->getId());; + if ( !startCaching(output) ) + REPORT_AND_STOP( "start caching failed " << output->getId() ); + + // imagine hre hard work to work out A and B features + + if ( m_get(output).isFailure() ) + REPORT_AND_STOP( "get failed" ); + if ( m_attach(output).isFailure() ) + REPORT_AND_STOP( "attach failed" ); + + if ( !stopCaching(output) ) + REPORT_AND_STOP("stop Caching failed " << output->getId() ); + } else { + REPORT_REGTEST( "CACHED execution needed on " << output->getId() ); + if ( !cache(output) ){ + REPORT_AND_STOP("The Caching failed " << output->getId() ); + } + } + END_TEST; + } +private: + std::string m_s; + GET m_get; + ATTACH m_attach; +}; + +template<class GET, class ATTACH> +Alg<GET, ATTACH> createAlgo(const std::string& name, GET get, ATTACH attach) { + return Alg<GET, ATTACH>(name, get, attach); +} + + + +int main() { + using namespace std; + + MsgStream log(Athena::getMessageSvc(), "RoICache_test"); + + MsgStream* msglog = &log; + BEGIN_TEST("RoIcaching test"); + + ISvcLocator* pSvcLoc; + if (!Athena_test::initGaudi("test.txt", pSvcLoc)) { + REPORT_AND_STOP("Can not intit Gaudi"); + } + assert(pSvcLoc); + + + StoreGateSvc* pStore(0); + + + if( pSvcLoc->service("StoreGateSvc", pStore, true).isSuccess() ) { + REPORT_AND_CONTINUE("SG pointer: " << pStore ); + } else { + REPORT_AND_STOP("SG not available"); + } + + IToolSvc* toolSvc; + + if( pSvcLoc->service("ToolSvc", toolSvc, true).isSuccess() ) { + REPORT_AND_CONTINUE("ToolSvc pointer obtained: " << toolSvc ); + } else { + REPORT_AND_STOP( "ToolSvc not available"); + } + + + IAlgTool* algTool; + if ( toolSvc->retrieveTool("HLT::Navigation/Navigation", algTool).isSuccess() ) { + REPORT_AND_CONTINUE("OK navigation tool retrieved" ); + hns = dynamic_cast< HLT::Navigation*>(algTool); + if ( hns ) { + REPORT_AND_CONTINUE("OK navigation casted" ); + } else { + REPORT_AND_STOP("navigation not casted" ); + } + } else { + REPORT_AND_STOP( "ERROR navigation tool NOT retrieved" ); + } + + hns->reset(); + + + + TriggerElement* initial = hns->getInitialNode(); + + // we make an RoI with 3 branches 2 identical and one slightly modified (with different feature) + // let's make obejcts first + + TriggerElement* roi0 = hns->addRoINode(initial); + TriggerElement* roi1 = hns->addRoINode(initial); + + std::string key; + TestA* a0 = new TestA(-34); + hns->attachFeature(roi0, a0, Navigation::ObjectCreatedByNew, key, "initialRoI"); + + TestA* a1 = new TestA(-34); + hns->attachFeature(roi1, a1, Navigation::ObjectCreatedByNew, key, "initialRoI"); + + TriggerElement* thresholdA = hns->addNode(roi0, 1); + TriggerElement* thresholdB = hns->addNode(roi0, 2); + TriggerElement* thresholdC = hns->addNode(roi0, 3); + TriggerElement* thresholdD = hns->addNode(roi0, 4); + + TriggerElement* thresholdA1 = hns->addNode(roi1, 1); + + + + // make next layer + TriggerElement* clusterA = hns->addNode(thresholdA, 11); + TriggerElement* clusterB = hns->addNode(thresholdB, 12); + TriggerElement* clusterC = hns->addNode(thresholdC, 13); + TriggerElement* clusterD = hns->addNode(thresholdD, 14); + + TriggerElement* clusterA1 = hns->addNode(thresholdA1, 1200); + + REPORT_AND_CONTINUE("Navigation structure built"); + + auto calo = createAlgo("calo", + [](TriggerElement* te) -> StatusCode { // get RoI + const TestA* back(0); + const TriggerElement* tsource; + std::string lsource; + hns->getRecentFeature(te, back, "", tsource, lsource); + return StatusCode::SUCCESS; + }, + [](TriggerElement* te) -> StatusCode { // produces xAOD like type TestBContainer + TestBContainer* a = new TestBContainer; + TestAuxB aux; + a->setStore(&aux); + std::string key; + hns->attachFeature(te, a, Navigation::ObjectCreatedByNew, key, "made_by_calo"); + return StatusCode::SUCCESS; + }); + if( calo.execute(clusterA).isFailure() ) ABORT(""); + if( calo.execute(clusterB).isFailure() ) ABORT(""); + if( calo.execute(clusterC).isFailure() ) ABORT(""); + if( calo.execute(clusterD).isFailure() ) ABORT(""); + + if( calo.execute(clusterA1).isFailure() ) ABORT(""); + + REPORT_AND_CONTINUE("Executed calo on clusters"); + + // idea here is that only two clusters out of 4 obtain extra object + // next algo will depend on this extra objects and there shoudl be apropriate caching kicking in only wto times + auto caloaux = createAlgo("caux", + [](TriggerElement* te) -> StatusCode { // require TestBContainer + const TestBContainer* back(0); + const TriggerElement* tsource; + std::string lsource; + hns->getRecentFeature(te, back, "", tsource, lsource); + return StatusCode::SUCCESS; + }, + [](TriggerElement* te) -> StatusCode { + TestA* a = new TestA(-38); + std::string key; + hns->attachFeature(te, a, Navigation::ObjectCreatedByNew, key, "refined_by_aux"); + return StatusCode::SUCCESS; + } + ); + if( caloaux.execute(clusterC).isFailure() ) ABORT(""); + if( caloaux.execute(clusterD).isFailure() ) ABORT(""); + + + + //log << MSG::INFO << "\n" << *hns << endreq; + + auto calo2 = createAlgo("calo2", + [&](TriggerElement* te) -> StatusCode { // get RoI + const TestA* back(0); + const TriggerElement* tsource; + std::string lsource; + hns->getRecentFeature(te, back, "", tsource, lsource); + REPORT_AND_CONTINUE("got back object " << back->value()); + return StatusCode::SUCCESS; + }, + [](TriggerElement* te) -> StatusCode { // produces xAOD like type TestBContainer + TestBContainer* a = new TestBContainer; + TestAuxB aux; + a->setStore(&aux); + std::string key; + hns->attachFeature(te, a, Navigation::ObjectCreatedByNew, key, "made_by_calo2"); + return StatusCode::SUCCESS; + }); + if( calo2.execute(clusterD).isFailure() ) ABORT(""); + if( calo2.execute(clusterC).isFailure() ) ABORT(""); + if( calo2.execute(clusterB).isFailure() ) ABORT(""); + if( calo2.execute(clusterA).isFailure() ) ABORT(""); + + if( calo2.execute(clusterA1).isFailure() ) ABORT(""); + + REPORT_AND_CONTINUE("Executed c2 on clusters"); + + + + //log << MSG::INFO << "\n" << *hns << endreq; + + + TriggerElement* trackA = hns->addNode(clusterA, 101); + TriggerElement* trackB = hns->addNode(clusterB, 102); + TriggerElement* trackC = hns->addNode(clusterC, 103); + TriggerElement* trackD = hns->addNode(clusterD, 104); + + + TriggerElement* trackA1 = hns->addNode(clusterA1, 10100); + + + // we expect now high level of caching as we dpend on the common object + auto trk = createAlgo("trk", + [&](TriggerElement* te) -> StatusCode { // get RoI + const TestA* back(0); + const TriggerElement* tsource; + std::string lsource; + hns->getRecentFeature(te, back, "initialRoI", tsource, lsource); + if ( back ) REPORT_AND_CONTINUE("got back object " << back->value()); + return StatusCode::SUCCESS; + }, + [](TriggerElement* te) -> StatusCode { // produces xAOD like type TestBContainer + TestC* a = new TestC(77); + std::string key; + hns->attachFeature(te, a, Navigation::ObjectCreatedByNew, key, "made_by_trk"); + return StatusCode::SUCCESS; + }); + if( trk.execute(trackB).isFailure() ) ABORT(""); + if( trk.execute(trackD).isFailure() ) ABORT(""); + if( trk.execute(trackC).isFailure() ) ABORT(""); + if( trk.execute(trackA).isFailure() ) ABORT(""); + if( trk.execute(trackA1).isFailure() ) ABORT(""); + + + + REPORT_AND_CONTINUE("Executed trk"); + + // now lets make the TrackA look different by attaching there an object of different type + { + TestC* c = new TestC(55); + std::string key; + hns->attachFeature(trackA, c, Navigation::ObjectCreatedByNew, key, "made_by_tr2"); + } + + + + + TriggerElement* eleA = hns->addNode(trackA, 1001); + TriggerElement* eleB = hns->addNode(trackB, 1002); + TriggerElement* eleC = hns->addNode(trackC, 1003); + TriggerElement* eleD = hns->addNode(trackD, 1004); + + TriggerElement* eleA1 = hns->addNode(trackA1, 100100); + + + auto matcher = createAlgo("matcher", + [&](TriggerElement* te) -> StatusCode { // get RoI + const TestC* back(0); + const TriggerElement* tsource; + std::string lsource; + hns->getRecentFeature(te, back, "", tsource, lsource); + if ( back ) { + REPORT_AND_CONTINUE("got back object " << back->value()); + } else { + REPORT_AND_CONTINUE("no object retrieved"); + } + return StatusCode::SUCCESS; + }, + [](TriggerElement* te) -> StatusCode { // produces xAOD like type TestBContainer + TestDContainer* a = new TestDContainer; + a->push_back(new TestD(98)); + std::string key; + hns->attachFeature(te, a, Navigation::ObjectCreatedByNew, key, "made_by_ma"); + return StatusCode::SUCCESS; + }); + if( matcher.execute(eleA).isFailure() ) ABORT(""); + if( matcher.execute(eleB).isFailure() ) ABORT(""); + if( matcher.execute(eleC).isFailure() ) ABORT(""); + if( matcher.execute(eleD).isFailure() ) ABORT(""); + if( matcher.execute(eleA1).isFailure() ) ABORT(""); + REPORT_AND_CONTINUE("Executed ma on electron TEs"); + + + + + + // now make another topological TEs and check caching on them + // A bit of explanation. + // We make 3 topological TEs. + // In terms of RoIs used in them they are identical (i.e. both use roi0, roi1 pair) + // Execution lines leading to eleC and eleD are identical. I.e. all algorithms cached. + // While execution line leading to eleA is different. We should observe that + // there shoudl be caching on ovCA1 and ovDA1 while ovAA1 shoudl always be executed. + // + std::vector<TriggerElement*> v; + v.push_back(eleC); + v.push_back(eleA1); + + TriggerElement* ovCA1 = hns->addNode(v, 222); + v[0] = eleD; + TriggerElement* ovDA1 = hns->addNode(v, 223); + v[0] = eleA; + TriggerElement* ovAA1 = hns->addNode(v, 224); + + auto overlap = createAlgo ("overlap", + [&](TriggerElement* te) -> StatusCode { // get obj made by ma + const TestDContainer* back(0); + const TriggerElement* tsource; + std::string lsource; + hns->getRecentFeature(te, back, "", tsource, lsource); + return StatusCode::SUCCESS; + }, + [](TriggerElement* ) -> StatusCode { + return StatusCode::SUCCESS; + }); + if ( overlap.execute(ovCA1).isFailure() ) ABORT(""); + if ( overlap.execute(ovDA1).isFailure() ) ABORT(""); + if ( overlap.execute(ovAA1).isFailure() ) ABORT(""); + + + REPORT_AND_CONTINUE("Executed on topo TEs"); + REPORT_AND_CONTINUE("ALLOK"); + + + //log << MSG::INFO << *hns << endreq; + return 0; +} diff --git a/Trigger/TrigEvent/TrigNavigation/test/TestTypes.h b/Trigger/TrigEvent/TrigNavigation/test/TestTypes.h new file mode 100644 index 0000000000000000000000000000000000000000..c9f924665c9da1fb8d398384e17d234a3c1195c0 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/test/TestTypes.h @@ -0,0 +1,118 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#pragma once + +#include "AthContainers/AuxElement.h" +#include "xAODCore/AuxContainerBase.h" + +#define TRIGSTORAGEDEF_MERGEPACKS +#include "TrigNavigation/TypeRegistration.h" + +HLT_BEGIN_TYPE_REGISTRATION + HLT_REGISTER_TYPE(struct TestA, struct TestA, struct DataVector<TestA>, struct TestAuxA) + HLT_REGISTER_TYPE(struct TestB, struct TestBContainer, struct TestBContainer, struct TestAuxB) + HLT_REGISTER_TYPE(struct TestC, struct TestC, struct DataVector<TestC>) + HLT_REGISTER_TYPE(struct TestD, struct TestDContainer, struct TestDContainer) +HLT_END_TYPE_REGISTRATION(TrigNavigationUnitTest) + +#define LTYPEMAPCLASS(name)\ + struct class_##name{\ + typedef TypeInfo_##name map;\ + static const std::string package_name;\ + }; + +LTYPEMAPCLASS(TrigNavigationUnitTest) + +struct TypeInfo_EDM { + typedef HLT::TypeInformation::newlist + ::add<class_TrigNavigationUnitTest> ::go + ::done map; +}; +REGISTER_PACKAGE_WITH_NAVI(TrigNavigationUnitTest) + +class TestA : public SG::AuxElement { +public: + TestA(){a = 0;} + TestA(int arg){a = arg;} + ~TestA() { std::cerr << " deleteing TestA: "<< a << std::endl; } + int value() const { return a; } + int a; +}; + + +CLASS_DEF(TestA, 6421, 1) +CLASS_DEF(DataVector<TestA>, 64210, 1) +typedef DataVector<TestA> TestAContainer; + + +class TestAuxA : public xAOD::AuxContainerBase { +public: + std::vector<float> detail; +}; +DATAVECTOR_BASE(TestAuxA,xAOD::AuxContainerBase); +CLASS_DEF(TestAuxA, 642300, 1) + + +class TestB : public SG::AuxElement{ +public: + TestB() : b(0) { } + TestB(int v) : b(v) { } + ~TestB() { std::cerr << " deleteing TestB: "<< b << std::endl; } + int value() const { return b; } + int b; +}; + + +class TestBContainer : public DataVector<TestB> { +public: + TestBContainer(SG::OwnershipPolicy policy = SG::OWN_ELEMENTS) + : DataVector<TestB>(policy) { } +}; + +CLASS_DEF(TestBContainer, 96422, 1) + + + +class TestAuxB : public xAOD::AuxContainerBase { +public: + std::vector<float> detail; +}; +CLASS_DEF(TestAuxB, 642311, 1) +DATAVECTOR_BASE(TestAuxB,xAOD::AuxContainerBase); +//HLT::AuxInit<TestAuxB> t; + + +class TestC { +public: + TestC() :c(0) {} + TestC(int v) : c(v) {} + ~TestC() {std::cerr << "Deleting TestC" << std::endl; } + int value() const { return c; } + int c; +}; + +CLASS_DEF(TestC, 7800, 1) +CLASS_DEF(DataVector<TestC>, 78001, 1) + +class TestCtypeContainer : public DataVector<TestC> { }; +CLASS_DEF(TestCtypeContainer, 78002, 1) + +class TestD { +public: + TestD() : b(0) { } + TestD(int v) : b(v) { } + ~TestD() { std::cerr << " deleteing TestD: "<< b << std::endl; } + int value() const { return b; } + int b; +}; + + +class TestDContainer : public DataVector<TestD> { +public: + +}; + +CLASS_DEF(TestDContainer, 96477, 1) + diff --git a/Trigger/TrigEvent/TrigNavigation/test/TestUtils.h b/Trigger/TrigEvent/TrigNavigation/test/TestUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..c639abd439aa95032a7e2ac4712810c2892ba68b --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/test/TestUtils.h @@ -0,0 +1,21 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#pragma once +MsgStream* msglog; + +#define _LINE_ __LINE__ +#define REPORT_AND_RETURN(__message, __ret) { *msglog << MSG::ERROR << "LINE:" <<_LINE_ << " Test failed: " << __message << endreq; return __ret; } +#define REPORT_AND_STOP(__message) REPORT_AND_RETURN(__message, StatusCode::FAILURE) +#define ABORT(__message) REPORT_AND_RETURN(__message, -1) + + +#define REPORT_AND_CONTINUE(__message) {*msglog << MSG::INFO << "LINE:" <<_LINE_ << " Test progress fine: " << __message << endreq;} +#define REPORT_REGTEST(__message) {*msglog << MSG::INFO << "REGTEST " << __message << endreq;} + + + +#define BEGIN_TEST(__name) const std::string __TEST_NAME=__name; \ + *msglog << MSG::INFO << "LINE:" <<_LINE_ << " Start of the test: " << __TEST_NAME << endreq +#define END_TEST *msglog << MSG::INFO << "LINE:" <<_LINE_ << " End of the test: " << __TEST_NAME << endreq; return StatusCode::SUCCESS diff --git a/Trigger/TrigEvent/TrigNavigation/test/TrigNavigation.xml b/Trigger/TrigEvent/TrigNavigation/test/TrigNavigation.xml new file mode 100644 index 0000000000000000000000000000000000000000..14139199f56b4bee36fd5e6f918ffb504fa7d32b --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/test/TrigNavigation.xml @@ -0,0 +1,12 @@ +<?xml version="1.0"?> +<atn> + <TEST name="TrigNavigationTest" type="makecheck" suite="trigger"> + <package>Trigger/TrigEvent/TrigNavigation</package> + <timelimit>15</timelimit> + <author> Tomasz Bold </author> + <mailto> Tomasz.Bold@cern.ch</mailto> + <expectations> + <returnValue>0</returnValue> + </expectations> + </TEST> +</atn> diff --git a/Trigger/TrigEvent/TrigNavigation/test/TriggerElement_test.cxx b/Trigger/TrigEvent/TrigNavigation/test/TriggerElement_test.cxx new file mode 100644 index 0000000000000000000000000000000000000000..cccd501c110f1d39271ff767a80751b74cf2d228 --- /dev/null +++ b/Trigger/TrigEvent/TrigNavigation/test/TriggerElement_test.cxx @@ -0,0 +1,96 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include <vector> +#include "TrigNavigation/TriggerElement.h" + + +#include "TestTools/initGaudi.h" +#include "AthenaKernel/getMessageSvc.h" +#include "GaudiKernel/MsgStream.h" + + +#include "TestUtils.h" + +using namespace std; +using namespace HLT; + +StatusCode unit0(const TriggerElement::ObjectIndex& orig, unsigned expSerializedSize, MsgStream& log ) { + BEGIN_TEST("Unit0 test"); + vector<uint32_t> serial; + vector<uint32_t>::const_iterator sIt; + TriggerElement::ObjectIndex deserial; + orig.serialize(serial); + + if (serial.size() != expSerializedSize) + REPORT_AND_STOP( "orig ObjIdx serialized has size != " << expSerializedSize << " " << serial.size() ); + + for ( sIt = serial.begin(); sIt != serial.end(); ++sIt ) { + log << MSG::INFO << "serialized word: 0x" << MSG::hex << *sIt << MSG::dec << endreq; + } + sIt = serial.begin(); + deserial.deserialize(sIt); + + if ( deserial.isSameOrWithin(&orig) && orig.isSameOrWithin(&deserial)) { + log << MSG::INFO << "serialziation works well for orig " << orig << endreq; + log << MSG::INFO << "original " << orig << endreq; + log << MSG::INFO << "deserialized " << deserial << endreq; + + } else REPORT_AND_STOP( "orig ObjIdx serialization failed " ); + + END_TEST; + +} + + +int main () { + + /* + ISvcLocator* pSvcLoc; + if (!Athena_test::initGaudi("test.txt", pSvcLoc)) { + cerr << "ERROR This test can not be run" << endl; + return 0; + } + assert(pSvcLoc); + */ + + MsgStream log(Athena::getMessageSvc(), "TriggerElement_test"); + msglog = &log; + + log << MSG::INFO << "small " << endreq; + // test ObjectIndex: + TriggerElement::ObjectIndex small1(12, 4, 5); + if ( unit0(small1, 1, log).isFailure() ) + ABORT(""); + + TriggerElement::ObjectIndex small2(15, 4, 7); + if ( unit0(small2, 1, log).isFailure() ) + ABORT(""); + + + REPORT_AND_CONTINUE("big "); + TriggerElement::ObjectIndex big1(345, 60000, 60001); + if ( unit0(big1, 2, log).isFailure() ) + ABORT(""); + + TriggerElement::ObjectIndex big2(345, 60000, 62345); + if ( unit0(big2, 2, log).isFailure() ) + ABORT(""); + + + log << MSG::INFO << "huge " << endreq; + try { + TriggerElement::ObjectIndex huge1(12, 65535, 65536); + if ( unit0(huge1, 3, log).isFailure() ) + ABORT(""); + } catch (std::exception& ex) { + ABORT("Execption from the test " << ex.what() ); + } + TriggerElement::ObjectIndex huge2(12, 820000, 820001); + if ( unit0(huge2, 3, log).isFailure() ) + ABORT(""); + + REPORT_AND_CONTINUE("SUCCESS"); + return 0; +}