Classes | Public Member Functions | Protected Types | Protected Member Functions | Protected Attributes | Friends

PubSubLobby Class Reference

#include <PubSubLobby.h>

Inheritance diagram for PubSubLobby:
BaseOverlay BaseRpc BaseTcpSupport TopologyVis RpcListener

List of all members.

Classes

class  ChildEntry

Public Member Functions

virtual ~PubSubLobby ()
virtual void initializeOverlay (int stage)
 Initializes derived-class-attributes.
virtual void finishOverlay ()
 collects statistical data in derived class
virtual void handleUDPMessage (BaseOverlayMessage *msg)
 Processes messages from underlay.
virtual void handleTimerEvent (cMessage *msg)
virtual bool handleRpcCall (BaseCallMessage *msg)
virtual void handleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt)
virtual void handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, cPolymorphic *context, int rpcId, const OverlayKey &destKey)

Protected Types

typedef std::map
< TransportAddress, ChildEntry
PlayerMap
typedef std::multimap< int,
ChildEntry *, std::greater
< int > > 
PlayerRessourceMap

Protected Member Functions

virtual void handleJoin (PubSubJoinCall *joinMsg)
virtual void handleHelpCall (PubSubHelpCall *helpMsg)
virtual void handleRespCall (PubSubResponsibleNodeCall *respCall)
virtual void handleTakeOverResponse (PubSubTakeOverSubspaceResponse *takeOverResp)
virtual void handleTakeOverTimeout (PubSubTakeOverSubspaceCall *takeOverCall, const TransportAddress &oldNode)
void handleHelpReleaseMessage (PubSubHelpReleaseMessage *helpRMsg)
void replaceResponsibleNode (int subspaceId, NodeHandle respNode)
void replaceResponsibleNode (PubSubSubspaceId subspaceId, NodeHandle respNode)
void failedNode (const TransportAddress &node)

Protected Attributes

int subspaceSize
int numSubspaces
std::vector< std::vector
< PubSubSubspaceLobby > > 
subspaces
std::list< PubSubHelpCall * > waitingForHelp
PlayerMap playerMap
PlayerRessourceMap playerRessourceMap
int numPubSubSignalingMessages
int pubSubSignalingMessagesSize

Friends

std::ostream & operator<< (std::ostream &o, const ChildEntry &entry)

Detailed Description

Definition at line 36 of file PubSubLobby.h.


Member Typedef Documentation

typedef std::map<TransportAddress, ChildEntry> PubSubLobby::PlayerMap [protected]

Definition at line 73 of file PubSubLobby.h.

typedef std::multimap<int, ChildEntry*, std::greater<int> > PubSubLobby::PlayerRessourceMap [protected]

Definition at line 75 of file PubSubLobby.h.


Constructor & Destructor Documentation

PubSubLobby::~PubSubLobby (  )  [virtual]

Definition at line 474 of file PubSubLobby.cc.

{
}


Member Function Documentation

void PubSubLobby::failedNode ( const TransportAddress node  )  [protected]

Definition at line 414 of file PubSubLobby.cc.

Referenced by handleTakeOverTimeout(), and handleUDPMessage().

{
    if( node.isUnspecified() ) return;

    // Find node in playerMap
    PlayerMap::iterator playerIt = playerMap.find( node );
    if( playerIt == playerMap.end() ){
        // Player was already deleted
        return;
    }
    ChildEntry* respNodeEntry = &(playerIt->second);

// FIXME: only for debugging
if( GlobalNodeListAccess().get()->getPeerInfo( node ) ){
    opp_error("Trying to delete node that's still there...");
}

    // check if node was responsible for a subspace
    set<int>::iterator dutyIt;
    for( dutyIt = respNodeEntry->dutySet.begin(); dutyIt != respNodeEntry->dutySet.end(); ++dutyIt ){
        PubSubSubspaceId subspaceId( *dutyIt, numSubspaces );
        PubSubSubspaceLobby& subspace = subspaces[subspaceId.getX()][subspaceId.getY()];
        if( !subspace.getResponsibleNode().isUnspecified() && node == subspace.getResponsibleNode() ){
            // remove old responsible node
            subspace.setResponsibleNode(NodeHandle());

            // wait for the backup node to claim subspace; if timer expires, waiting-flag will be reset
            subspace.waitingForRespNode = true;
            PubSubTimer* graceTimer = new PubSubTimer("Grace timer for claiming subspace");
            graceTimer->setType( PUBSUB_TAKEOVER_GRACE_TIME );
            graceTimer->setSubspaceId( subspace.getId().getId() );
            scheduleAt( simTime() + 5, graceTimer ); //FIXME: make it a parameter
        }
    }

   // delete node from backupList
    pair<PlayerRessourceMap::iterator, PlayerRessourceMap::iterator> resRange;
    PlayerRessourceMap::iterator resIt;

    resRange = playerRessourceMap.equal_range( respNodeEntry->ressources );
    for( resIt = resRange.first; resIt != resRange.second; ++resIt ){
        if( resIt->second == respNodeEntry ){
            playerRessourceMap.erase( resIt );
            break;
        }
    }
    playerMap.erase( playerIt );
}

void PubSubLobby::finishOverlay (  )  [virtual]

collects statistical data in derived class

Reimplemented from BaseOverlay.

Definition at line 463 of file PubSubLobby.cc.

{
    simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
    if (time < GlobalStatistics::MIN_MEASURED) return;

    globalStatistics->addStdDev("PubSubLobby: Sent Signaling Messages/s",
                                numPubSubSignalingMessages / time);
    globalStatistics->addStdDev("PubSubLobby: Sent Signaling bytes/s",
                                pubSubSignalingMessagesSize / time);
}

void PubSubLobby::handleHelpCall ( PubSubHelpCall helpMsg  )  [protected, virtual]

Definition at line 226 of file PubSubLobby.cc.

Referenced by handleRpcCall().

{
    // A node needs help! Give him the handle of the node with the most ressources...
    const NodeHandle& src = helpMsg->getSrcNode();
    int subspaceId = helpMsg->getSubspaceId();
    PlayerRessourceMap::iterator it;
    for( it = playerRessourceMap.begin(); it != playerRessourceMap.end(); ++it ){
        if( it->second->handle != src &&
               it->second->dutySet.find( subspaceId ) == it->second->dutySet.end() &&
               it->second->ressources > 1 ){
            break;
        }
    }

    // No suitable node found!
    if( it == playerRessourceMap.end() ){
        waitingForHelp.push_back( helpMsg );
        return;
    }

    // decrease ressources
    ChildEntry* child = it->second;
    child->ressources -= ( helpMsg->getHelpType() == PUBSUB_BACKUP ) ? 2 : 1; // FIXME: make it a parameter
    child->dutySet.insert( subspaceId );
    playerRessourceMap.erase( it );
    playerRessourceMap.insert( make_pair(child->ressources, child) );

    // Send handle to requesting node
    PubSubHelpResponse* helpResp = new PubSubHelpResponse("Ask him to help you");
    helpResp->setSubspaceId( subspaceId );
    helpResp->setHelpType( helpMsg->getHelpType() );
    helpResp->setNode( child->handle );
    helpResp->setBitLength( PUBSUB_HELPRESPONSE_L( helpResp ));
    RECORD_STATS(
            ++numPubSubSignalingMessages;
            pubSubSignalingMessagesSize += helpResp->getByteLength()
            );
    sendRpcResponse( helpMsg, helpResp );
}

void PubSubLobby::handleHelpReleaseMessage ( PubSubHelpReleaseMessage helpRMsg  )  [protected]

Definition at line 331 of file PubSubLobby.cc.

Referenced by handleUDPMessage().

{
    PlayerMap::iterator playerIt = playerMap.find( helpRMsg->getNode() );
    if( playerIt == playerMap.end() ){
        // Player was already deleted
        return;
    }
    ChildEntry* nodeEntry = &(playerIt->second);

    // remove subspace from node's duty set
    nodeEntry->dutySet.erase( helpRMsg->getSubspaceId() );

    // Increase node's ressources
    pair<PlayerRessourceMap::iterator, PlayerRessourceMap::iterator> resRange;
    PlayerRessourceMap::iterator resIt;
    resRange = playerRessourceMap.equal_range( nodeEntry->ressources );
    for( resIt = resRange.first; resIt != resRange.second; ++resIt ){
        if( resIt->second == nodeEntry ){
            playerRessourceMap.erase( resIt );
            break;
        }
    }
    nodeEntry->ressources += 1; // FIXME: make it a parameter
    playerRessourceMap.insert( make_pair(nodeEntry->ressources, nodeEntry) );
}

void PubSubLobby::handleJoin ( PubSubJoinCall joinMsg  )  [protected, virtual]

Definition at line 138 of file PubSubLobby.cc.

Referenced by handleRpcCall().

{
    // Insert node in the queue of possible backup nodes
    ChildEntry e;
    e.handle = joinMsg->getSrcNode();
    e.ressources = joinMsg->getRessources();

    pair<PlayerMap::iterator, bool> inserter;
    inserter = playerMap.insert( make_pair( e.handle, e ));
    ChildEntry* childEntry = &(inserter.first->second);
    //pair<PlayerRessourceMap::iterator, bool> rInserter;
    //rInserter = playerRessourceMap.insert( make_pair( e.ressources, childEntry ));
    PlayerRessourceMap::iterator rInserter;
    rInserter = playerRessourceMap.insert( make_pair( e.ressources, childEntry ));
    bool insertedAtBegin = rInserter == playerRessourceMap.begin();

    // send answer with responsible node
    PubSubJoinResponse* joinResp = new PubSubJoinResponse( "Join Response");
    unsigned int x = (unsigned int) (joinMsg->getPosition().x / subspaceSize);
    unsigned int y = (unsigned int) (joinMsg->getPosition().y / subspaceSize);
    PubSubSubspaceLobby& subspace = subspaces[x][y];
    NodeHandle respNode = subspace.getResponsibleNode();
    joinResp->setResponsibleNode( respNode );
    joinResp->setBitLength( PUBSUB_JOINRESPONSE_L( joinResp ));
    RECORD_STATS(
            ++numPubSubSignalingMessages;
            pubSubSignalingMessagesSize += joinResp->getByteLength()
            );
    sendRpcResponse( joinMsg, joinResp );

    if( respNode.isUnspecified() && !subspace.waitingForRespNode) {
        // respNode is unknown, create new...
        // TODO: refactor: make a funktion out of this...
        PubSubTakeOverSubspaceCall* toCall = new PubSubTakeOverSubspaceCall( "Take over subspace");
        toCall->setSubspacePos( Vector2D(x, y) );

        ChildEntry* child = playerRessourceMap.begin()->second;
        toCall->setBitLength( PUBSUB_TAKEOVERSUBSPACECALL_L( toCall ));
        RECORD_STATS(
                ++numPubSubSignalingMessages;
                pubSubSignalingMessagesSize += toCall->getByteLength()
                );
        sendUdpRpcCall( child->handle, toCall );

        playerRessourceMap.erase( playerRessourceMap.begin() );
        child->dutySet.insert( subspace.getId().getId() );
        child->ressources-=2; // XXX FIXME: make it a parameter...
        if( insertedAtBegin ){
            rInserter = playerRessourceMap.insert( make_pair(child->ressources, child) );
        } else {
            playerRessourceMap.insert( make_pair(child->ressources, child) );
        }

        subspace.waitingForRespNode = true;
    }

    // New node is out of luck: he gets to help all waiting nodes as long as he has ressources left
    if( waitingForHelp.size() > 0 ) {
        std::list<PubSubHelpCall*>::iterator it = waitingForHelp.begin();
        while( it != waitingForHelp.end() ) {
            // Insert subspace into node's dutySet
            if( childEntry->dutySet.insert( (*it)->getSubspaceId() ).second ){
                // If it was not already there (due to duplicate HelpCalls because of retransmissions),
                // decrease ressources
                childEntry->ressources -= ( (*it)->getHelpType() == PUBSUB_BACKUP ) ? 2 : 1; // FIXME: make it a parameter
            }

            PubSubHelpResponse* helpResp = new PubSubHelpResponse("Ask him to help you");
            helpResp->setSubspaceId( (*it)->getSubspaceId() );
            helpResp->setType( (*it)->getType() );
            helpResp->setNode( e.handle );
            helpResp->setBitLength( PUBSUB_HELPRESPONSE_L( helpResp ));
            RECORD_STATS(
                    ++numPubSubSignalingMessages;
                    pubSubSignalingMessagesSize += helpResp->getByteLength()
                    );
            sendRpcResponse( *it, helpResp );

            waitingForHelp.erase( it++ );

            if( childEntry->ressources <= 0 ) break; // FIXME: clean up duplicate calls!
        }
        // Fix ressource map entry
        playerRessourceMap.erase( rInserter );
        playerRessourceMap.insert( make_pair(childEntry->ressources, childEntry) );
    }
}

void PubSubLobby::handleRespCall ( PubSubResponsibleNodeCall respCall  )  [protected, virtual]

Definition at line 266 of file PubSubLobby.cc.

Referenced by handleRpcCall().

{
    unsigned int x = (unsigned int) respCall->getSubspacePos().x;
    unsigned int y = (unsigned int) respCall->getSubspacePos().y;
    NodeHandle respNode = subspaces[x][y].getResponsibleNode();
    if( !respNode.isUnspecified() ) {
        PubSubSubspaceId region( x, y, numSubspaces);

        PubSubResponsibleNodeResponse* msg = new PubSubResponsibleNodeResponse( "ResponsibleNode Response");
        msg->setResponsibleNode( respNode );
        msg->setSubspaceId( region.getId() );
        msg->setBitLength( PUBSUB_RESPONSIBLENODERESPONSE_L( msg ));
        RECORD_STATS(
                ++numPubSubSignalingMessages;
                pubSubSignalingMessagesSize += msg->getByteLength()
                );
        sendRpcResponse( respCall, msg );
    } else {
        // no responsible node for subspace known.
        // push call to list of waiting nodes ...
        PubSubSubspaceLobby& subspace = subspaces[x][y];
        subspace.waitingNodes.push_back( respCall );

        if (!subspace.waitingForRespNode) {
            // ... and ask a node to take over the subspace
            PubSubTakeOverSubspaceCall* msg = new PubSubTakeOverSubspaceCall( "Take over subspace");
            msg->setSubspacePos( Vector2D( x, y) );

            ChildEntry* child = playerRessourceMap.begin()->second;
            msg->setBitLength( PUBSUB_TAKEOVERSUBSPACECALL_L( msg ));
            RECORD_STATS(
                    ++numPubSubSignalingMessages;
                    pubSubSignalingMessagesSize += msg->getByteLength()
                    );
            sendUdpRpcCall( child->handle, msg );

            playerRessourceMap.erase( playerRessourceMap.begin() );
            child->dutySet.insert( subspace.getId().getId() );
            // Decrease ressources. Note: the ressources are decreased by the cost of an "backup" node
            // The rest will be decreased when the new responsible answeres the takeover call
            child->ressources-=1; // FIXME: make it a parameter...
            playerRessourceMap.insert( make_pair(child->ressources, child) );

            subspace.waitingForRespNode = true;
        }
    }
}

bool PubSubLobby::handleRpcCall ( BaseCallMessage msg  )  [virtual]

Definition at line 96 of file PubSubLobby.cc.

{
    // delegate messages
    RPC_SWITCH_START( msg )
    RPC_DELEGATE( PubSubJoin, handleJoin );
    RPC_DELEGATE( PubSubHelp, handleHelpCall );
    RPC_DELEGATE( PubSubResponsibleNode, handleRespCall );
    RPC_SWITCH_END( )

    return RPC_HANDLED;
}

void PubSubLobby::handleRpcResponse ( BaseResponseMessage msg,
cPolymorphic *  context,
int  rpcId,
simtime_t  rtt 
) [virtual]

Definition at line 108 of file PubSubLobby.cc.

{
    RPC_SWITCH_START(msg);
    RPC_ON_RESPONSE( PubSubTakeOverSubspace ) {
        handleTakeOverResponse( _PubSubTakeOverSubspaceResponse );
        break;
    }
    RPC_SWITCH_END( );
}

void PubSubLobby::handleRpcTimeout ( BaseCallMessage msg,
const TransportAddress dest,
cPolymorphic *  context,
int  rpcId,
const OverlayKey destKey 
) [virtual]

Definition at line 120 of file PubSubLobby.cc.

{
    RPC_SWITCH_START(msg)
    RPC_ON_CALL( PubSubTakeOverSubspace ) {
        handleTakeOverTimeout( _PubSubTakeOverSubspaceCall, dest );
        EV << "[PubSubMMOG::handleRpcTimeout() @ " << thisNode.getIp()
           << " (" << thisNode.getKey().toString(16) << ")]\n"
           << "    TakeOverSubspace RPC Call timed out: id=" << rpcId << "\n"
           << "    msg=" << *_PubSubTakeOverSubspaceCall
           << endl;
        break;
    }
    RPC_SWITCH_END( )
}

void PubSubLobby::handleTakeOverResponse ( PubSubTakeOverSubspaceResponse takeOverResp  )  [protected, virtual]

Definition at line 314 of file PubSubLobby.cc.

Referenced by handleRpcResponse().

{
    NodeHandle respNode = takeOverResp->getSrcNode();
    unsigned int x = (unsigned int) takeOverResp->getSubspacePos().x;
    unsigned int y = (unsigned int) takeOverResp->getSubspacePos().y;
    PubSubSubspaceId region( x, y, numSubspaces);

    replaceResponsibleNode( region, takeOverResp->getSrcNode() );
}

void PubSubLobby::handleTakeOverTimeout ( PubSubTakeOverSubspaceCall takeOverCall,
const TransportAddress oldNode 
) [protected, virtual]

Definition at line 324 of file PubSubLobby.cc.

Referenced by handleRpcTimeout().

{
    Vector2D pos = takeOverCall->getSubspacePos();
    subspaces[(int) pos.x][(int) pos.y].waitingForRespNode = false;
    failedNode( oldNode );
}

void PubSubLobby::handleTimerEvent ( cMessage *  msg  )  [virtual]

Definition at line 67 of file PubSubLobby.cc.

{
    if( PubSubTimer* timer = dynamic_cast<PubSubTimer*>(msg) ) {
        if( timer->getType() == PUBSUB_TAKEOVER_GRACE_TIME ){
            // Grace period for subspace takeover timed out.
            // If noone claimed the subspace yet, the next respNode query will
            // trigger the selection of a new responsible node
            PubSubSubspaceId subspaceId(timer->getSubspaceId(), numSubspaces );
            subspaces[subspaceId.getX()][subspaceId.getY()].waitingForRespNode = false;
            delete timer;
        }
    }
}

void PubSubLobby::handleUDPMessage ( BaseOverlayMessage msg  )  [virtual]

Processes messages from underlay.

Parameters:
msg Message from UDP

Reimplemented from BaseOverlay.

Definition at line 81 of file PubSubLobby.cc.

{
    if( PubSubFailedNodeMessage* failMsg = dynamic_cast<PubSubFailedNodeMessage*>(msg) ){
        failedNode( failMsg->getFailedNode() );
        delete msg;

    } else if( PubSubReplacementMessage* repMsg = dynamic_cast<PubSubReplacementMessage*>(msg) ){
        replaceResponsibleNode( repMsg->getSubspaceId(), repMsg->getNewResponsibleNode() );
        delete msg;
    } else if( PubSubHelpReleaseMessage* helpRMsg = dynamic_cast<PubSubHelpReleaseMessage*>(msg) ){
        handleHelpReleaseMessage( helpRMsg );
        delete msg;
    }
}

void PubSubLobby::initializeOverlay ( int  stage  )  [virtual]

Initializes derived-class-attributes.


Initializes derived-class-attributes, called by BaseOverlay::initialize(). By default this method is called once. If more stages are needed one can overload numInitStages() and add more stages.

Parameters:
stage the init stage

Reimplemented from BaseOverlay.

Definition at line 39 of file PubSubLobby.cc.

{
    // because of IPAddressResolver, we need to wait until interfaces are registered,
    // address auto-assignment takes place etc.
    if(stage != MIN_STAGE_OVERLAY) return;

    numSubspaces = par("numSubspaces");
    subspaceSize = (int) ( (unsigned int) par("areaDimension") / numSubspaces);

    // FIXME: Inefficient, make subspace a single dimensioned array
    subspaces.resize( numSubspaces );
    for ( int i = 0; i < numSubspaces; ++i ) {
        for( int ii = 0; ii < numSubspaces; ++ii ) {
            PubSubSubspaceId region( i, ii, numSubspaces );
            subspaces[i].push_back( PubSubSubspaceLobby( region ) );
        }
        WATCH_VECTOR( subspaces[i] );
    }
    thisNode.setKey( OverlayKey::random() );
    GlobalNodeListAccess().get()->registerPeer( thisNode );

    numPubSubSignalingMessages = 0;
    pubSubSignalingMessagesSize = 0;
    WATCH( numPubSubSignalingMessages );
    WATCH( pubSubSignalingMessagesSize );
    WATCH_MAP( playerMap );
}

void PubSubLobby::replaceResponsibleNode ( int  subspaceId,
NodeHandle  respNode 
) [protected]

Definition at line 357 of file PubSubLobby.cc.

Referenced by handleTakeOverResponse(), and handleUDPMessage().

{
    replaceResponsibleNode( PubSubSubspaceId( subspaceId, numSubspaces), respNode );
}

void PubSubLobby::replaceResponsibleNode ( PubSubSubspaceId  subspaceId,
NodeHandle  respNode 
) [protected]

Definition at line 362 of file PubSubLobby.cc.

{
    // a new responsible node was found for a subspace
    PubSubSubspaceLobby& subspace = subspaces[subspaceId.getX()][subspaceId.getY()];
//    NodeHandle oldNode = subspace.getResponsibleNode();

    // set new responsible node
    subspace.setResponsibleNode( respNode );
    subspace.waitingForRespNode = false;

    // decrease responsible node's ressources
    pair<PlayerRessourceMap::iterator, PlayerRessourceMap::iterator> resRange;
    PlayerRessourceMap::iterator resIt;
    PlayerMap::iterator plIt = playerMap.find( respNode );

    if( plIt == playerMap.end() ){
        // FIXME: How to react?
        // Best would be: reinsert node. But most probable we have two nodes that want to be
        // responsible, so how to avoid the resulting inconsostency?
        opp_error("PlayerMap inconsistent: Allegedly failed node wants to become Responsible node");
    }
//    ChildEntry* respNodeEntry = &(plIt->second);
//    resRange = playerRessourceMap.equal_range( respNodeEntry->ressources );
//    for( resIt = resRange.first; resIt != resRange.second; ++resIt ){
//        if( resIt->second == respNodeEntry ){
//            playerRessourceMap.erase( resIt );
//            break;
//        }
//    }
//    respNodeEntry->ressources -= 2; // FIXME: make it a parameter
//    playerRessourceMap.insert( make_pair(respNodeEntry->ressources, respNodeEntry) );

    // remove old node from backupList->he failed...
//    failedNode( oldNode );

    // inform all waiting nodes...
    std::list<PubSubResponsibleNodeCall*>::iterator it;
    for( it = subspace.waitingNodes.begin(); it != subspace.waitingNodes.end(); ++it ) {
        PubSubResponsibleNodeResponse* msg = new PubSubResponsibleNodeResponse( "ResponsibleNode Response");
        msg->setResponsibleNode( respNode );
        msg->setSubspaceId( subspaceId.getId() );
        msg->setBitLength( PUBSUB_RESPONSIBLENODERESPONSE_L( msg ));
        RECORD_STATS(
                ++numPubSubSignalingMessages;
                pubSubSignalingMessagesSize += msg->getByteLength()
                );
        sendRpcResponse( *it, msg );
    }
    subspace.waitingNodes.clear();
}


Friends And Related Function Documentation

std::ostream& operator<< ( std::ostream &  o,
const ChildEntry entry 
) [friend]

Definition at line 31 of file PubSubLobby.cc.

{
    o << "Node: " << entry.handle << " ressources: " << entry.ressources;
    return o;
}


Member Data Documentation

int PubSubLobby::subspaceSize [protected]

Definition at line 67 of file PubSubLobby.h.

Referenced by handleJoin(), and initializeOverlay().

Definition at line 70 of file PubSubLobby.h.

Referenced by handleHelpCall(), and handleJoin().


The documentation for this class was generated from the following files: