diff --git a/Control/AthViews/AthViews/SimpleView.h b/Control/AthViews/AthViews/SimpleView.h index 466c9cf90ecfa50bf0e627210f6e9805a39bf7e1..c689a45dbd44ca05350172d8b7130b72577c6812 100644 --- a/Control/AthViews/AthViews/SimpleView.h +++ b/Control/AthViews/AthViews/SimpleView.h @@ -43,6 +43,13 @@ class SimpleView : public IProxyDict /*virtual SG::DataProxy* proxy(const CLID& id) const { return 0; };*/ + /** + * @brief links to the previously used views + * though this additional parent views additional data abject become availbe + **/ + void linkParent( const IProxyDict* parent ); + + /// get proxy for a given data object address in memory, /// but performs a deep search among all possible 'symlinked' containers // TEMPORARY: This method is going away. @@ -174,6 +181,7 @@ class SimpleView : public IProxyDict //Connection to the whole event store ServiceHandle< StoreGateSvc > m_store; std::string m_name; + std::vector<const IProxyDict*> m_parents; }; diff --git a/Control/AthViews/AthViews/View.h b/Control/AthViews/AthViews/View.h index 67114dbcffe8e0514f46c472868bad380ea550e7..b2eaa9af4ed516f8cf65fb54d562a3584a020612 100644 --- a/Control/AthViews/AthViews/View.h +++ b/Control/AthViews/AthViews/View.h @@ -8,7 +8,7 @@ #define ATHVIEWS_VIEW_H #include "AthenaKernel/IProxyDict.h" - +#include "AthViews/SimpleView.h" // DECLARATIONS namespace SG { class DataProxy; @@ -25,7 +25,7 @@ public: View (const View&) = delete; View& operator= (const View&) = delete; - void impl ( IProxyDict* impl ) { m_implementation = impl; } + void impl ( SimpleView* impl ) { m_implementation = impl; } IProxyDict* impl (void ) { return m_implementation; } const IProxyDict* impl (void ) const { return m_implementation; } @@ -34,6 +34,10 @@ public: return m_implementation->proxy(id); }*/ + void linkParent( const IProxyDict* parent) { + m_implementation->linkParent( parent ); + } + virtual SG::DataProxy* deep_proxy(const void* const pTransient) const { return m_implementation->proxy (pTransient); @@ -105,7 +109,7 @@ public: virtual void registerKey( IStringPool::sgkey_t key, const std::string& str, CLID clid ){ m_implementation->registerKey( key, str, clid ); } private: - IProxyDict *m_implementation; + SimpleView *m_implementation; }; } // EOF SG namespace diff --git a/Control/AthViews/CMakeLists.txt b/Control/AthViews/CMakeLists.txt index 3e2d1dbddbbfe81bbe2b40b3df1f26abeb201338..c628e4f38c7bdd14bd2dafcd32ee18560c1e4670 100644 --- a/Control/AthViews/CMakeLists.txt +++ b/Control/AthViews/CMakeLists.txt @@ -17,7 +17,8 @@ atlas_depends_on_subdirs( PUBLIC Trigger/TrigEvent/TrigSteeringEvent GaudiKernel PRIVATE - Control/CxxUtils ) + Control/CxxUtils + AtlasTest/TestTools ) # Component(s) in the package: atlas_add_library( AthViews @@ -33,6 +34,12 @@ atlas_add_component( AthViewsDFlow INCLUDE_DIRS ${TBB_INCLUDE_DIRS} LINK_LIBRARIES ${TBB_LIBRARIES} AthenaBaseComps AthenaKernel SGTools StoreGateLib GaudiKernel CxxUtils AthViews TrigSteeringEvent ) + +atlas_add_test( ViewLinking_test + INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${TBB_INCLUDE_DIRS} + SOURCES test/ViewLinking_test.cxx + LINK_LIBRARIES ${Boost_LIBRARIES} ${TBB_LIBRARIES} AthViews ) + # Install files from the package: atlas_install_headers( AthViews ) atlas_install_joboptions( share/*.py ) diff --git a/Control/AthViews/src/SimpleView.cxx b/Control/AthViews/src/SimpleView.cxx index dcc855168bde4c55d0b8b5c1f68c2b433e6a6996..62e7a649328c2ec041076347fb09b85f7c6e347c 100644 --- a/Control/AthViews/src/SimpleView.cxx +++ b/Control/AthViews/src/SimpleView.cxx @@ -3,6 +3,7 @@ */ #include <iostream> +#include <stdexcept> #include "AthViews/SimpleView.h" using namespace std; @@ -23,6 +24,10 @@ SimpleView::~SimpleView() { } +void SimpleView::linkParent( const IProxyDict* parent ) { + m_parents.push_back( parent ); +} + /** * @brief Get proxy given a hashed key+clid. @@ -55,7 +60,17 @@ SG::DataProxy * SimpleView::proxy_exact( SG::sgkey_t sgkey ) const SG::DataProxy * SimpleView::proxy( const CLID& id, const std::string& key ) const { const std::string viewKey = m_name + "_" + key; - return m_store->proxy( id, viewKey ); + auto local = m_store->proxy( id, viewKey ); + + for ( auto parent: m_parents ) { + auto dp = parent->proxy( id, key ); + if ( dp and not local ) { + return dp; + } else if ( dp and local ) { + throw std::runtime_error("Duplicate object CLID:"+ std::to_string(id) + " key: " + key + " found in views: " + name()+ " and parent " + parent->name() ); + } // else search further + } + return local; // can be the nullptr still } diff --git a/Control/AthViews/test/ViewLinking_test.cxx b/Control/AthViews/test/ViewLinking_test.cxx new file mode 100644 index 0000000000000000000000000000000000000000..007821a6752c648c1ca7b3075c5b122d1821deea --- /dev/null +++ b/Control/AthViews/test/ViewLinking_test.cxx @@ -0,0 +1,147 @@ +/* + 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 "StoreGate/ReadHandle.h" +#include "StoreGate/WriteHandle.h" + +#include "TestTools/initGaudi.h" +#include "TestTools/expect.h" +#include "TestTools/expect_exception.h" +#include "AthViews/View.h" + +struct TestClass { + int value = 0; +}; + +CLASS_DEF( TestClass , 16530831 , 1 ) +using namespace SG; +void testDataInView( StoreGateSvc* /*sg*/ , MsgStream& log ) { + auto parentView = new View( "ParentView" ); + + auto t1 = std::make_unique<TestClass>(); + t1->value = 1; + // auto status1 = parentView->recordObject( t1, "test1" ); + + { + SG::WriteHandle<TestClass> wh( "test1" ); + wh.setProxyDict( parentView ); + auto status = wh.record( std::move( t1 ) ); + VALUE( status.isSuccess() ) EXPECTED( true ); + } + + auto childView = new View( "ChildView" ); + + + auto t2 = std::make_unique<TestClass>(); + t2->value = 2; + { + SG::WriteHandle<TestClass> wh( "test2" ); + wh.setProxyDict( childView ); + auto status = wh.record( std::move( t2 ) ); + VALUE( status.isSuccess() ) EXPECTED( true ); + } + // auto status2 = childView->recordObject( t2, "test1" ); + // all prepared, will start testing if querries respond correctly + { + // rtivial test, we ask for a wrong object + SG::ReadHandle<TestClass> rh( "test" ); + rh.setProxyDict( childView ); + VALUE( rh.isValid() ) EXPECTED( false ); + } + + + + { + SG::ReadHandle<TestClass> rh( "test2" ); + rh.setProxyDict( childView ); + VALUE( rh.isValid() ) EXPECTED( true ); + VALUE( rh->value ) EXPECTED( 2 ); + } + + { + SG::ReadHandle<TestClass> rh( "test1" ); + rh.setProxyDict( childView ); + VALUE( rh.isValid() ) EXPECTED( false ); + } + log << MSG::INFO << "Views that are not linked behave correctly " << endmsg; + // link them and see if data object is accessible + childView->linkParent( parentView ); + + { + SG::ReadHandle<TestClass> rh( "test2" ); + rh.setProxyDict( childView ); + VALUE( rh.isValid() ) EXPECTED( true ); + VALUE( rh->value ) EXPECTED( 2 ); + } + { + SG::ReadHandle<TestClass> rh( "test1" ); + rh.setProxyDict( childView ); + VALUE( rh.isValid() ) EXPECTED( true ); + VALUE( rh->value ) EXPECTED( 1 ); + } + log << MSG::INFO << "Views that are linked behave correctly " << endmsg; + + // hide object from parent by adding one in the Child + auto t3 = std::make_unique<TestClass>(); + t3->value = 3; + + { + SG::WriteHandle<TestClass> wh( "test1" ); + wh.setProxyDict( childView ); + auto status = wh.record( std::move( t3 ) ); + VALUE( status.isSuccess() ) EXPECTED( true ); + } + + + { + SG::ReadHandle<TestClass> rh( "test1" ); + rh.setProxyDict( childView ); + EXPECT_EXCEPTION( std::runtime_error, rh.isValid() ); + } + log << MSG::INFO << "Hiding works as expected " << endmsg; + + +} + + + +int main() { + using namespace std; + + MsgStream log(Athena::getMessageSvc(), "ViewLinking_test"); + + // MsgStream* msglog = &log; + + + ISvcLocator* pSvcLoc; + //if (!Athena_test::initGaudi("test.txt", pSvcLoc)) { + if (!Athena_test::initGaudi("", pSvcLoc)) { + log << MSG::ERROR << "Can not intit Gaudi" << endmsg; + return -1; + } + assert(pSvcLoc); + + + StoreGateSvc* pStore(0); + + + if( pSvcLoc->service("StoreGateSvc", pStore, true).isSuccess() ) { + log << MSG::INFO << "SG pointer: " << pStore << endmsg; + } else { + log << MSG::ERROR << "SG not available" << endmsg; + return -1; + } + + + + testDataInView( pStore, log ); + log << MSG::INFO << "linking function w/o overlap works" << endmsg; + + return 0; +}