コード例 #1
0
ファイル: command.cpp プロジェクト: MichaelVlad/Equalizer
void Command::clone_( Command& from )
{
    EQ_TS_THREAD( _writeThread );
    EQASSERT( _refCount == 0 );
    EQASSERT( !_func.isValid( ));

    _node = from._node;
    _localNode = from._localNode;
    _packet = from._packet;

    _refCountMaster = &from._refCount;
}
コード例 #2
0
ファイル: commandQueue.cpp プロジェクト: cstalder/Equalizer
Command* CommandQueue::pop( const uint32_t timeout )
{
    EQ_TS_THREAD( _thread );
    if( timeout == EQ_TIMEOUT_INDEFINITE )
        return _commands.pop();

    Command* command;
    if( !_commands.timedPop( timeout, command ))
        throw Exception( Exception::TIMEOUT_COMMANDQUEUE );

    return command;
}
コード例 #3
0
ファイル: commandCache.cpp プロジェクト: cstalder/Equalizer
Command& CommandCache::alloc( NodePtr node, LocalNodePtr localNode, 
                              const uint64_t size )
{
    EQ_TS_THREAD( _thread );

    const Cache which = (size > Packet::minSize) ? CACHE_BIG : CACHE_SMALL;

    _compact( which );
    Command& command = _newCommand( which );
    command._alloc( node, localNode, size );
    return command;
}
コード例 #4
0
ファイル: localNode.cpp プロジェクト: MichaelVlad/Equalizer
bool LocalNode::_cmdStopRcv( Command& command )
{
    EQ_TS_THREAD( _rcvThread );
    EQASSERT( _state == STATE_LISTENING );
    EQINFO << "Cmd stop receiver " << this << std::endl;

    _state = STATE_CLOSING; // causes rcv thread exit

    command->command = CMD_NODE_STOP_CMD; // causes cmd thread exit
    _dispatchCommand( command );
    return true;
}
コード例 #5
0
Command& CommandCache::alloc( NodePtr node, LocalNodePtr localNode, 
                              const uint64_t size )
{
    EQ_TS_THREAD( _thread );
    EQASSERTINFO( size < EQ_BIT48,
                  "Out-of-sync network stream: packet size " << size << "?" );

    const Cache which = (size > Packet::minSize) ? CACHE_BIG : CACHE_SMALL;

    _compact( which );
    Command& command = _newCommand( which );
    command.alloc_( node, localNode, size );
    return command;
}
コード例 #6
0
ファイル: masterCM.cpp プロジェクト: cstalder/Equalizer
void MasterCM::removeSlaves( NodePtr node )
{
    EQ_TS_THREAD( _cmdThread );

    const NodeID& nodeID = node->getNodeID();
    SlavesCount::iterator i = _slavesCount.find( nodeID );
    if( i == _slavesCount.end( ))
        return;

    Nodes::iterator j = stde::find( _slaves, node );
    EQASSERT( j != _slaves.end( ));
    _slaves.erase( j );
    _slavesCount.erase( i );
}
コード例 #7
0
void FrameBufferObject::exit()
{
    EQ_TS_THREAD( _thread );
    if( _fboID )
    {
        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
        glDeleteFramebuffersEXT( 1, &_fboID );
        _fboID = 0;
    }

    for( size_t i = 0; i < _colors.size(); ++i )
        _colors[i]->flush();
    _depth.flush();

    _valid = false;
}
コード例 #8
0
void UnbufferedMasterCM::removeSlave( NodePtr node )
{
    EQ_TS_THREAD( _cmdThread );
    // remove from subscribers
    const NodeID& nodeID = node->getNodeID();
    EQASSERTINFO( _slavesCount[ nodeID ] != 0, base::className( _object ));

    --_slavesCount[ nodeID ];
    if( _slavesCount[ nodeID ] == 0 )
    {
        Nodes::iterator i = find( _slaves.begin(), _slaves.end(), node );
        EQASSERT( i != _slaves.end( ));
        _slaves.erase( i );
        _slavesCount.erase( nodeID );
    }
}
コード例 #9
0
ファイル: command.cpp プロジェクト: MichaelVlad/Equalizer
void Command::_free()
{
    EQ_TS_THREAD( _writeThread );
    EQASSERT( _refCount == 0 );
    EQASSERT( !_func.isValid( ));

    if( _data )
        free( _data );

    _data = 0;
    _dataSize = 0;
    _packet = 0;
    _node = 0;
    _localNode = 0;
    _refCountMaster = 0;
}        
コード例 #10
0
ファイル: pgmConnection.cpp プロジェクト: cstalder/Equalizer
ConnectionPtr PGMConnection::acceptSync()
{
    EQ_TS_THREAD( _recvThread );
    if( _state != STATE_LISTENING )
        return 0;

    EQASSERT( _overlappedAcceptData );
    EQASSERT( _overlappedSocket != INVALID_SOCKET );
    if( _overlappedSocket == INVALID_SOCKET )
        return 0;

    // complete accept
    DWORD got   = 0;
    DWORD flags = 0;
    if( !WSAGetOverlappedResult( _readFD, &_overlapped, &got, TRUE, &flags ))
    {
        EQWARN << "Accept completion failed: " << base::sysError 
               << ", closing connection" << std::endl;
        close();
        return 0;
    }

    sockaddr_in* local     = 0;
    sockaddr_in* remote    = 0;
    int          localLen  = 0;
    int          remoteLen = 0;
    GetAcceptExSockaddrs( _overlappedAcceptData, 0, sizeof( sockaddr_in ) + 16,
                          sizeof( sockaddr_in ) + 16, (sockaddr**)&local, 
                          &localLen, (sockaddr**)&remote, &remoteLen );

    PGMConnection* newConnection = new PGMConnection;
    ConnectionPtr connection( newConnection ); // to keep ref-counting correct

    newConnection->_readFD  = _overlappedSocket;
    _overlappedSocket       = INVALID_SOCKET;

    newConnection->_setupReadSocket();
    newConnection->_writeFD = _writeFD;
    newConnection->_initAIORead();
    newConnection->_state       = STATE_CONNECTED;
    newConnection->_description = _description;

    EQINFO << "accepted connection " << (void*)newConnection << " from " 
           << inet_ntoa( remote->sin_addr ) << ":" << ntohs( remote->sin_port )
           << std::endl;
    return connection;
}
コード例 #11
0
bool FrameBufferObject::resize( const int32_t width, const int32_t height )
{
    EQ_TS_THREAD( _thread );
    EQASSERT( width > 0 && height > 0 );

    EQASSERT( !_colors.empty( ));
    Texture* color = _colors.front();

    if( color->getWidth() == width && color->getHeight() == height && _valid )
       return true;

    for( size_t i = 0; i < _colors.size(); ++i )
        _colors[i]->resize( width, height );

    if ( _depth.isValid( ))
        _depth.resize( width, height );

    return _checkStatus();
}
コード例 #12
0
bool FrameBufferObject::init( const int32_t width, const int32_t height,
                              const GLuint colorFormat,
                              const int32_t depthSize,
                              const int32_t stencilSize )
{
    EQ_TS_THREAD( _thread );

    if( _fboID )
    {
        _setError( ERROR_FRAMEBUFFER_INITIALIZED );
        EQWARN << _error << std::endl;
        return false;
    }

    // generate and bind the framebuffer
    glGenFramebuffersEXT( 1, &_fboID );
    glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, _fboID );

    // create and bind textures
    for( unsigned i = 0; i < _colors.size(); ++i )
    {
        _colors[i]->init( colorFormat, width, height );
        _colors[i]->bindToFBO( GL_COLOR_ATTACHMENT0 + i, width, height );
    }
    if( stencilSize > 0 && GLEW_EXT_packed_depth_stencil )
    {
        _depth.init( GL_DEPTH24_STENCIL8, width, height );
        _depth.bindToFBO( GL_DEPTH_STENCIL_ATTACHMENT, width, height ); 
    }
    else if( depthSize > 0 )
    {
        _depth.init( GL_DEPTH_COMPONENT, width, height );
        _depth.bindToFBO( GL_DEPTH_ATTACHMENT, width, height );
    }

    if( _checkStatus( ))
        return true;
    // else

    exit();
    return false;
}
コード例 #13
0
ファイル: commandCache.cpp プロジェクト: cstalder/Equalizer
Command& CommandCache::_newCommand( const Cache which )
{
    EQ_TS_THREAD( _thread );

    Data& cache = _cache[ which ];
    const uint32_t cacheSize = uint32_t( cache.size( ));
    base::a_int32_t& freeCounter = _free[ which ];
    EQASSERTINFO( size_t( freeCounter ) <= cacheSize,
                  freeCounter << " > " << cacheSize );

    if( freeCounter > 0 )
    {
        EQASSERT( cacheSize > 0 );

        const DataCIter end = _position[ which ];
        DataCIter& i = _position[ which ];

        for( ++i; i != end; ++i )
        {
            if( i == cache.end( ))
                i = cache.begin();
#ifdef PROFILE
            ++_lookups;
#endif
            Command* command = *i;
            if( command->isFree( ))
            {
#ifdef PROFILE
                const long hits = ++_hits;
                if( (hits%1000) == 0 )
                {
                    for( size_t j = 0; j < CACHE_ALL; ++j )
                    {
                        size_t size = 0;
                        const Data& cmds = _cache[ j ];
                        for( DataCIter k=cmds.begin(); k != cmds.end(); ++k)
                            size += (*k)->getAllocationSize();

                        EQINFO << _hits << "/" << _hits + _misses << " hits, "
                               << _lookups << " lookups, " << _free[j] << " of "
                               << cmds.size() << " packets free, " << _allocs
                               << " allocs, " << _frees << " frees, " 
                               << size / 1024 << "KB" << std::endl;
                    }
                }
#endif
                return *command;
            }
        }
    }
#ifdef PROFILE
    ++_misses;
#endif
    
    const uint32_t add = (cacheSize >> 3) + 1;
    for( size_t j = 0; j < add; ++j )
        cache.push_back( new Command( freeCounter ));

    freeCounter += add;
    const int32_t num = int32_t( cache.size() >> _freeShift );
    _maxFree[ which ] = EQ_MAX( _minFree[ which ], num );
    _position[ which ] = cache.begin();

#ifdef PROFILE
    _allocs += add;
#endif

    return *( cache.back( ));
}
コード例 #14
0
ファイル: masterCM.cpp プロジェクト: cstalder/Equalizer
//---------------------------------------------------------------------------
// command handlers
//---------------------------------------------------------------------------
bool MasterCM::_cmdSlaveDelta( Command& command )
{
    EQ_TS_THREAD( _cmdThread );
    const ObjectSlaveDeltaPacket* packet = 
        command.get< ObjectSlaveDeltaPacket >();

    EQASSERTINFO( _pendingDeltas.size() < 100,
                  "More than 100 unfinished slave commits!?" );

    ObjectDataIStream* istream = 0;
    PendingStreams::iterator i = _pendingDeltas.begin();
    for( ; i != _pendingDeltas.end(); ++i )
    {
        PendingStream& pending = *i;
        if( pending.first == packet->commit )
        {
            istream = pending.second;
            break;
        }
    }

    if( !istream )
    {
        EQASSERT( i == _pendingDeltas.end( ));
        istream = _iStreamCache.alloc();
    }

    istream->addDataPacket( command );

    if( istream->isReady( ))
    {
        if( i != _pendingDeltas.end( ))
            _pendingDeltas.erase( i );

        _queuedDeltas.push( istream );
        _object->notifyNewVersion();
        EQASSERTINFO( _queuedDeltas.getSize() < 100,
                      "More than 100 queued slave commits!?" );
#if 0
        EQLOG( LOG_OBJECTS )
            << "Queued slave commit " << packet->commit << " object "
            << _object->getID() << " " << base::className( _object )
            << std::endl;
#endif
    }
    else if( i == _pendingDeltas.end( ))
    {
        _pendingDeltas.push_back( PendingStream( packet->commit, istream ));
#if 0
        EQLOG( LOG_OBJECTS )
            << "New incomplete slave commit " << packet->commit << " object "
            << _object->getID() << " " << base::className( _object )
            << std::endl;
#endif
    }
#if 0
    else
        EQLOG( LOG_OBJECTS )
            << "Got data for incomplete slave commit " << packet->commit
            << " object " << _object->getID() << " "
            << base::className( _object ) << std::endl;
#endif

    return true;
}
コード例 #15
0
void FrameBufferObject::bind()
{
    EQ_TS_THREAD( _thread );
    EQASSERT( _fboID );
    EQ_GL_CALL( glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, _fboID ));
}
コード例 #16
0
ファイル: fullMasterCM.cpp プロジェクト: oliver-e/Equalizer
void FullMasterCM::addSlave( Command& command, NodeMapObjectReplyPacket& reply )
{
    EQ_TS_THREAD( _cmdThread );
    EQASSERT( command->type == PACKETTYPE_CO_NODE );
    EQASSERT( command->command == CMD_NODE_MAP_OBJECT );

    NodePtr node = command.getNode();
    const NodeMapObjectPacket* packet = command.get< NodeMapObjectPacket >();
    const uint128_t requested  = packet->requestedVersion;
    const uint32_t instanceID = packet->instanceID;

    Mutex mutex( _slaves );
    EQASSERT( _version != VERSION_NONE );
    _checkConsistency();

    // add to subscribers
    ++_slavesCount[ node->getNodeID() ];
    _slaves->push_back( node );
    stde::usort( *_slaves );

    if( requested == VERSION_NONE ) // no data to send
    {
        _sendEmptyVersion( node, instanceID, _version );
        reply.version = _version;
        return;
    }

    const uint128_t oldest = _instanceDatas.front()->os.getVersion();
    uint128_t start = (requested == VERSION_OLDEST || requested < oldest ) ?
                          oldest : requested;
    uint128_t end = _version;
    const bool useCache = packet->masterInstanceID == _object->getInstanceID();

#ifndef NDEBUG
    if( requested != VERSION_OLDEST && requested < start )
        EQINFO << "Mapping version " << start
               << " instead of requested version " << requested << std::endl;
#endif

    reply.version = start;
    reply.useCache = packet->useCache && useCache;

    if( reply.useCache )
    {
        if( packet->minCachedVersion <= start && 
            packet->maxCachedVersion >= start )
        {
#ifdef EQ_INSTRUMENT_MULTICAST
            _hit += packet->maxCachedVersion + 1 - start;
#endif
            start = packet->maxCachedVersion + 1;
        }
        else if( packet->maxCachedVersion == end )
        {
            end = EQ_MAX( start, packet->minCachedVersion - 1 );
#ifdef EQ_INSTRUMENT_MULTICAST
            _hit += _version - end;
#endif
        }
        // TODO else cached block in the middle, send head and tail elements
    }

#if 0
    EQLOG( LOG_OBJECTS )
        << *_object << ", instantiate on " << node->getNodeID() << " with v"
        << ((requested == VERSION_OLDEST) ? oldest : requested) << " ("
        << requested << ") sending " << start << ".." << end << " have "
        << _version - _nVersions << ".." << _version << " "
        << _instanceDatas.size() << std::endl;
#endif
    EQASSERT( start >= oldest );

    // send all instance datas from start..end
    InstanceDataDeque::iterator i = _instanceDatas.begin();
    while( i != _instanceDatas.end() && (*i)->os.getVersion() < start )
        ++i;

    for( ; i != _instanceDatas.end() && (*i)->os.getVersion() <= end; ++i )
    {
        InstanceData* data = *i;
        EQASSERT( data );
        data->os.sendMapData( node, instanceID );

#ifdef EQ_INSTRUMENT_MULTICAST
        ++_miss;
#endif
    }

#ifdef EQ_INSTRUMENT_MULTICAST
    if( _miss % 100 == 0 )
        EQINFO << "Cached " << _hit << "/" << _hit + _miss
               << " instance data transmissions" << std::endl;
#endif
}
コード例 #17
0
ファイル: localNode.cpp プロジェクト: MichaelVlad/Equalizer
//----------------------------------------------------------------------
// receiver thread functions
//----------------------------------------------------------------------
void LocalNode::_runReceiverThread()
{
    EQ_TS_THREAD( _rcvThread );

    int nErrors = 0;
    while( _state == STATE_LISTENING )
    {
        const ConnectionSet::Event result = _incoming.select();
        switch( result )
        {
            case ConnectionSet::EVENT_CONNECT:
                _handleConnect();
                break;

            case ConnectionSet::EVENT_DATA:
                _handleData();
                break;

            case ConnectionSet::EVENT_DISCONNECT:
            case ConnectionSet::EVENT_INVALID_HANDLE:
                _handleDisconnect();
                break;

            case ConnectionSet::EVENT_TIMEOUT:
                EQINFO << "select timeout" << std::endl;
                break;

            case ConnectionSet::EVENT_ERROR:
                ++nErrors;
                EQWARN << "Connection error during select" << std::endl;
                if( nErrors > 100 )
                {
                    EQWARN << "Too many errors in a row, capping connection" 
                           << std::endl;
                    _handleDisconnect();
                }
                break;

            case ConnectionSet::EVENT_SELECT_ERROR:
                EQWARN << "Error during select" << std::endl;
                ++nErrors;
                if( nErrors > 10 )
                {
                    EQWARN << "Too many errors in a row" << std::endl;
                    EQUNIMPLEMENTED;
                }
                break;

            case ConnectionSet::EVENT_INTERRUPT:
                _redispatchCommands();
                break;

            default:
                EQUNIMPLEMENTED;
        }
        if( result != ConnectionSet::EVENT_ERROR && 
            result != ConnectionSet::EVENT_SELECT_ERROR )

            nErrors = 0;
    }

    if( !_pendingCommands.empty( ))
        EQWARN << _pendingCommands.size() 
               << " commands pending while leaving command thread" << std::endl;

    for( CommandList::const_iterator i = _pendingCommands.begin();
         i != _pendingCommands.end(); ++i )
    {
        Command* command = *i;
        command->release();
    }

    EQCHECK( _commandThread->join( ));
    _objectStore->clear();
    _pendingCommands.clear();
    _commandCache.flush();

    EQINFO << "Leaving receiver thread of " << base::className( this )
           << std::endl;
}
コード例 #18
0
void GLXEventHandler::_processEvent( GLXWindowEvent& event )
{
    EQ_TS_THREAD( _thread );

    XEvent& xEvent = event.xEvent;
    XID drawable = xEvent.xany.window;

    if( _window->getXDrawable() != drawable )
        return;

    Window* window = _window->getWindow();

    switch( xEvent.type )
    {
        case Expose:
            if( xEvent.xexpose.count ) // Only report last expose event
                return;
                
            event.type = Event::WINDOW_EXPOSE;
            break;

        case ConfigureNotify:
            event.type = Event::WINDOW_RESIZE;
            _getWindowSize( xEvent.xany.display, drawable, event.resize );
            break;

        case UnmapNotify:
            event.type = Event::WINDOW_HIDE;
            _getWindowSize( xEvent.xany.display, drawable, event.resize );
            break;

        case MapNotify:
            event.type = Event::WINDOW_SHOW;
            _getWindowSize( xEvent.xany.display, drawable, event.resize );
            break;

        case ClientMessage:
        {
            Atom deleteAtom = XInternAtom( xEvent.xany.display,
                                           "WM_DELETE_WINDOW", False );

            if( static_cast<Atom>( xEvent.xclient.data.l[0] ) != deleteAtom )
                return; // not a delete message, ignore.
        }
        // else: delete message, fall through
        case DestroyNotify:
            event.type = Event::WINDOW_CLOSE;
            break;

        case MotionNotify:
            event.type = Event::WINDOW_POINTER_MOTION;
            event.pointerMotion.x = xEvent.xmotion.x;
            event.pointerMotion.y = xEvent.xmotion.y;
            event.pointerMotion.buttons = _getButtonState( xEvent );
            event.pointerMotion.button  = PTR_BUTTON_NONE;

            _computePointerDelta( window, event );
            _getRenderContext( window, event );
            break;

        case ButtonPress:
            event.type = Event::WINDOW_POINTER_BUTTON_PRESS;
            event.pointerButtonPress.x = xEvent.xbutton.x;
            event.pointerButtonPress.y = xEvent.xbutton.y;
            event.pointerButtonPress.buttons = _getButtonState( xEvent );
            event.pointerButtonPress.button  = _getButtonAction( xEvent );

            // Translate wheel events
            switch( event.pointerButtonPress.button )
            {
              case PTR_BUTTON4: event.pointerWheel.xAxis = 1; break;
              case PTR_BUTTON5: event.pointerWheel.xAxis = -1; break;
              case PTR_BUTTON6: event.pointerWheel.yAxis = 1; break;
              case PTR_BUTTON7: event.pointerWheel.yAxis = -1; break;
            }
            switch( event.pointerButtonPress.button )
            {
              case PTR_BUTTON4:
              case PTR_BUTTON5:
              case PTR_BUTTON6:
              case PTR_BUTTON7:
                event.type = Event::WINDOW_POINTER_WHEEL;
                event.pointerWheel.button = PTR_BUTTON_NONE;
            }

            _computePointerDelta( window, event );
            _getRenderContext( window, event );
            break;
            
        case ButtonRelease:
            event.type = Event::WINDOW_POINTER_BUTTON_RELEASE;
            event.pointerButtonRelease.x = xEvent.xbutton.x;
            event.pointerButtonRelease.y = xEvent.xbutton.y;
            event.pointerButtonRelease.buttons = _getButtonState( xEvent );
            event.pointerButtonRelease.button  = _getButtonAction( xEvent);
            
            _computePointerDelta( window, event );
            _getRenderContext( window, event );
            break;
            
        case KeyPress:
            event.type = Event::KEY_PRESS;
            event.keyPress.key = _getKey( xEvent );
            break;
                
        case KeyRelease:
            event.type = Event::KEY_RELEASE;
            event.keyPress.key = _getKey( xEvent );
            break;

        case ReparentNotify:
        case VisibilityNotify:
            event.type = Event::UNKNOWN;
            EQINFO << "Ignored X event, type " << xEvent.type << std::endl;
            break;

        default:
            event.type = Event::UNKNOWN;
            EQWARN << "Unhandled X event, type " << xEvent.type << std::endl;
            break;
    }

    event.originator = window->getID();
    event.serial = window->getSerial();
    _window->processEvent( event );
}
コード例 #19
0
void UnbufferedMasterCM::addSlave( Command& command, 
                                   NodeMapObjectReplyPacket& reply )
{
    EQ_TS_THREAD( _cmdThread );
    EQASSERT( command->type == PACKETTYPE_CO_NODE );
    EQASSERT( command->command == CMD_NODE_MAP_OBJECT );

    NodePtr node = command.getNode();
    NodeMapObjectPacket* packet =
        command.get<NodeMapObjectPacket>();
    const uint128_t version = packet->requestedVersion;
    const uint32_t instanceID = packet->instanceID;

    // add to subscribers
    ++_slavesCount[ node->getNodeID() ];
    _slaves.push_back( node );
    stde::usort( _slaves );

#if 0
    EQLOG( LOG_OBJECTS ) << "Object id " << _object->_id << " v" << _version
                         << ", instantiate on " << node->getNodeID()
                         << std::endl;
#endif
    reply.version = _version;

    if( version == VERSION_NONE )
    {
        // no data, send empty packet to set version
        _sendEmptyVersion( node, instanceID );
        return;
    }


#ifndef NDEBUG
    if( version != VERSION_OLDEST && version < _version )
        EQINFO << "Mapping version " << _version
               << " instead of requested version" << version << std::endl;
#endif

    const bool useCache = packet->masterInstanceID == _object->getInstanceID();

    if( useCache && 
        packet->minCachedVersion <= _version && 
        packet->maxCachedVersion >= _version )
    {
#ifdef EQ_INSTRUMENT_MULTICAST
        ++_hit;
#endif
        reply.useCache = true;
        return;
    }

#ifdef EQ_INSTRUMENT_MULTICAST
    ++_miss;
#endif

    // send instance data
    ObjectInstanceDataOStream os( this );

    os.enableMap( _version, node, instanceID );
    _object->getInstanceData( os );
    os.disable();
    if( os.hasSentData( ))
        return;

    // no data, send empty packet to set version
    _sendEmptyVersion( node, instanceID );
}