LCOV - code coverage report
Current view: top level - eq/server - node.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 156 376 41.5 %
Date: 2016-09-29 05:02:09 Functions: 33 56 58.9 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2005-2016, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                          Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *                          Cedric Stalder <cedric.stalder@gmail.com>
       5             :  *
       6             :  * This library is free software; you can redistribute it and/or modify it under
       7             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       8             :  * by the Free Software Foundation.
       9             :  *
      10             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      11             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      12             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      13             :  * details.
      14             :  *
      15             :  * You should have received a copy of the GNU Lesser General Public License
      16             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      17             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      18             :  */
      19             : 
      20             : #include "node.h"
      21             : 
      22             : #include "channel.h"
      23             : #include "config.h"
      24             : #include "global.h"
      25             : #include "log.h"
      26             : #include "nodeFactory.h"
      27             : #include "pipe.h"
      28             : #include "server.h"
      29             : #include "window.h"
      30             : 
      31             : #include <eq/fabric/commands.h>
      32             : #include <eq/fabric/elementVisitor.h>
      33             : #include <eq/fabric/event.h>
      34             : #include <eq/fabric/paths.h>
      35             : 
      36             : #include <co/barrier.h>
      37             : #include <co/global.h>
      38             : #include <co/objectICommand.h>
      39             : 
      40             : #include <lunchbox/clock.h>
      41             : #include <lunchbox/os.h>
      42             : #include <lunchbox/sleep.h>
      43             : 
      44             : #include <boost/filesystem/operations.hpp>
      45             : #include <boost/filesystem/path.hpp>
      46             : 
      47             : namespace eq
      48             : {
      49             : namespace server
      50             : {
      51             : typedef fabric::Node< Config, Node, Pipe, NodeVisitor > Super;
      52             : typedef co::CommandFunc<Node> NodeFunc;
      53             : namespace
      54             : {
      55             : #define S_MAKE_ATTR_STRING( attr ) ( std::string("EQ_NODE_") + #attr )
      56          56 : std::string _sAttributeStrings[] = {
      57             :     S_MAKE_ATTR_STRING( SATTR_LAUNCH_COMMAND )
      58          28 : };
      59          56 : std::string _cAttributeStrings[] = {
      60             :     S_MAKE_ATTR_STRING( CATTR_LAUNCH_COMMAND_QUOTE )
      61          28 : };
      62             : 
      63           0 : void _addEnv( std::ostringstream& stream, const char* key )
      64             : {
      65           0 :     char* env = getenv( key );
      66           0 :     if( env )
      67           0 :         stream << key << "=" << env << " ";
      68           0 : }
      69             : 
      70           0 : bool _containsPrefix( const std::string& str, const Strings& prefixes )
      71             : {
      72           0 :     for( const auto& prefix : { "LB_", "CO_", "EQ_", "DEFLECT_" })
      73           0 :         if( str.find( prefix ) == 0 )
      74           0 :             return true;
      75             : 
      76           0 :     for( const auto& prefix : prefixes )
      77           0 :         if( str.find( prefix ) == 0 )
      78           0 :             return true;
      79             : 
      80           0 :     return false;
      81             : }
      82             : }
      83             : 
      84         862 : Node::Node( Config* parent )
      85             :     : Super( parent )
      86             :     , _active( 0 )
      87             :     , _finishedFrame( 0 )
      88             :     , _flushedFrame( 0 )
      89             :     , _state( STATE_STOPPED )
      90         862 :     , _bufferedTasks( new co::BufferConnection )
      91        1724 :     , _lastDrawPipe( 0 )
      92             : {
      93         862 :     const Global* global = Global::instance();
      94        1724 :     for( int i=0; i < Node::SATTR_LAST; ++i )
      95             :     {
      96         862 :         const SAttribute attr = static_cast< SAttribute >( i );
      97         862 :         setSAttribute( attr, global->getNodeSAttribute( attr ));
      98             :     }
      99        1724 :     for( int i=0; i < Node::CATTR_LAST; ++i )
     100             :     {
     101         862 :         const CAttribute attr = static_cast< CAttribute >( i );
     102         862 :         setCAttribute( attr, global->getNodeCAttribute( attr ));
     103             :     }
     104        3448 :     for( int i = 0; i < IATTR_LAST; ++i )
     105             :     {
     106        2586 :         const IAttribute attr = static_cast< IAttribute >( i );
     107        2586 :         setIAttribute( attr, global->getNodeIAttribute( attr ));
     108             :     }
     109         862 : }
     110             : 
     111        1720 : Node::~Node()
     112             : {
     113        1720 : }
     114             : 
     115           4 : void Node::attach( const uint128_t& id, const uint32_t instanceID )
     116             : {
     117           4 :     Super::attach( id, instanceID );
     118             : 
     119           4 :     co::CommandQueue* cmdQ = getCommandThreadQueue();
     120             :     registerCommand( fabric::CMD_OBJECT_SYNC,
     121           4 :                      NodeFunc( this, &Node::_cmdSync ), cmdQ );
     122             :     registerCommand( fabric::CMD_NODE_CONFIG_INIT_REPLY,
     123           4 :                      NodeFunc( this, &Node::_cmdConfigInitReply ), cmdQ );
     124             :     registerCommand( fabric::CMD_NODE_CONFIG_EXIT_REPLY,
     125           4 :                      NodeFunc( this, &Node::_cmdConfigExitReply ), cmdQ );
     126             :     registerCommand( fabric::CMD_NODE_FRAME_FINISH_REPLY,
     127           4 :                      NodeFunc( this, &Node::_cmdFrameFinishReply ), cmdQ );
     128           4 : }
     129             : 
     130          20 : ServerPtr Node::getServer()
     131             : {
     132          20 :     return getConfig() ? getConfig()->getServer() : 0;
     133             : }
     134             : 
     135           0 : ConstServerPtr Node::getServer() const
     136             : {
     137           0 :     return getConfig() ? getConfig()->getServer() : 0;
     138             : }
     139             : 
     140          12 : co::CommandQueue* Node::getMainThreadQueue()
     141             : {
     142          12 :     return getConfig()->getMainThreadQueue();
     143             : }
     144             : 
     145          20 : co::CommandQueue* Node::getCommandThreadQueue()
     146             : {
     147          20 :     return getConfig()->getCommandThreadQueue();
     148             : }
     149             : 
     150           0 : Channel* Node::getChannel( const ChannelPath& path )
     151             : {
     152           0 :     const Pipes& pipes = getPipes();
     153           0 :     LBASSERT( pipes.size() > path.pipeIndex );
     154             : 
     155           0 :     if( pipes.size() <= path.pipeIndex )
     156           0 :         return 0;
     157             : 
     158           0 :     return pipes[ path.pipeIndex ]->getChannel( path );
     159             : }
     160             : 
     161           4 : void Node::addTasks( const uint32_t tasks )
     162             : {
     163           4 :     setTasks( getTasks() | tasks );
     164           4 : }
     165             : 
     166           2 : void Node::activate()
     167             : {
     168           2 :     ++_active;
     169           2 :     LBLOG( LOG_VIEW ) << "activate: " << _active << std::endl;
     170           2 : }
     171             : 
     172           2 : void Node::deactivate()
     173             : {
     174           2 :     LBASSERT( _active != 0 );
     175           2 :     --_active;
     176           2 :     LBLOG( LOG_VIEW ) << "deactivate: " << _active << std::endl;
     177           2 : };
     178             : 
     179         862 : void Node::setSAttribute( const SAttribute attr, const std::string& value )
     180             : {
     181         862 :     _sAttributes[attr] = value;
     182         862 : }
     183             : 
     184         432 : const std::string& Node::getSAttribute( const SAttribute attr ) const
     185             : {
     186         432 :     return _sAttributes[attr];
     187             : }
     188             : 
     189         682 : const std::string& Node::getSAttributeString( const SAttribute attr )
     190             : {
     191         682 :     return _sAttributeStrings[attr];
     192             : }
     193             : 
     194         862 : void Node::setCAttribute( const CAttribute attr, const char value )
     195             : {
     196         862 :     _cAttributes[attr] = value;
     197         862 : }
     198             : 
     199         432 : char Node::getCAttribute( const CAttribute attr ) const
     200             : {
     201         432 :     return _cAttributes[attr];
     202             : }
     203             : 
     204         682 : const std::string& Node::getCAttributeString( const CAttribute attr )
     205             : {
     206         682 :     return _cAttributeStrings[attr];
     207             : }
     208             : 
     209             : //===========================================================================
     210             : // Operations
     211             : //===========================================================================
     212             : 
     213             : //---------------------------------------------------------------------------
     214             : // launch and connect
     215             : //---------------------------------------------------------------------------
     216             : 
     217             : namespace
     218             : {
     219           0 : class NetNode : public co::Node
     220             : {
     221             : public:
     222           0 :     NetNode( server::Node& node ) : co::Node(), _node( node ) {}
     223             : 
     224             : private:
     225             :     server::Node& _node;
     226             : 
     227           0 :     std::string getWorkDir() const override
     228           0 :         { return _node.getConfig()->getWorkDir(); }
     229             : 
     230           0 :     std::string getLaunchQuote() const override
     231             :     {
     232             :         return std::string( 1, _node.getCAttribute(
     233           0 :                                     server::Node::CATTR_LAUNCH_COMMAND_QUOTE ));
     234             :     }
     235             : };
     236             : 
     237           0 : static co::NodePtr _createNetNode( Node* node )
     238             : {
     239           0 :     co::NodePtr netNode = new NetNode( *node );
     240             :     const co::ConnectionDescriptions& descriptions =
     241           0 :         node->getConnectionDescriptions();
     242           0 :     for( co::ConnectionDescriptionPtr desc : descriptions )
     243             :     {
     244             :         netNode->addConnectionDescription(
     245           0 :             new co::ConnectionDescription( *desc ));
     246             : 
     247           0 :         if( node->getHost().empty( ))
     248             :         {
     249           0 :             node->setHost( desc->getHostname( ));
     250           0 :             LBWARN << "No host specified, guessing " << node->getHost()
     251           0 :                    << " from " << desc << std::endl;
     252             :         }
     253           0 :     }
     254             : 
     255           0 :     netNode->setHostname( node->getHost( ));
     256           0 :     return netNode;
     257             : }
     258             : }
     259             : 
     260           2 : bool Node::connect()
     261             : {
     262           2 :     LBASSERT( isActive( ));
     263             : 
     264           2 :     if( _node )
     265           2 :         return _node->isConnected();
     266             : 
     267           0 :     if( !isStopped( ))
     268             :     {
     269           0 :         LBASSERT( _state == STATE_FAILED );
     270           0 :         return true;
     271             :     }
     272             : 
     273           0 :     co::LocalNodePtr localNode = getLocalNode();
     274           0 :     LBASSERT( localNode );
     275             : 
     276           0 :     _node = _createNetNode( this );
     277             : 
     278           0 :     LBLOG( LOG_INIT ) << "Connecting node" << std::endl;
     279           0 :     if( localNode->connect( _node ) ||
     280           0 :         localNode->launch( _node, _createLaunchCommand( )))
     281             :     {
     282           0 :         return true;
     283             :     }
     284             : 
     285           0 :     LBWARN << "Connection to " << _node->getNodeID() << " failed" << std::endl;
     286           0 :     _state = STATE_FAILED;
     287           0 :     _node = nullptr;
     288           0 :     return false;
     289             : }
     290             : 
     291           2 : bool Node::syncLaunch( const lunchbox::Clock& clock )
     292             : {
     293           2 :     LBASSERT( isActive( ));
     294             : 
     295           2 :     if( !_node )
     296           0 :         return false;
     297             : 
     298           2 :     if( _node->isConnected( ))
     299           2 :         return true;
     300             : 
     301           0 :     LBASSERT( !isApplicationNode( ));
     302             : 
     303           0 :     co::LocalNodePtr localNode = getLocalNode();
     304           0 :     const int64_t timeOut = getIAttribute( IATTR_LAUNCH_TIMEOUT );
     305           0 :     _node = localNode->syncLaunch( _node->getNodeID(),
     306             :                                    std::max( int64_t( 0 ),
     307           0 :                                              timeOut - clock.getTime64( )));
     308           0 :     if( _node )
     309           0 :         return true;
     310             : 
     311           0 :     sendError( fabric::ERROR_NODE_CONNECT ) << _host;
     312           0 :     _state = STATE_FAILED;
     313           0 :     return false;
     314             : }
     315             : 
     316           0 : std::string Node::_createLaunchCommand() const
     317             : {
     318           0 :     const std::string& command = getSAttribute( SATTR_LAUNCH_COMMAND );
     319           0 :     const size_t commandPos = command.find( "%c" );
     320           0 :     if( commandPos == std::string::npos )
     321           0 :         return command + " " + _createRemoteCommand();
     322             : 
     323           0 :     return command.substr( 0, commandPos ) + _createRemoteCommand() +
     324           0 :            command.substr( commandPos + 2 );
     325             : }
     326             : 
     327           0 : std::string Node::_createRemoteCommand() const
     328             : {
     329           0 :     const Config* config = getConfig();
     330           0 :     std::string program = config->getRenderClient();
     331           0 :     if( program.empty( ))
     332             :     {
     333           0 :         LBWARN << "No render client name, auto-launch will fail" << std::endl;
     334           0 :         return program;
     335             :     }
     336             : 
     337             :     //----- environment
     338           0 :     std::ostringstream os;
     339           0 :     const std::string& quote = _node->getLaunchQuote();
     340             : 
     341             :     //----- program + args
     342             : #ifndef WIN32
     343             : #  ifdef Darwin
     344             :     const char libPath[] = "DYLD_LIBRARY_PATH";
     345             : #  else
     346           0 :     const char libPath[] = "LD_LIBRARY_PATH";
     347             : #  endif
     348             : 
     349           0 :     os << "env ";
     350           0 :     _addEnv( os, libPath );
     351           0 :     _addEnv( os, "PATH" );
     352           0 :     _addEnv( os, "PYTHONPATH" );
     353             : #ifdef EQUALIZER_USE_DEFLECT
     354           0 :     _addEnv( os, "DEFLECT_HOST" );
     355           0 :     _addEnv( os, "DEFLECT_ID" );
     356             : #endif
     357             : 
     358           0 :     const Strings& prefixes = config->getRenderClientEnvPrefixes();
     359           0 :     for( int i=0; environ[i] != 0; ++i )
     360             :     {
     361           0 :         const std::string var = environ[i];
     362           0 :         if( _containsPrefix( var, prefixes ))
     363           0 :             os << quote << var << quote << " ";
     364           0 :     }
     365             : 
     366           0 :     os << "LB_LOG_LEVEL=" <<lunchbox::Log::getLogLevelString() << " ";
     367           0 :     if( lunchbox::Log::topics != 0 )
     368           0 :         os << "LB_LOG_TOPICS=" <<lunchbox::Log::topics << " ";
     369             : #endif
     370             : 
     371             :     const boost::filesystem::path absolute =
     372           0 :         boost::filesystem::system_complete( boost::filesystem::path( program ));
     373           0 :     program = absolute.string();
     374             : 
     375           0 :     std::string options;
     376           0 :     for( const std::string& arg : config->getRenderClientArgs( ))
     377           0 :         options += std::string( " " ) + quote + arg + quote;
     378           0 :     return os.str() + quote + program + quote + options + " -- --eq-client %o ";
     379             : }
     380             : 
     381             : //---------------------------------------------------------------------------
     382             : // init
     383             : //---------------------------------------------------------------------------
     384           2 : void Node::configInit( const uint128_t& initID, const uint32_t frameNumber )
     385             : {
     386           2 :     LBASSERT( _state == STATE_STOPPED );
     387           2 :     _state = STATE_INITIALIZING;
     388             : 
     389           2 :     const Config* config = getConfig();
     390           2 :     _flushedFrame  = config->getFinishedFrame();
     391           2 :     _finishedFrame = config->getFinishedFrame();
     392           2 :     _frameIDs.clear();
     393             : 
     394           2 :     LBLOG( LOG_INIT ) << "Create node" << std::endl;
     395           2 :     getConfig()->send( _node, fabric::CMD_CONFIG_CREATE_NODE ) << getID();
     396             : 
     397           2 :     LBLOG( LOG_INIT ) << "Init node" << std::endl;
     398           2 :     send( fabric::CMD_NODE_CONFIG_INIT ) << initID << frameNumber;
     399           2 : }
     400             : 
     401           2 : bool Node::syncConfigInit()
     402             : {
     403           2 :     LBASSERT( _state == STATE_INITIALIZING || _state == STATE_INIT_SUCCESS ||
     404             :               _state == STATE_INIT_FAILED );
     405             : 
     406           2 :     _state.waitNE( STATE_INITIALIZING );
     407             : 
     408           2 :     if( _state == STATE_INIT_SUCCESS )
     409             :     {
     410           2 :         _state = STATE_RUNNING;
     411           2 :         return true;
     412             :     }
     413             : 
     414           0 :     LBWARN << "Node initialization failed" << std::endl;
     415           0 :     configExit();
     416           0 :     return false;
     417             : }
     418             : 
     419             : //---------------------------------------------------------------------------
     420             : // exit
     421             : //---------------------------------------------------------------------------
     422           2 : void Node::configExit()
     423             : {
     424           2 :     if( _state == STATE_EXITING )
     425           2 :         return;
     426             : 
     427           2 :     LBASSERT( _state == STATE_RUNNING || _state == STATE_INIT_FAILED );
     428           2 :     _state = STATE_EXITING;
     429             : 
     430           2 :     LBLOG( LOG_INIT ) << "Exit node" << std::endl;
     431           2 :     send( fabric::CMD_NODE_CONFIG_EXIT );
     432           2 :     flushSendBuffer();
     433             : }
     434             : 
     435           2 : bool Node::syncConfigExit()
     436             : {
     437           2 :     LBASSERT( _state == STATE_EXITING || _state == STATE_EXIT_SUCCESS ||
     438             :               _state == STATE_EXIT_FAILED );
     439             : 
     440           2 :     _state.waitNE( STATE_EXITING );
     441           2 :     const bool success = ( _state == STATE_EXIT_SUCCESS );
     442           2 :     LBASSERT( success || _state == STATE_EXIT_FAILED );
     443             : 
     444           2 :     _state = isActive() ? STATE_FAILED : STATE_STOPPED;
     445           2 :     setTasks( fabric::TASK_NONE );
     446           2 :     _frameIDs.clear();
     447           2 :     _flushBarriers();
     448           2 :     return success;
     449             : }
     450             : 
     451             : //---------------------------------------------------------------------------
     452             : // update
     453             : //---------------------------------------------------------------------------
     454           0 : void Node::update( const uint128_t& frameID, const uint32_t frameNumber )
     455             : {
     456           0 :     if( !isRunning( ))
     457           0 :         return;
     458             : 
     459           0 :     LBVERB << "Start frame " << frameNumber << std::endl;
     460           0 :     LBASSERT( isActive( ));
     461             : 
     462           0 :     _frameIDs[ frameNumber ] = frameID;
     463             : 
     464           0 :     uint128_t configVersion = co::VERSION_INVALID;
     465           0 :     if( !isApplicationNode( )) // synced in Config::_cmdFrameStart
     466           0 :         configVersion = getConfig()->getVersion();
     467             : 
     468             :     send( fabric::CMD_NODE_FRAME_START )
     469           0 :             << getVersion() << configVersion << frameID << frameNumber;
     470           0 :     LBLOG( LOG_TASKS ) << "TASK node start frame " << std::endl;
     471             : 
     472           0 :     const Pipes& pipes = getPipes();
     473           0 :     for( Pipes::const_iterator i = pipes.begin(); i != pipes.end(); ++i )
     474           0 :         (*i)->update( frameID, frameNumber );
     475             : 
     476           0 :     if( !_lastDrawPipe ) // no FrameDrawFinish sent
     477             :     {
     478           0 :         send( fabric::CMD_NODE_FRAME_DRAW_FINISH ) << frameID << frameNumber;
     479           0 :         LBLOG( LOG_TASKS ) << "TASK node draw finish " << getName() <<  " "
     480           0 :                            << std::endl;
     481             :     }
     482           0 :     _lastDrawPipe = 0;
     483             : 
     484           0 :     send( fabric::CMD_NODE_FRAME_TASKS_FINISH ) << frameID << frameNumber;
     485           0 :     LBLOG( LOG_TASKS ) << "TASK node tasks finish " << std::endl;
     486             : 
     487           0 :     _finish( frameNumber );
     488           0 :     flushSendBuffer();
     489             : }
     490             : 
     491           0 : uint32_t Node::_getFinishLatency() const
     492             : {
     493           0 :     switch( getIAttribute( Node::IATTR_THREAD_MODEL ))
     494             :     {
     495             :         case fabric::UNDEFINED:
     496             :         case fabric::DRAW_SYNC:
     497           0 :             if( getTasks() & fabric::TASK_DRAW )
     498             :             {
     499             :                 // More than one frame latency doesn't make sense, since the
     500             :                 // draw sync for frame+1 does not allow for more
     501           0 :                 const Config* config = getConfig();
     502           0 :                 const uint32_t latency = config->getLatency();
     503             : 
     504           0 :                 return LB_MIN( latency, 1 );
     505             :             }
     506           0 :             break;
     507             : 
     508             :         case fabric::LOCAL_SYNC:
     509           0 :             if( getTasks() != fabric::TASK_NONE )
     510             :                 // local sync enforces no latency
     511           0 :                 return 0;
     512           0 :             break;
     513             : 
     514             :         case fabric::ASYNC:
     515           0 :             break;
     516             :         default:
     517           0 :             LBUNIMPLEMENTED;
     518             :     }
     519             : 
     520           0 :     const Config* config = getConfig();
     521           0 :     return config->getLatency();
     522             : }
     523             : 
     524           0 : void Node::_finish( const uint32_t currentFrame )
     525             : {
     526           0 :     const Pipes& pipes = getPipes();
     527           0 :     for( Pipes::const_iterator i = pipes.begin(); i != pipes.end(); ++i )
     528             :     {
     529           0 :         const Pipe* pipe = *i;
     530           0 :         if( pipe->getIAttribute( Pipe::IATTR_HINT_THREAD ) && pipe->isRunning())
     531             :         {
     532           0 :             const uint32_t latency = _getFinishLatency();
     533           0 :             if( currentFrame > latency )
     534           0 :                 flushFrames( currentFrame - latency );
     535           0 :             return;
     536             :         }
     537             :     }
     538             : 
     539             :     // else only non-threaded pipes, all local tasks are done, send finish now.
     540           0 :     flushFrames( currentFrame );
     541             : }
     542             : 
     543           0 : void Node::flushFrames( const uint32_t frameNumber )
     544             : {
     545           0 :     LBLOG( LOG_TASKS ) << "Flush frames including " << frameNumber << std::endl;
     546             : 
     547           0 :     while( _flushedFrame < frameNumber )
     548             :     {
     549           0 :         ++_flushedFrame;
     550           0 :         _sendFrameFinish( _flushedFrame );
     551             :     }
     552             : 
     553           0 :     flushSendBuffer();
     554           0 : }
     555             : 
     556           0 : void Node::_sendFrameFinish( const uint32_t frameNumber )
     557             : {
     558           0 :     FrameIDHash::iterator i = _frameIDs.find( frameNumber );
     559           0 :     if( i == _frameIDs.end( ))
     560           0 :         return; // finish already send
     561             : 
     562           0 :     send( fabric::CMD_NODE_FRAME_FINISH ) << i->second << frameNumber;
     563           0 :     _frameIDs.erase( i );
     564           0 :     LBLOG( LOG_TASKS ) << "TASK node finish frame " << frameNumber << std::endl;
     565             : }
     566             : 
     567             : //---------------------------------------------------------------------------
     568             : // Barrier cache
     569             : //---------------------------------------------------------------------------
     570           0 : co::Barrier* Node::getBarrier()
     571             : {
     572           0 :     if( _barriers.empty( ))
     573             :     {
     574             :         co::Barrier* barrier = new co::Barrier( getServer(),
     575           0 :                                                 _node->getNodeID( ));
     576           0 :         barrier->setAutoObsolete( getConfig()->getLatency() + 1 );
     577           0 :         return barrier;
     578             :     }
     579             :     // else
     580             : 
     581           0 :     co::Barrier* barrier = _barriers.back();
     582           0 :     _barriers.pop_back();
     583           0 :     barrier->setHeight( 0 );
     584           0 :     return barrier;
     585             : }
     586             : 
     587           0 : void Node::changeLatency( const uint32_t latency )
     588             : {
     589           0 :     for( co::Barriers::const_iterator i = _barriers.begin();
     590           0 :          i != _barriers.end(); ++ i )
     591             :     {
     592           0 :         co::Barrier* barrier = *i;
     593           0 :         barrier->setAutoObsolete( latency + 1 );
     594             :     }
     595           0 : }
     596             : 
     597           0 : void Node::releaseBarrier( co::Barrier* barrier )
     598             : {
     599           0 :     _barriers.push_back( barrier );
     600           0 : }
     601             : 
     602           2 : void Node::_flushBarriers()
     603             : {
     604           2 :     for( co::BarriersCIter i =_barriers.begin(); i != _barriers.end(); ++i )
     605           0 :         delete *i;
     606           2 :     _barriers.clear();
     607           2 : }
     608             : 
     609           0 : bool Node::removeConnectionDescription( co::ConnectionDescriptionPtr cd )
     610             : {
     611             :     // Don't use std::find, RefPtr::operator== compares pointers, not values.
     612           0 :     for(co::ConnectionDescriptions::iterator i=_connectionDescriptions.begin();
     613           0 :         i != _connectionDescriptions.end(); ++i )
     614             :     {
     615           0 :         if( *cd != **i )
     616           0 :             continue;
     617             : 
     618           0 :         _connectionDescriptions.erase( i );
     619           0 :         return true;
     620             :     }
     621           0 :     return false;
     622             : }
     623             : 
     624           4 : co::ObjectOCommand Node::send( const uint32_t cmd )
     625             : {
     626           4 :     return send( cmd, getID( ));
     627             : }
     628             : 
     629          22 : co::ObjectOCommand Node::send( const uint32_t cmd, const uint128_t& id )
     630             : {
     631             :     return co::ObjectOCommand( co::Connections( 1, _bufferedTasks ), cmd,
     632          22 :                                co::COMMANDTYPE_OBJECT, id, CO_INSTANCE_ALL );
     633             : }
     634             : 
     635           0 : EventOCommand Node::sendError( const uint32_t error )
     636             : {
     637           0 :     return getConfig()->sendError( Event::NODE_ERROR, Error( error, getID( )));
     638             : }
     639             : 
     640          12 : void Node::flushSendBuffer()
     641             : {
     642          12 :     _bufferedTasks->sendBuffer( _node->getConnection( ));
     643          12 : }
     644             : 
     645             : //===========================================================================
     646             : // command handling
     647             : //===========================================================================
     648           2 : bool Node::_cmdConfigInitReply( co::ICommand& cmd )
     649             : {
     650           2 :     co::ObjectICommand command( cmd );
     651           2 :     LBVERB << "handle configInit reply " << command << std::endl;
     652           2 :     LBASSERT( _state == STATE_INITIALIZING );
     653           2 :     _state = command.read< uint64_t >() ? STATE_INIT_SUCCESS : STATE_INIT_FAILED;
     654             : 
     655           2 :     return true;
     656             : }
     657             : 
     658           2 : bool Node::_cmdConfigExitReply( co::ICommand& cmd )
     659             : {
     660           2 :     co::ObjectICommand command( cmd );
     661           2 :     LBVERB << "handle configExit reply " << command << std::endl;
     662           2 :     LBASSERT( _state == STATE_EXITING );
     663             : 
     664           2 :     _state = command.read< bool >() ? STATE_EXIT_SUCCESS : STATE_EXIT_FAILED;
     665           2 :     return true;
     666             : }
     667             : 
     668           0 : bool Node::_cmdFrameFinishReply( co::ICommand& cmd )
     669             : {
     670           0 :     co::ObjectICommand command( cmd );
     671           0 :     LBVERB << "handle frame finish reply " << command << std::endl;
     672             : 
     673           0 :     const uint32_t frameNumber = command.read< uint32_t >();
     674             : 
     675           0 :     _finishedFrame = frameNumber;
     676           0 :     getConfig()->notifyNodeFrameFinished( frameNumber );
     677             : 
     678           0 :     return true;
     679             : }
     680             : 
     681         432 : void Node::output( std::ostream& os ) const
     682             : {
     683         432 :     if( !_host.empty( ))
     684         258 :         os << "host     \"" << _host << '"' << std::endl;
     685             : 
     686         432 :     const co::ConnectionDescriptions& descriptions = _connectionDescriptions;
     687        2202 :     for( co::ConnectionDescriptions::const_iterator i = descriptions.begin();
     688        1468 :          i != descriptions.end(); ++i )
     689             :     {
     690         302 :         co::ConnectionDescriptionPtr desc = *i;
     691         302 :         os << *desc;
     692         302 :     }
     693             : 
     694         432 :     bool attrPrinted   = false;
     695             : 
     696        1728 :     for( Node::SAttribute i = static_cast<Node::SAttribute>( 0 );
     697         864 :          i < Node::SATTR_LAST;
     698             :          i = static_cast<Node::SAttribute>( static_cast<uint32_t>( i )+1))
     699             :     {
     700         432 :         const std::string& value = getSAttribute( i );
     701         432 :         if( value == Global::instance()->getNodeSAttribute( i ))
     702         432 :             continue;
     703             : 
     704           0 :         if( !attrPrinted )
     705             :         {
     706           0 :             os << std::endl << "attributes" << std::endl;
     707           0 :             os << "{" << std::endl << lunchbox::indent;
     708           0 :             attrPrinted = true;
     709             :         }
     710             : 
     711             :         os << ( i==Node::SATTR_LAUNCH_COMMAND ? "launch_command       " :
     712           0 :                 "ERROR" )
     713           0 :            << "\"" << value << "\"" << std::endl;
     714             :     }
     715             : 
     716        1728 :     for( Node::CAttribute i = static_cast<Node::CAttribute>( 0 );
     717         864 :          i < Node::CATTR_LAST;
     718             :          i = static_cast<Node::CAttribute>( static_cast<uint32_t>( i )+1))
     719             :     {
     720         432 :         const char value = getCAttribute( i );
     721         432 :         if( value == Global::instance()->getNodeCAttribute( i ))
     722         432 :             continue;
     723             : 
     724           0 :         if( !attrPrinted )
     725             :         {
     726           0 :             os << std::endl << "attributes" << std::endl;
     727           0 :             os << "{" << std::endl << lunchbox::indent;
     728           0 :             attrPrinted = true;
     729             :         }
     730             : 
     731             :         os << ( i==Node::CATTR_LAUNCH_COMMAND_QUOTE ? "launch_command_quote " :
     732           0 :                 "ERROR" )
     733           0 :            << "'" << value << "'" << std::endl;
     734             :     }
     735             : 
     736        3456 :     for( Node::IAttribute i = static_cast< Node::IAttribute>( 0 );
     737        1728 :          i < Node::IATTR_LAST;
     738             :          i = static_cast< Node::IAttribute >( static_cast<uint32_t>( i )+1))
     739             :     {
     740        1296 :         const int value = getIAttribute( i );
     741        1296 :         if( value == Global::instance()->getNodeIAttribute( i ))
     742        1296 :             continue;
     743             : 
     744           0 :         if( !attrPrinted )
     745             :         {
     746           0 :             os << std::endl << "attributes" << std::endl;
     747           0 :             os << "{" << std::endl << lunchbox::indent;
     748           0 :             attrPrinted = true;
     749             :         }
     750             : 
     751             :         os << ( i== Node::IATTR_LAUNCH_TIMEOUT ? "launch_timeout       " :
     752             :                 i== Node::IATTR_THREAD_MODEL   ? "thread_model         " :
     753             :                 i== Node::IATTR_HINT_AFFINITY  ? "hint_affinity        " :
     754           0 :                 "ERROR" )
     755           0 :            << static_cast< fabric::IAttribute >( value ) << std::endl;
     756             :     }
     757             : 
     758         432 :     if( attrPrinted )
     759           0 :         os << lunchbox::exdent << "}" << std::endl << std::endl;
     760         432 : }
     761             : 
     762             : }
     763             : }
     764             : 
     765             : #include "../fabric/node.ipp"
     766             : template class eq::fabric::Node< eq::server::Config, eq::server::Node,
     767             :                                  eq::server::Pipe, eq::server::NodeVisitor >;
     768             : /** @cond IGNORE */
     769             : template std::ostream& eq::fabric::operator << ( std::ostream&,
     770          84 :                                                  const eq::server::Super& );
     771             : /** @endcond */

Generated by: LCOV version 1.11