LCOV - code coverage report
Current view: top level - eq/fabric - node.ipp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 137 157 87.3 %
Date: 2014-06-18 Functions: 36 54 66.7 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2010-2014, Stefan Eilemann <eile@eyescale.ch>
       3             :  *                    2010, Cedric Stalder <cedric.stalder@gmail.com>
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or modify it under
       6             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       7             :  * by the Free Software Foundation.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      10             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      11             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      12             :  * details.
      13             :  *
      14             :  * You should have received a copy of the GNU Lesser General Public License
      15             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      16             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      17             :  */
      18             : 
      19             : #include "node.h"
      20             : 
      21             : #include "elementVisitor.h"
      22             : #include "leafVisitor.h"
      23             : #include "log.h"
      24             : #include "paths.h"
      25             : 
      26             : #include <co/dataIStream.h>
      27             : #include <co/dataOStream.h>
      28             : 
      29             : namespace eq
      30             : {
      31             : namespace fabric
      32             : {
      33             : namespace
      34             : {
      35             : #define MAKE_ATTR_STRING( attr ) ( std::string("EQ_NODE_") + #attr )
      36             : 
      37          42 : std::string _iAttributeStrings[] = {
      38             :     MAKE_ATTR_STRING( IATTR_THREAD_MODEL ),
      39             :     MAKE_ATTR_STRING( IATTR_LAUNCH_TIMEOUT ),
      40             :     MAKE_ATTR_STRING( IATTR_HINT_AFFINITY )
      41          21 : };
      42             : 
      43             : }
      44             : 
      45             : template< class C, class N, class P, class V >
      46         476 : Node< C, N, P, V >::Node( C* parent )
      47             :         : _config( parent )
      48         476 :         , _isAppNode( false )
      49             : {
      50         476 :     parent->_addNode( static_cast< N* >( this ) );
      51         476 :     LBLOG( LOG_INIT ) << "New " << lunchbox::className( this ) << std::endl;
      52         476 : }
      53             : 
      54             : template< class C, class N, class P, class V >
      55         445 : Node< C, N, P, V >::~Node()
      56             : {
      57         445 :     LBLOG( LOG_INIT ) << "Delete " << lunchbox::className( this ) << std::endl;
      58        1477 :     while( !_pipes.empty() )
      59             :     {
      60         587 :         P* pipe = _pipes.back();
      61         587 :         LBASSERT( pipe->getNode() == static_cast< N* >( this ) );
      62         587 :         _removePipe( pipe );
      63         587 :         delete pipe;
      64             :     }
      65             : 
      66         445 :     _config->_removeNode( static_cast< N* >( this ) );
      67         890 : }
      68             : 
      69             : template< class C, class N, class P, class V >
      70         952 : Node< C, N, P, V >::BackupData::BackupData()
      71             : {
      72         952 :     memset( iAttributes, 0xff, IATTR_ALL * sizeof( int32_t ));
      73         952 : }
      74             : 
      75             : template< class C, class N, class P, class V >
      76          15 : void Node< C, N, P, V >::backup()
      77             : {
      78          15 :     Object::backup();
      79          15 :     _backup = _data;
      80          15 : }
      81             : 
      82             : template< class C, class N, class P, class V >
      83           2 : void Node< C, N, P, V >::restore()
      84             : {
      85           2 :     _data = _backup;
      86           2 :     Object::restore();
      87           2 : }
      88             : 
      89             : template< class C, class N, class P, class V >
      90          44 : uint128_t Node< C, N, P, V >::commit( const uint32_t incarnation )
      91             : {
      92          44 :     if( Serializable::isDirty( DIRTY_PIPES ))
      93          26 :         commitChildren( _pipes, incarnation );
      94          44 :     return Object::commit( incarnation );
      95             : }
      96             : 
      97             : template< class C, class N, class P, class V > void
      98          35 : Node< C, N, P, V >::serialize( co::DataOStream& os, const uint64_t dirtyBits )
      99             : {
     100          35 :     Object::serialize( os, dirtyBits );
     101          35 :     if( dirtyBits & DIRTY_ATTRIBUTES )
     102          24 :         os << co::Array< int32_t >( _data.iAttributes, IATTR_ALL );
     103          35 :     if( dirtyBits & DIRTY_PIPES && isMaster( ))
     104             :     {
     105          27 :         os << _mapNodeObjects();
     106          27 :         os.serializeChildren( _pipes );
     107             :     }
     108          35 :     if( dirtyBits & DIRTY_MEMBER )
     109           8 :         os << _isAppNode;
     110          35 : }
     111             : 
     112             : template< class C, class N, class P, class V > void
     113          23 : Node< C, N, P, V >::deserialize( co::DataIStream& is, const uint64_t dirtyBits)
     114             : {
     115          23 :     Object::deserialize( is, dirtyBits );
     116          23 :     if( dirtyBits & DIRTY_ATTRIBUTES )
     117          19 :         is >> co::Array< int32_t >( _data.iAttributes, IATTR_ALL );
     118          23 :     if( dirtyBits & DIRTY_PIPES )
     119             :     {
     120          15 :         if( isMaster( ))
     121           0 :             syncChildren( _pipes );
     122             :         else
     123             :         {
     124          15 :             const bool useChildren = is.read< bool >();
     125          15 :             if( useChildren && _mapNodeObjects( ))
     126             :             {
     127           0 :                 Pipes result;
     128           0 :                 is.deserializeChildren( this, _pipes, result );
     129           0 :                 _pipes.swap( result );
     130           0 :                 LBASSERT( _pipes.size() == result.size( ));
     131             :             }
     132             :             else // consume unused ObjectVersions
     133          15 :                 is.read< co::ObjectVersions >();
     134             :         }
     135             :     }
     136          23 :     if( dirtyBits & DIRTY_MEMBER )
     137           8 :         is >> _isAppNode;
     138          23 : }
     139             : 
     140             : template< class C, class N, class P, class V >
     141       32254 : void Node< C, N, P, V >::setDirty( const uint64_t dirtyBits )
     142             : {
     143       32254 :     Object::setDirty( dirtyBits );
     144       32254 :     _config->setDirty( C::DIRTY_NODES );
     145       32254 : }
     146             : 
     147             : template< class C, class N, class P, class V >
     148          23 : void Node< C, N, P, V >::notifyDetach()
     149             : {
     150          23 :     Object::notifyDetach();
     151          46 :     while( !_pipes.empty( ))
     152             :     {
     153          15 :         P* pipe = _pipes.back();
     154          15 :         if( !pipe->isAttached( ))
     155             :         {
     156          15 :             LBASSERT( isMaster( ));
     157          38 :             return;
     158             :         }
     159             : 
     160           0 :         LBASSERT( !isMaster( ));
     161           0 :         getLocalNode()->unmapObject( pipe );
     162           0 :         _removePipe( pipe );
     163           0 :         _config->getServer()->getNodeFactory()->releasePipe( pipe );
     164             :     }
     165             : }
     166             : 
     167             : template< class C, class N, class P, class V >
     168           0 : void Node< C, N, P, V >::create( P** pipe )
     169             : {
     170           0 :     *pipe = _config->getServer()->getNodeFactory()->createPipe(
     171             :         static_cast< N* >( this ));
     172           0 : }
     173             : 
     174             : template< class C, class N, class P, class V >
     175           0 : void Node< C, N, P, V >::release( P* pipe )
     176             : {
     177           0 :     _config->getServer()->getNodeFactory()->releasePipe( pipe );
     178           0 : }
     179             : 
     180             : namespace
     181             : {
     182             : template< class N, class V >
     183       12227 : VisitorResult _accept( N* node, V& visitor )
     184             : {
     185       12227 :     VisitorResult result = visitor.visitPre( node );
     186       12227 :     if( result != TRAVERSE_CONTINUE )
     187         241 :         return result;
     188             : 
     189       11986 :     const typename N::Pipes& pipes = node->getPipes();
     190       78549 :     for( typename N::Pipes::const_iterator i = pipes.begin();
     191       52366 :          i != pipes.end(); ++i )
     192             :     {
     193       17125 :         switch( (*i)->accept( visitor ))
     194             :         {
     195             :             case TRAVERSE_TERMINATE:
     196        2928 :                 return TRAVERSE_TERMINATE;
     197             : 
     198             :             case TRAVERSE_PRUNE:
     199          40 :                 result = TRAVERSE_PRUNE;
     200          40 :                 break;
     201             : 
     202             :             case TRAVERSE_CONTINUE:
     203             :             default:
     204       14157 :                 break;
     205             :         }
     206             :     }
     207             : 
     208        9058 :     switch( visitor.visitPost( node ))
     209             :     {
     210             :         case TRAVERSE_TERMINATE:
     211           0 :             return TRAVERSE_TERMINATE;
     212             : 
     213             :         case TRAVERSE_PRUNE:
     214           0 :             return TRAVERSE_PRUNE;
     215             : 
     216             :         case TRAVERSE_CONTINUE:
     217             :         default:
     218        9058 :             break;
     219             :     }
     220             : 
     221        9058 :     return result;
     222             : }
     223             : }
     224             : 
     225             : template< class C, class N, class P, class V >
     226       12227 : VisitorResult Node< C, N, P, V >::accept( V& visitor )
     227             : {
     228       12227 :     return _accept( static_cast< N* >( this ), visitor );
     229             : }
     230             : 
     231             : template< class C, class N, class P, class V >
     232           0 : VisitorResult Node< C, N, P, V >::accept( V& visitor ) const
     233             : {
     234           0 :     return _accept( static_cast< const N* >( this ), visitor );
     235             : }
     236             : 
     237             : template< class C, class N, class P, class V >
     238         120 : NodePath Node< C, N, P, V >::getPath() const
     239             : {
     240         120 :     const C* config = static_cast< const N* >( this )->getConfig( );
     241         120 :     LBASSERT( config );
     242             : 
     243         120 :     const typename std::vector< N* >& nodes = config->getNodes();
     244             :     typename std::vector< N* >::const_iterator i =
     245         120 :         std::find( nodes.begin(), nodes.end(), this );
     246         120 :     LBASSERT( i != nodes.end( ));
     247             : 
     248         120 :     NodePath path;
     249         120 :     path.nodeIndex = std::distance( nodes.begin(), i );
     250         120 :     return path;
     251             : }
     252             : 
     253             : template< class C, class N, class P, class V >
     254         215 : void Node< C, N, P, V >::setApplicationNode( const bool isAppNode )
     255             : {
     256         215 :     if( _isAppNode == isAppNode )
     257         215 :         return;
     258         215 :     _isAppNode = isAppNode;
     259         215 :     setDirty( DIRTY_MEMBER );
     260             : }
     261             : 
     262             : template< class C, class N, class P, class V > void
     263        1322 : Node< C, N, P, V >::setIAttribute( const IAttribute attr, const int32_t value )
     264             : {
     265        1322 :     if( _data.iAttributes[attr] == value )
     266        1760 :         return;
     267         884 :     _data.iAttributes[attr] = value;
     268         884 :     setDirty( DIRTY_ATTRIBUTES );
     269             : }
     270             : 
     271             : template< class C, class N, class P, class V >
     272         778 : int32_t Node< C, N, P, V >::getIAttribute( const IAttribute attr ) const
     273             : {
     274         778 :     return _data.iAttributes[attr];
     275             : }
     276             : 
     277             : template< class C, class N, class P, class V > const std::string&
     278        1067 : Node< C, N, P, V >::getIAttributeString( const IAttribute attr )
     279             : {
     280        1067 :     return _iAttributeStrings[attr];
     281             : }
     282             : 
     283             : template< class C, class N, class P, class V >
     284         693 : void Node< C, N, P, V >::_addPipe( P* pipe )
     285             : {
     286         693 :     LBASSERT( pipe->getNode() == this );
     287         693 :     _pipes.push_back( pipe );
     288         693 : }
     289             : 
     290             : template< class C, class N, class P, class V >
     291        1189 : bool Node< C, N, P, V >::_removePipe( P* pipe )
     292             : {
     293        1189 :     typename Pipes::iterator i = lunchbox::find( _pipes, pipe );
     294        1189 :     if( i == _pipes.end( ))
     295         587 :         return false;
     296             : 
     297         602 :     _pipes.erase( i );
     298         602 :     return true;
     299             : }
     300             : 
     301             : template< class C, class N, class P, class V >
     302          15 : P* Node< C, N, P, V >::findPipe( const uint128_t& id )
     303             : {
     304          45 :     for( typename Pipes::const_iterator i = _pipes.begin();
     305          30 :          i != _pipes.end(); ++i )
     306             :     {
     307          15 :         P* pipe = *i;
     308          15 :         if( pipe->getID() == id )
     309          15 :             return pipe;
     310             :     }
     311           0 :     return 0;
     312             : }
     313             : 
     314             : template< class C, class N, class P, class V >
     315         239 : std::ostream& operator << ( std::ostream& os, const Node< C, N, P, V >& node )
     316             : {
     317         239 :     os << lunchbox::disableFlush << lunchbox::disableHeader;
     318         239 :     if( node.isApplicationNode( ))
     319         120 :         os << "appNode" << std::endl;
     320             :     else
     321         119 :         os << "node" << std::endl;
     322             : 
     323         239 :     os << "{" << std::endl << lunchbox::indent;
     324             : 
     325         239 :     const std::string& name = node.getName();
     326         239 :     if( !name.empty( ))
     327           9 :         os << "name     \"" << name << "\"" << std::endl;
     328             : 
     329         239 :     node.output( os );
     330             : 
     331         239 :     const typename N::Pipes& pipes = node.getPipes();
     332        1695 :     for( typename N::Pipes::const_iterator i = pipes.begin();
     333        1130 :          i != pipes.end(); ++i )
     334             :     {
     335         326 :         os << **i;
     336             :     }
     337         478 :     os << lunchbox::exdent << "}" << std::endl
     338         239 :        << lunchbox::enableHeader << lunchbox::enableFlush;
     339         239 :     return os;
     340             : }
     341             : 
     342             : }
     343             : }

Generated by: LCOV version 1.10