Public Types | Public Member Functions | Protected Member Functions | Private Member Functions | Private Attributes | Static Private Attributes | Friends

oversim::Nice Class Reference

NICE overlay module. More...

#include <Nice.h>

Inheritance diagram for oversim::Nice:
BaseOverlay BaseRpc BaseTcpSupport TopologyVis RpcListener

List of all members.

Public Types

typedef std::set
< TransportAddress
TaSet
typedef std::set
< TransportAddress >::iterator 
TaSetIt

Public Member Functions

 Nice ()
virtual ~Nice ()
virtual void initializeOverlay (int stage)
 Initializes derived-class-attributes.
virtual void handleTimerEvent (cMessage *msg)
virtual void handleUDPMessage (BaseOverlayMessage *msg)
 Processes messages from underlay.
virtual void handleAppMessage (cMessage *msg)
 Processes "timer" self-messages.
virtual void finishOverlay ()
 collects statistical data in derived class

Protected Member Functions

virtual void changeState (int toState)
 changes node state
virtual void joinOverlay ()
 Join the overlay with a given nodeID in thisNode.key.
virtual void handleNodeLeaveNotification ()
 This method gets call **.gracefulLeaveDelay seconds before it is killed.

Private Member Functions

void updateVisualization ()
int getHighestLeaderLayer ()
int getHighestLayer ()
void BasicJoinLayer (short layer)
void ClusterSplit (int layer)
void Query (const TransportAddress &node, short layer)
void handleNiceClusterMergeRequest (NiceClusterMerge *mergeMsg)
void handleNiceForceMerge (NiceMessage *msg)
void handleNiceHeartbeat (NiceHeartbeat *msg)
void handleNiceLeaderHeartbeat (NiceLeaderHeartbeat *lhbMsg)
void handleNiceLeaderTransfer (NiceLeaderHeartbeat *transferMsg)
void handleNiceJoinCluster (NiceMessage *joinMsg)
void handleNiceJoineval (NiceMessage *msg)
void handleNiceJoinevalResponse (NiceMessage *msg)
void handleNiceLeaderHeartbeatOrTransfer (NiceMessage *msg)
void handleNiceMulticast (NiceMulticastMessage *multicastMsg)
void handleNicePeerTemporary (NiceMessage *msg)
void handleNicePeerTemporaryRelease (NiceMessage *msg)
void handleNicePingProbe (NiceMessage *msg)
void handleNicePingProbeResponse (NiceMessage *msg)
void handleNicePollRp (NiceMessage *msg)
void handleNicePollRpResponse (NiceMessage *msg)
void handleNiceQuery (NiceMessage *queryMsg)
void handleNiceQueryResponse (NiceMemberMessage *queryRspMsg)
void handleNiceRemove (NiceMessage *msg)
void JoinCluster (const TransportAddress &leader, short layer)
void sendHeartbeats ()
void cleanPeers ()
 Cleans the tempPeers map from peers that have timed out, removes timed-out peers in peerInfos and also removes them from the clusters.
bool splitNeeded ()
 Splits clusters if needed.
bool mergeNeeded ()
 Merges clusters if needed.
bool checkLeaderHeartbeatsForCollisions (NiceLeaderHeartbeat *hbMsg)
 Checks if we have received conflicting leader heartbeats.
void maintenance ()
simtime_t getMaxDistance (TransportAddress member, const std::set< TransportAddress > &neighbors)
template<class ConstIter >
simtime_t getMaxDistance (TransportAddress member, ConstIter neighborsBegin, ConstIter neighborsEnd)
simtime_t getMeanDistance (std::set< TransportAddress > neighbors)
void LeaderTransfer (int layer, TransportAddress leader, TaSet cluster, TransportAddress sc_leader, TaSet superCluster)
void LeaderTransfer (int layer, TransportAddress leader)
void Remove (int layer)
void sendHeartbeatTo (const TransportAddress &node, int layer)
void sendRemoveTo (const TransportAddress &node, int layer)
 sendRemoveTo
void ClusterMerge (int layer)
void ClusterMergeRequest (const TransportAddress &node, int layer)
void gracefulLeave (short bottomLayer)
std::pair< TransportAddress,
simtime_t > 
findCenter (TaSet cluster, bool allowRandom=false)
std::pair< TransportAddress,
simtime_t > 
findCenter (std::vector< TransportAddress > cluster, bool allowRandom=false)
std::pair< TransportAddress,
simtime_t > 
findCenter (const NiceCluster &cluster, bool allowRandom=false)
template<class ConstIter >
std::pair< TransportAddress,
simtime_t > 
findCenter (ConstIter begin, ConstIter end, bool allowRandom=false)
void sendDataToOverlay (NiceMulticastMessage *appMsg)
void pollRP (int layer)

Private Attributes

int pimp
TransportAddress RendevouzPoint
bool isRendevouzPoint
cMessage * heartbeatTimer
simtime_t heartbeatInterval
cMessage * maintenanceTimer
simtime_t maintenanceInterval
cMessage * queryTimer
simtime_t queryInterval
cMessage * rpPollTimer
simtime_t rpPollTimerInterval
double peerTimeoutHeartbeats
cMessage * visualizationTimer
simtime_t first_HB
TransportAddress first_leader
simtime_t second_HB
TransportAddress second_leader
std::vector< std::pair
< TransportAddress, simtime_t > > 
leaderHeartbeats
int clusterrefinement
int debug_heartbeats
int debug_visualization
int debug_join
int debug_peertimeouts
int debug_removes
int debug_queries
unsigned short k
NiceCluster clusters [maxLayers]
int evalLayer
int joinLayer
TransportAddress polledRendevouzPoint
simtime_t query_start
TransportAddress tempResolver
simtime_t query_compare
short targetLayer
std::map< TransportAddress,
NicePeerInfo * > 
peerInfos
std::map< TransportAddress,
simtime_t > 
tempPeers
bool isTempPeered
double CLUSTERLEADERBOUND
double CLUSTERLEADERCOMPAREDIST
double SC_PROC_DISTANCE
double SC_MIN_OFFSET
int numInconsistencies
int numQueryTimeouts
int numPeerTimeouts
int numTempPeerTimeouts
int numStructurePartitions
int numOwnMessagesReceived
double totalSCMinCompare
int numJoins
int numForward
int totalForwardBytes
int numReceived
int totalReceivedBytes
int numHeartbeat
int totalHeartbeatBytes

Static Private Attributes

static const short maxLayers = 10

Friends

class NicePeerInfo

Detailed Description

NICE overlay module.

Implementation of the NICE overlay as described in "Scalable Application Layer Multicast" by S. Banerjee and B. Bhattacharjee and C. Kommareddy, published at SIGCOMM'02, 2002.

Author:
Christian Huebsch

Definition at line 59 of file Nice.h.


Member Typedef Documentation

Definition at line 70 of file Nice.h.

typedef std::set<TransportAddress>::iterator oversim::Nice::TaSetIt

Definition at line 71 of file Nice.h.


Constructor & Destructor Documentation

oversim::Nice::Nice (  ) 

Definition at line 70 of file Nice.cc.

oversim::Nice::~Nice (  )  [virtual]

Definition at line 95 of file Nice.cc.

{

    // destroy self timer messages
    cancelAndDelete(heartbeatTimer);
    cancelAndDelete(maintenanceTimer);
    cancelAndDelete(rpPollTimer);
    cancelAndDelete(queryTimer);
    cancelAndDelete(visualizationTimer);

    std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.begin();

    for (; it != peerInfos.end(); it++) {

        delete it->second;

    }


Member Function Documentation

void oversim::Nice::BasicJoinLayer ( short  layer  )  [private]

Definition at line 553 of file Nice.cc.

Referenced by changeState(), and maintenance().

{

    // Cancel timers involved in structure refinement
    /*
    if (layer == -1 || layer == 0) {
        cancelEvent(maintenanceTimer);
        cancelEvent(heartbeatTimer);
    }
    */

    Query(RendevouzPoint, -1);

    if (layer > -1)
        targetLayer = layer;
    else
        targetLayer = 0;

    // Temporary peer with RP for faster data reception
    NiceMessage* msg = new NiceMessage("NICE_PEER_TEMPORARY");
    msg->setSrcNode(thisNode);
    msg->setCommand(NICE_PEER_TEMPORARY);
    msg->setLayer(-1);
    msg->setBitLength(NICEMESSAGE_L(msg));

    sendMessageToUDP(RendevouzPoint, msg);

    isTempPeered = true;

void oversim::Nice::changeState ( int  toState  )  [protected, virtual]

changes node state

Parameters:
toState state to change to

Definition at line 246 of file Nice.cc.

Referenced by joinOverlay().

{
    switch (toState) {

    case INIT:

        state = INIT;

        getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 1, "red");

        scheduleAt(simTime() + 1, visualizationTimer);

        break;

    case BOOTSTRAP:

        state = BOOTSTRAP;

        /* get rendevouz point */
        RendevouzPoint = bootstrapList->getBootstrapNode();
        if (RendevouzPoint.isUnspecified()) {

            RendevouzPoint = thisNode;
            isRendevouzPoint = true;

            /* join cluster layer 0 as first node */
            clusters[0].add(thisNode);
            clusters[0].setLeader(thisNode);

            changeState(READY);

            return;

        }
        else {

            pollRP(-1);

            /* initiate NICE structure joining */
            BasicJoinLayer(-1);

        }

        break;

    case READY:

        state = READY;

        cancelEvent(heartbeatTimer);
        scheduleAt(simTime() + heartbeatInterval, heartbeatTimer);
        cancelEvent(maintenanceTimer);
        scheduleAt(simTime() + maintenanceInterval, maintenanceTimer);

        getParentModule()->getParentModule()->getDisplayString().setTagArg
        ("i2", 1, clustercolors[getHighestLayer()]);

        setOverlayReady(true);
        /* allow only rendevouz point to be bootstrap node */
        if (!isRendevouzPoint) bootstrapList->removeBootstrapNode(thisNode);

        break;

    }

bool oversim::Nice::checkLeaderHeartbeatsForCollisions ( NiceLeaderHeartbeat hbMsg  )  [private]

Checks if we have received conflicting leader heartbeats.

checkLeaderHeartbeatsForCollisions

Returns true if a collision was detected.

Definition at line 2261 of file Nice.cc.

{

    bool collisionDetected = false;

    //Alternative Detection
    leaderHeartbeats.push_back(std::make_pair(hbMsg->getSrcNode(), simTime()));

    if (leaderHeartbeats.size() > 3) {

        if (debug_heartbeats)
            EV << simTime() << "leaderHeartbeats.size() > 3 :  " << leaderHeartbeats.size() << endl;

        simtime_t predecessor =  leaderHeartbeats.at(leaderHeartbeats.size()-2).second;

        if (debug_heartbeats)
            EV << simTime() << "predecessor :  " << predecessor << endl;


        if (simTime() < (predecessor + heartbeatInterval)) {

            if (debug_heartbeats)
                EV << simTime() << "simTime() < (predecessor + heartbeatInterval)" << endl;

            if (leaderHeartbeats.at(leaderHeartbeats.size()-2).first != hbMsg->getSrcNode()) {

                if (debug_heartbeats) {
                    EV << simTime() << "(leaderHeartbeats.at(leaderHeartbeats.size()-2).first != hbMsg->getSrcNode())" << endl;
                    EV << "leaderHeartbeats.at(leaderHeartbeats.size()-2).first: " << leaderHeartbeats.at(leaderHeartbeats.size()-2).first << endl;
                }

                if (leaderHeartbeats.at(leaderHeartbeats.size()-3).first == hbMsg->getSrcNode()) {

                    if (debug_heartbeats) {
                        EV << simTime() << "(leaderHeartbeats.at(leaderHeartbeats.size()-3).first == hbMsg->getSrcNode())" << endl;
                        EV << "leaderHeartbeats.at(leaderHeartbeats.size()-3).first: " << leaderHeartbeats.at(leaderHeartbeats.size()-3).first << endl;
                        EV << "timestamp: " << leaderHeartbeats.at(leaderHeartbeats.size()-3).second << endl;
                    }

                    if (leaderHeartbeats.at(leaderHeartbeats.size()-4).first == leaderHeartbeats.at(leaderHeartbeats.size()-2).first) {

                        if (debug_heartbeats) {
                            EV << simTime() << "(leaderHeartbeats.at(leaderHeartbeats.size()-4).first == leaderHeartbeats.at(leaderHeartbeats.size()-2).first" << endl;
                            EV << "leaderHeartbeats.at(leaderHeartbeats.size()-4).first: " << leaderHeartbeats.at(leaderHeartbeats.size()-4).first << endl;
                            EV << "timestamp: " << leaderHeartbeats.at(leaderHeartbeats.size()-4).second << endl;

                        }

                        if (debug_heartbeats)
                            EV << simTime() << " : " << thisNode.getIp() << " : CONFLICTING LEADERS!" << endl;

                        NiceMessage* removeMsg = new NiceMessage("NICE_REMOVE");
                        removeMsg->setSrcNode(thisNode);
                        removeMsg->setCommand(NICE_REMOVE);
                        removeMsg->setLayer(hbMsg->getLayer());

                        removeMsg->setBitLength(NICEMESSAGE_L(removeMsg));

                        sendMessageToUDP(leaderHeartbeats.at(leaderHeartbeats.size()-2).first, removeMsg);

                        collisionDetected = true;

                    }

                }

            }
        }

    }


    /* Tidy up leaderheartbeats */
    if (leaderHeartbeats.size() > 4) {

        for (unsigned int i=0; i<(leaderHeartbeats.size()-4); i++) {

            leaderHeartbeats.erase(leaderHeartbeats.begin());

        }

    }

void oversim::Nice::cleanPeers (  )  [private]

Cleans the tempPeers map from peers that have timed out, removes timed-out peers in peerInfos and also removes them from the clusters.

cleanPeers

Definition at line 2148 of file Nice.cc.

Referenced by maintenance().

{
    // Clean tempPeers
    std::vector<TransportAddress> deadTempPeers;
    
    std::map<TransportAddress, simtime_t>::iterator itTempPeer;
    for (itTempPeer = tempPeers.begin(); itTempPeer != tempPeers.end(); ++itTempPeer) {
        if (simTime() > (itTempPeer->second + 3 * heartbeatInterval)) {
            RECORD_STATS(++numTempPeerTimeouts);
            deadTempPeers.push_back(itTempPeer->first);
        }
    }

    std::vector<TransportAddress>::iterator itDead;
    for (itDead = deadTempPeers.begin(); itDead != deadTempPeers.end(); ++itDead) {
        tempPeers.erase(*itDead);
        deleteOverlayNeighborArrow(*itDead);
    }

    /* Delete nodes that haven't been active for too long autonomously */
    std::vector<TransportAddress> deadPeers;

    std::map<TransportAddress, NicePeerInfo*>::iterator itPeer = peerInfos.begin();
    while (itPeer != peerInfos.end()) {

        double offset = peerTimeoutHeartbeats * heartbeatInterval.dbl();
        if (itPeer->first != thisNode && simTime() > (itPeer->second->getActivity() + offset)) {

            if (debug_peertimeouts) {
                EV << simTime() << " : " << thisNode.getIp() << " : PEER TIMED OUT! : " << itPeer->first << endl;
                EV << "Activity : " << itPeer->second->getActivity() << endl;
            }

            RECORD_STATS(++numPeerTimeouts);

            deadPeers.push_back(itPeer->first);

        }

        ++itPeer;

    }

    for (itDead = deadPeers.begin(); itDead != deadPeers.end(); ++itDead) {
        delete peerInfos[*itDead];
        peerInfos.erase(*itDead);

        // Delete nodes from all layer clusters
        for (int i = 0; i < maxLayers; i++) {
            clusters[i].remove(*itDead);
            deleteOverlayNeighborArrow(*itDead);
        }

void oversim::Nice::ClusterMerge ( int  layer  )  [private]

Definition at line 2866 of file Nice.cc.

{

    ASSERT(layer < maxLayers - 1);
    ASSERT(clusters[layer].getLeader() == thisNode);
    simtime_t min_delay = 999;

    TransportAddress min_node = TransportAddress::UNSPECIFIED_NODE;

    for (int i=0; i<clusters[layer+1].getSize(); i++) {

        TransportAddress node = clusters[layer+1].get(i);

        if (node != thisNode) {

            std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(node);

            if (it != peerInfos.end()) {
                simtime_t delay = it->second->get_distance();

                if ((delay > 0) && (delay < min_delay)) {

                    min_delay = delay;
                    min_node = node;

                }
            }
        }

    }

    if (!min_node.isUnspecified()) {

        // send merge request
        ClusterMergeRequest(min_node, layer);

        // leave above layer, we are no longer the leader of this cluster.
        gracefulLeave(layer + 1);

        clusters[layer].add(min_node);
        clusters[layer].setLeader(min_node);
        clusters[layer].confirmLeader();

        for (int j=0; j<clusters[layer+1].getSize(); j++) {

            deleteOverlayNeighborArrow(clusters[layer+1].get(j));

        }

        for (int i = 0, highest = getHighestLayer(); i < highest; i++) {

            getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 1, clustercolors[i]);

        }

    }
    else {

        EV << thisNode.getIp() << " no suitable cluster found";

    }

void oversim::Nice::ClusterMergeRequest ( const TransportAddress node,
int  layer 
) [private]

Definition at line 2934 of file Nice.cc.

Referenced by ClusterMerge().

{
    ASSERT(clusters[layer+1].contains(thisNode));
    ASSERT(!clusters[layer+1].getLeader().isUnspecified());

    NiceClusterMerge* msg = new NiceClusterMerge("NICE_CLUSTER_MERGE_REQUEST");
    msg->setSrcNode(thisNode);
    msg->setCommand(NICE_CLUSTER_MERGE_REQUEST);
    msg->setLayer(layer);

    msg->setMembersArraySize(clusters[layer].getSize());

    /* Fill in members */
    for (int j = 0; j < clusters[layer].getSize(); j++) {

        msg->setMembers(j, clusters[layer].get(j));

        deleteOverlayNeighborArrow(clusters[layer].get(j));

    }

    msg->setNewClusterLeader(clusters[layer+1].getLeader());

    msg->setBitLength(NICECLUSTERMERGE_L(msg));

    getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 0, "block/circle_vs");

    sendMessageToUDP(node, msg);

void oversim::Nice::ClusterSplit ( int  layer  )  [private]

Definition at line 2619 of file Nice.cc.

{

    EV << simTime() << " : " << thisNode.getIp() << " : ClusterSplit in Layer " << layer << endl;

    /* Get cluster to be splitted */
    NiceCluster cluster = clusters[layer];

    /* Introduce some helper structures */
    std::vector<TransportAddress> vec1;
    std::vector<TransportAddress> vec2;
    std::vector<TransportAddress> cl1;
    std::vector<TransportAddress> cl2;
    TaSet cl1set, cl2set;
    TransportAddress cl1_center = TransportAddress::UNSPECIFIED_NODE;
    TransportAddress cl2_center = TransportAddress::UNSPECIFIED_NODE;
    simtime_t min_delay = 999;

    for (int i=0; i<cluster.getSize(); i++) {

        /* Delete all arrows in visualization */
        deleteOverlayNeighborArrow(cluster.get(i));

        /* Put all members to first vector */
        vec1.push_back(cluster.get(i));
        //EV << "vec1.push_back(cluster.get(i)): " << cluster.get(i).getIp() << endl;

        /* Put first half of members to second vector */
        if (i < cluster.getSize()/2) {
            vec2.push_back(cluster.get(i));
            //EV << "vec2.push_back(cluster.get(i)): " << cluster.get(i).getIp() << endl;
        }

    }

    int combinations = 0;

    TaSet::iterator sit;

    if (cluster.getSize() < 18) {

        /* Go through all combinations of clusters */
        do {

            combinations++;

            //EV << "combinations: " << combinations << endl;

            /* Introduce some helper structures */
            TransportAddress q1_center;
            TransportAddress q2_center;
            std::vector<TransportAddress> vec3;

            /* Determine elements that are in first set but not in second */
            std::set_difference(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), inserter(vec3, vec3.begin()));

            simtime_t min_q1_delay = 999;
            simtime_t min_q2_delay = 999;
            simtime_t max_delay = 0;

            q1_center = findCenter(vec2).first;

            //EV << "q1_center: " << q1_center.getIp() << endl;

            std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(q1_center);

            if (it != peerInfos.end()) {

                min_q1_delay = it->second->get_distance();

            }
            else {

                min_q1_delay = 0;

            }

            q2_center = findCenter(vec3).first;

            //EV << "q2_center: " << q2_center.getIp() << endl;

            it = peerInfos.find(q2_center);

            if (it != peerInfos.end()) {

                min_q2_delay = it->second->get_distance();

            }
            else {

                min_q2_delay = 0;

            }

            max_delay = std::max(min_q1_delay, min_q2_delay);

            if (min_delay == 0) min_delay = max_delay;

            if ((max_delay < min_delay) && !q1_center.isUnspecified() && !q2_center.isUnspecified()) {

                min_delay = max_delay;
                cl1 = vec2;
                cl2 = vec3;
                cl1_center = q1_center;
                cl2_center = q2_center;
            }

        } while (next_combination(vec1.begin(), vec1.end(), vec2.begin(), vec2.end()));

        //build sets
        cl1set.insert(cl1.begin(), cl1.end());
        cl2set.insert(cl2.begin(), cl2.end());

    }
    else {
        EV << thisNode.getIp() << " RANDOM SPLIT" << endl;
        cl1set.clear();
        cl2set.clear();
        for (int i=0; i<cluster.getSize(); i++) {
            if (i < cluster.getSize()/2) {
                cl1set.insert(cluster.get(i));
            }
            else {
                cl2set.insert(cluster.get(i));
            }
        }
        cl1_center = findCenter(cl1set,true).first;
        cl2_center = findCenter(cl2set,true).first;
    }

    if (isRendevouzPoint) {
        // Make certain that we remain leader
        if (cl1set.count(thisNode) > 0) {
            cl1_center = thisNode;
        }
        else {
            cl2_center = thisNode;
        }
    }

    // Cluster split accomplished, now handling consequences

    // CASE 1: We lost all cluster leaderships
    // repair all cluster layer, top down
    if ((cl1_center != thisNode) && (cl2_center != thisNode)) {

        clusters[layer+1].add(cl1_center);
        clusters[layer+1].add(cl2_center);
        TaSet superCluster = TaSet(clusters[layer + 1].begin(), clusters[layer + 1].end());
        TransportAddress scLeader;

        if (layer < getHighestLayer()) {
            gracefulLeave(layer+1);
            scLeader = clusters[layer + 1].getLeader();
        }
        else {
            scLeader = cl1_center;
            if (isRendevouzPoint) {
                opp_error("Something went wrong in Nice::ClusterSplit and the RendevouzPoint is trying to give up leadership. This is a bug in OverSim's implementation of Nice. Please fix it, or file a bug.");
            }
        }

        // Leaving the upper layer before sending LTs leads to wrong information in the packets.
        LeaderTransfer(layer, cl1_center, cl1set, scLeader, superCluster);
        LeaderTransfer(layer, cl2_center, cl2set, scLeader, superCluster);

        if (layer < maxLayers - 1) {
            for (TaSet::iterator itn = clusters[layer + 1].begin(); itn != clusters[layer + 1].end(); ++itn) {
                deleteOverlayNeighborArrow(*itn);
            }
            clusters[layer + 1].clear();
        }

        getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 0, "block/circle_vs");

    }

    // CASE 2: We stay leader in one of the new clusters
    if ((cl1_center == thisNode) || (cl2_center == thisNode)) {

        if (clusters[layer + 1].getSize() == 0) {

            clusters[layer + 1].add(cl1_center);
            clusters[layer + 1].add(cl2_center);

            clusters[layer + 1].setLeader(thisNode);
            clusters[layer + 1].confirmLeader();

        }

        clusters[layer + 1].add(cl2_center);
        clusters[layer + 1].add(cl1_center);
        TaSet superCluster = TaSet(clusters[layer + 1].begin(), clusters[layer + 1].end());
        if (cl1_center == thisNode) {

            LeaderTransfer(layer, cl2_center, cl2set, clusters[layer + 1].getLeader(), superCluster);

        }
        else {

            LeaderTransfer(layer, cl1_center, cl1set, clusters[layer + 1].getLeader(), superCluster);

        }


    }

    // Set local cluster info
    clusters[layer].clear();

    // Depends on in which of the two clusters this node is
    if (cl1set.count(thisNode)) {

        TaSet::iterator cit = cl1set.begin();
        while (cit != cl1set.end()) {
            clusters[layer].add(*cit);
            cit++;
        }

        clusters[layer].setLeader(cl1_center);

    }
    else {

        TaSet::iterator cit = cl2set.begin();
        while (cit != cl2set.end()) {
            clusters[layer].add(*cit);
            cit++;
        }

        clusters[layer].setLeader(cl2_center);

    }
    clusters[layer].confirmLeader();

    //update arrows
    updateVisualization();

    if (pimp)
        sendHeartbeats();

template<class ConstIter >
std::pair< TransportAddress, simtime_t > oversim::Nice::findCenter ( ConstIter  begin,
ConstIter  end,
bool  allowRandom = false 
) [private]

Definition at line 2996 of file Nice.cc.

{

    TransportAddress center = TransportAddress::UNSPECIFIED_NODE;
    simtime_t min_delay = 1000;

    for (ConstIter it = begin; it != end; ++it) {

        simtime_t delay = getMaxDistance(*it, begin, end);

        if ((delay > 0) && (delay < min_delay)) {

            min_delay = delay;
            center = *it;

        }

    }

    if (center.isUnspecified()) {
        center = *begin;
    }

    //EV << "center: " << center << endl;
    return std::make_pair(center, min_delay);

std::pair< TransportAddress, simtime_t > oversim::Nice::findCenter ( TaSet  cluster,
bool  allowRandom = false 
) [private]

Definition at line 2969 of file Nice.cc.

Referenced by ClusterSplit(), findCenter(), gracefulLeave(), and maintenance().

{

std::pair< TransportAddress, simtime_t > oversim::Nice::findCenter ( std::vector< TransportAddress cluster,
bool  allowRandom = false 
) [private]

Definition at line 2978 of file Nice.cc.

{

std::pair< TransportAddress, simtime_t > oversim::Nice::findCenter ( const NiceCluster cluster,
bool  allowRandom = false 
) [private]

Definition at line 2987 of file Nice.cc.

{

void oversim::Nice::finishOverlay (  )  [virtual]

collects statistical data in derived class

Reimplemented from BaseOverlay.

Definition at line 519 of file Nice.cc.

{

    if (isRendevouzPoint) {
        RendevouzPoint = TransportAddress::UNSPECIFIED_NODE;
    }

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

    globalStatistics->addStdDev("Nice: Inconsistencies/s", (double)numInconsistencies / time);
    globalStatistics->addStdDev("Nice: Query Timeouts/s", (double)numQueryTimeouts / time);
    globalStatistics->addStdDev("Nice: Peer Timeouts/s", (double)numPeerTimeouts / time);
    globalStatistics->addStdDev("Nice: Temporary Peer Timeouts/s", (double)numTempPeerTimeouts / time);
    globalStatistics->addStdDev("Nice: Structure Partitions/s", (double)numStructurePartitions / time);
    globalStatistics->addStdDev("Nice: Own Messages Received/s", (double)numOwnMessagesReceived / time);
    globalStatistics->addStdDev("Nice: SC Minimum Compare/s", (double)totalSCMinCompare / time);
    globalStatistics->addStdDev("Nice: Received JOIN Messages/s", (double)numJoins / time);
    globalStatistics->addStdDev("Nice: Forwarded Multicast Messages/s", (double)numForward / time);
    globalStatistics->addStdDev("Nice: Forwarded Multicast Bytes/s", (double)totalForwardBytes / time);
    globalStatistics->addStdDev("Nice: Received Multicast Messages/s (subscribed groups only)", (double)numReceived / time);
    globalStatistics->addStdDev("Nice: Received Multicast Bytes/s (subscribed groups only)", (double)totalReceivedBytes / time);
    globalStatistics->addStdDev("Nice: Send Heartbeat Messages/s", (double)numHeartbeat / time);
    globalStatistics->addStdDev("Nice: Send Heartbeat Bytes/s", (double)totalHeartbeatBytes / time);
    if( debug_join ) recordScalar("Nice: Total joins", (double)numJoins);

int oversim::Nice::getHighestLayer (  )  [private]

Definition at line 1640 of file Nice.cc.

Referenced by changeState(), ClusterMerge(), ClusterSplit(), getHighestLeaderLayer(), gracefulLeave(), maintenance(), Remove(), sendDataToOverlay(), sendHeartbeats(), and updateVisualization().

{
    if (clusters[0].getSize() == 0) {
        // Not yet joined to overlay
        return -1;
    }

    int highest = 0;

    while (highest < maxLayers &&
           !clusters[highest].getLeader().isUnspecified() &&
           clusters[highest].getLeader() == thisNode) {
        ++highest;
    }

    if (highest == maxLayers) {
        // we are top leader
        return maxLayers - 1;
    }
    else if (!clusters[highest].contains(thisNode)) {
        // we are top leader. highest is one plus our layer.
        return highest - 1;
    }
    else {
        return highest;

int oversim::Nice::getHighestLeaderLayer (  )  [private]

Definition at line 1626 of file Nice.cc.

Referenced by gracefulLeave(), handleNiceQuery(), and maintenance().

{
    int layer = getHighestLayer();
    if (!clusters[layer].getLeader().isUnspecified() && clusters[layer].getLeader() == thisNode) {
        return layer;
    }
    else if (layer == -1) {
        return -1;
    }
    else {
        return layer - 1;

simtime_t oversim::Nice::getMaxDistance ( TransportAddress  member,
const std::set< TransportAddress > &  neighbors 
) [private]

Definition at line 3073 of file Nice.cc.

Referenced by findCenter(), and maintenance().

{

template<class ConstIter >
simtime_t oversim::Nice::getMaxDistance ( TransportAddress  member,
ConstIter  neighborsBegin,
ConstIter  neighborsEnd 
) [private]

Definition at line 3029 of file Nice.cc.

{
    simtime_t maxDelay = 0;
    simtime_t delay = 0;

    if (member == thisNode) {

        for (ConstIter it = neighborsBegin; it != neighborsEnd; ++it) {

            std::map<TransportAddress, NicePeerInfo*>::iterator itInfo = peerInfos.find(*it);

            if (itInfo != peerInfos.end()) {

                delay = itInfo->second->get_distance();
                maxDelay = std::max(delay, maxDelay);

            }

        }

    }
    else {

        std::map<TransportAddress, NicePeerInfo*>::iterator itInfo = peerInfos.find(member);

        if (itInfo != peerInfos.end()) {

            for (ConstIter it = neighborsBegin; it != neighborsEnd; ++it) {

                //EV << "getDistanceTo " << *it2 << endl;
                delay = itInfo->second->getDistanceTo(*it);
                //EV << thisNode.getIp() << " : Distance to " << it2->getIp() << " : " << delay << endl;
                maxDelay = std::max(delay, maxDelay);

            }

        }

    }

    return maxDelay;

simtime_t oversim::Nice::getMeanDistance ( std::set< TransportAddress neighbors  )  [private]

Definition at line 3081 of file Nice.cc.

Referenced by maintenance().

{
    simtime_t meanDelay = 0;
    simtime_t delay = 0;
    unsigned int number = 0;

    std::set<TransportAddress>::iterator it = neighbors.begin();

    while (it != neighbors.end()) {

        if (*it != thisNode) {

            std::map<TransportAddress, NicePeerInfo*>::iterator it2 = peerInfos.find(*it);

            if (it2 != peerInfos.end()) {

                delay = it2->second->get_distance();
                //EV << "delay to " << *it << " : " << delay << endl;

                if  (delay > 0.0) {

                    meanDelay += delay;
                    number++;

                }

            }

        }

        it++;

    }

    if (number > 0) {

        return meanDelay/number;

    }
    else {

        return 0;

    }

void oversim::Nice::gracefulLeave ( short  bottomLayer  )  [private]

Definition at line 3232 of file Nice.cc.

Referenced by ClusterMerge(), ClusterSplit(), and maintenance().

{
    EV << simTime() << " : " << thisNode.getIp() << " : gracefulLeave()" << endl;

    int layer = getHighestLayer();

    ASSERT(layer >= bottomLayer);

    if (isRendevouzPoint) {
        opp_error("The RendevouzPoint is trying to leave a layer and the simulation cannot continue. This is a bug in the Nice implementation in OverSim, please check the backtrace and fix it or submit a bug report.");
    }

    if (!clusters[layer].getLeader().isUnspecified() && clusters[layer].getLeader() != thisNode) {
        // simply leave cluster
        EV << "removing " << thisNode.getIp() << " from " << layer << endl;
        if (!clusters[layer].getLeader().isUnspecified()) {
            Remove(layer);
        }
        clusters[layer].remove(thisNode);
    }

    for (layer = getHighestLeaderLayer(); layer >= bottomLayer; layer--) {

        EV << "REPAIR: " << layer << endl;

        for (TaSet::const_iterator itNode = clusters[layer].begin(); itNode != clusters[layer].end(); ++itNode) {

            EV << "rest: " << itNode->getIp() << endl;

            deleteOverlayNeighborArrow(*itNode);

        }

        EV << "remove from: " << layer << endl;
        Remove(layer);

        if (clusters[layer].getSize() > 0) {
            TransportAddress new_sc_center = findCenter(clusters[layer]).first;

            EV << "NEW LEADER (GL): " << layer << " --> " << new_sc_center.getIp() << endl;

            if (new_sc_center.isUnspecified()) {

                new_sc_center = clusters[layer].get(0);

                EV << "UNSPECIFIED! instead choose: " << new_sc_center.getIp() << endl;

            }

            clusters[layer].setLeader(new_sc_center);

            LeaderTransfer(layer, new_sc_center);

        }

    }

    EV << simTime() << " : " << thisNode.getIp() << " : gracefulLeave() finished." << endl;

void oversim::Nice::handleAppMessage ( cMessage *  msg  )  [virtual]

Processes "timer" self-messages.

Parameters:
msg A self-message Processes non-commonAPI messages
msg non-commonAPIMessage

Reimplemented from BaseOverlay.

Definition at line 3298 of file Nice.cc.

{
    if ( ALMAnycastMessage* anycastMsg = dynamic_cast<ALMAnycastMessage*>(msg) ) {
        EV << "[Nice::handleAppMessage() @ " << overlay->getThisNode().getIp()
           << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
           << "    Anycast message for group " << anycastMsg->getGroupId() << "\n"
           << "    ignored: Not implemented yet!"
           << endl;
    }
    else if ( ALMCreateMessage* createMsg = dynamic_cast<ALMCreateMessage*>(msg) ) {
        EV << "[Nice::handleAppMessage() @ " << overlay->getThisNode().getIp()
           << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
           << "    Create message for group " << createMsg->getGroupId() << "\n"
           << "    ignored: Not implemented yet!"
           << endl;
    }
    else if ( ALMDeleteMessage* deleteMsg = dynamic_cast<ALMDeleteMessage*>(msg) ) {
        EV << "[Nice::handleAppMessage() @ " << overlay->getThisNode().getIp()
           << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
           << "    Delete message for group " << deleteMsg->getGroupId() << "\n"
           << "    ignored: Not implemented yet!"
           << endl;
    }
    else if ( ALMLeaveMessage* leaveMsg = dynamic_cast<ALMLeaveMessage*>(msg) ) {
        EV << "[Nice::handleAppMessage() @ " << overlay->getThisNode().getIp()
           << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
           << "    Leave message for group " << leaveMsg->getGroupId() << "\n"
           << "    ignored: Not implemented yet!"
           << endl;
    }
    else if ( ALMMulticastMessage* multicastMsg = dynamic_cast<ALMMulticastMessage*>(msg) ) {
        NiceMulticastMessage *niceMsg = new NiceMulticastMessage("NICE_MULTICAST");
        niceMsg->setCommand(NICE_MULTICAST);
        niceMsg->setLayer(-1);
        niceMsg->setSrcNode(thisNode);
        niceMsg->setLastHop(thisNode);
        niceMsg->setHopCount(0);

        niceMsg->setBitLength(NICEMULTICAST_L(niceMsg));

        niceMsg->encapsulate(multicastMsg);
        sendDataToOverlay(niceMsg);

        // otherwise msg gets deleted later
        msg = NULL;
    }
    else if ( ALMSubscribeMessage* subscribeMsg = dynamic_cast<ALMSubscribeMessage*>(msg) ) {
        EV << "[Nice::handleAppMessage() @ " << overlay->getThisNode().getIp()
           << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
           << "    Subscribe message for group " << subscribeMsg->getGroupId() << "\n"
           << "    ignored: Not implemented yet!"
           << endl;
    }

    // Delete msg if not already deleted
    if ( msg ) {
        delete msg;
    }

void oversim::Nice::handleNiceClusterMergeRequest ( NiceClusterMerge mergeMsg  )  [private]

Definition at line 753 of file Nice.cc.

Referenced by handleUDPMessage().

{
    EV << simTime() << " : " << thisNode.getIp() << " : NICE_CLUSTER_MERGE_REQUEST" << endl;

    short layer = mergeMsg->getLayer();

    // Only react if I am a leader of this cluster layer

    if (clusters[layer].getLeader().isUnspecified()) {

        EV << simTime() << " : " << thisNode.getIp() << " : NO LEADER! BREAK. NICE_CLUSTER_MERGE_REQUEST finished" << endl;

        delete mergeMsg;

        return;

    }

    if (clusters[layer].getLeader() == thisNode) {

        clusters[layer+1].remove(mergeMsg->getSrcNode());
        deleteOverlayNeighborArrow(mergeMsg->getSrcNode());

        TransportAddress oldLeader = clusters[layer+1].getLeader();
        if (oldLeader.isUnspecified() || oldLeader != thisNode) {
            clusters[layer+1].add(mergeMsg->getNewClusterLeader());
            clusters[layer+1].setLeader(mergeMsg->getNewClusterLeader());
        }

        for (unsigned int i=0; i<mergeMsg->getMembersArraySize(); i++) {

            /* Add new node to cluster */
            clusters[layer].add(mergeMsg->getMembers(i));

            /* Create peer context to joining node */
            /* Check if peer info already exists */
            std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(mergeMsg->getMembers(i));

            if (it != peerInfos.end()) { /* We already know this node */

            }
            else { /* Create PeerInfo object */

                NicePeerInfo* pi = new NicePeerInfo(this);

                pi->set_last_HB_arrival(simTime().dbl());

                peerInfos.insert(std::make_pair(mergeMsg->getMembers(i), pi));

            }

            /* Draw arrow to new member */
            showOverlayNeighborArrow(mergeMsg->getMembers(i), false, clusterarrows[layer]);

            EV << "getHighestLeaderLayer()].getSize(): " << clusters[getHighestLeaderLayer()].getSize() << endl;

#if 0
            if (clusters[getHighestLeaderLayer()].getSize() < 2) {

                // cancel layer
                for (TaSet::iterator itn = clusters[i].begin(); itn != clusters[i].end(); ++itn) {
                    deleteOverlayNeighborArrow(*itn);
                }
                clusters[getHighestLeaderLayer()].clear();

                for (short i=0; i<maxLayers; i++) {

                    if (clusters[i].getSize() > 0) {

                        if (clusters[i].contains(thisNode)) {

                            getParentModule()->getParentModule()->getDisplayString().setTagArg
                                ("i2", 1, clustercolors[i]);

                        }

                    }

                }

            }
#endif

        }

    }
    else { // Forward to new cluster leader

        if (pimp) {

            NiceMemberMessage* dup = static_cast<NiceMemberMessage*>(mergeMsg->dup());
            sendMessageToUDP(clusters[layer].getLeader(), dup);
            delete mergeMsg;
            return;

        }

    }

    if (pimp)
        sendHeartbeats();

    delete mergeMsg;

void oversim::Nice::handleNiceForceMerge ( NiceMessage msg  )  [private]

Definition at line 860 of file Nice.cc.

Referenced by handleUDPMessage().

void oversim::Nice::handleNiceHeartbeat ( NiceHeartbeat msg  )  [private]

Definition at line 867 of file Nice.cc.

Referenced by handleUDPMessage().

{
    if (debug_heartbeats)
        EV << simTime() << " : " << thisNode.getIp() << " : NICE_HEARTBEAT from  " << hbMsg->getSrcNode() << endl;

    /* Update sequence number information and evaluate distance */
    std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(hbMsg->getSrcNode());

    if (it != peerInfos.end()) {

        /* We already know this node */
        // Collect subcluster infos
        it->second->setSubClusterMembers(hbMsg->getSublayermembers());

        it->second->set_last_HB_arrival(simTime().dbl());

        if (it->second->get_backHB(hbMsg->getSeqRspNo()) > 0) {

            /* Valid distance measurement, get value */
            double oldDistance = it->second->get_distance();

            /* Use Exponential Moving Average with factor 0.1 */
            double newDistance = (simTime().dbl() - it->second->get_backHB(hbMsg->getSeqRspNo()) - hbMsg->getHb_delay())/2.0;

            if (oldDistance > 0) {

                it->second->set_distance((0.1 * newDistance) + (0.9 * oldDistance));

            }
            else {

                it->second->set_distance(newDistance);

            }

        }

        it->second->set_last_recv_HB(hbMsg->getSeqNo());

    }

    it = peerInfos.find(hbMsg->getSrcNode());

    if (it != peerInfos.end()) {

        for (unsigned int i=0; i<hbMsg->getMembersArraySize(); i++) {

            it->second->updateDistance(hbMsg->getMembers(i), hbMsg->getDistances(i));

        }

    }

    delete hbMsg;

    if (debug_heartbeats)

void oversim::Nice::handleNiceJoinCluster ( NiceMessage joinMsg  )  [private]

Definition at line 1280 of file Nice.cc.

Referenced by handleUDPMessage().

{
    if (debug_join)
        EV << simTime() << " : " << thisNode.getIp() << " : handleNiceJoinCluster()" << endl;

    short layer = joinMsg->getLayer();

    if (debug_join)
        std::cout << " From : " << joinMsg->getSrcNode() << ", Layer:  " << layer << endl;

    if (!clusters[layer].getLeader().isUnspecified()) {

        if (clusters[layer].getLeader() != thisNode) {

            if (pimp) {

                NiceMessage* dup = static_cast<NiceMessage*>(joinMsg->dup());
                sendMessageToUDP(clusters[layer].getLeader(), dup);

            }

        }
        else {

            RECORD_STATS(++numJoins);

            /* Add new node to cluster */
            clusters[layer].add(joinMsg->getSrcNode());

            /* Create peer context to joining node */
            /* Check if peer info already exists */
            std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(joinMsg->getSrcNode());

            if (it != peerInfos.end()) { /* We already know this node */


            }
            else { /* Create PeerInfo object */

                NicePeerInfo* pi = new NicePeerInfo(this);

                peerInfos.insert(std::make_pair(joinMsg->getSrcNode(), pi));

            }

            /* Draw arrow to new member */
            showOverlayNeighborArrow(joinMsg->getSrcNode(), false, clusterarrows[layer]);

            if (pimp)
                sendHeartbeatTo(joinMsg->getSrcNode(), layer);
        }

    }
    else {

        if (debug_join)
            EV << "Leader unspecified. Ignoring request." << endl;

    }

    if (debug_join)
        EV << simTime() << " : " << thisNode.getIp() << " : handleNiceJoinCluster() finished." << endl;

void oversim::Nice::handleNiceJoineval ( NiceMessage msg  )  [private]

Definition at line 1346 of file Nice.cc.

Referenced by handleUDPMessage().

{
    NiceMessage* responseMsg = new NiceMessage("NICE_JOINEVAL_RESPONSE");
    responseMsg->setSrcNode(thisNode);
    responseMsg->setCommand(NICE_JOINEVAL_RESPONSE);
    responseMsg->setLayer(msg->getLayer());

    responseMsg->setBitLength(NICEMESSAGE_L(responseMsg));

    sendMessageToUDP(msg->getSrcNode(), responseMsg);

void oversim::Nice::handleNiceJoinevalResponse ( NiceMessage msg  )  [private]

Definition at line 1360 of file Nice.cc.

Referenced by handleUDPMessage().

{
    if (evalLayer > 0 && evalLayer == msg->getLayer()) {

        query_compare = simTime() - query_compare;

        if (query_compare < query_start) {

            Query(msg->getSrcNode(), msg->getLayer()-1);

        }
        else {

            Query(tempResolver, msg->getLayer() - 1);

        }

        evalLayer = -1;
    }

void oversim::Nice::handleNiceLeaderHeartbeat ( NiceLeaderHeartbeat lhbMsg  )  [private]

Definition at line 926 of file Nice.cc.

Referenced by handleUDPMessage().

{
    if (debug_heartbeats)
        EV << simTime() << " : " << thisNode.getIp() << " : NICE_LEADERHEARTBEAT from  " << lhbMsg->getSrcNode() << endl;

    ASSERT(lhbMsg->getSrcNode() != thisNode);

    /* Update sequence number information and evaluate distance */
    std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(lhbMsg->getSrcNode());

    if (it != peerInfos.end()) { /* We already know this node */

        it->second->set_last_HB_arrival(simTime().dbl());

        if (it->second->get_backHB(lhbMsg->getSeqRspNo()) > 0) {

            /* Valid distance measurement, get value */
            it->second->set_distance((simTime().dbl() - it->second->get_backHB(lhbMsg->getSeqRspNo()) - lhbMsg->getHb_delay())/2);

        }

        it->second->set_last_recv_HB(lhbMsg->getSeqNo());

    }

    it = peerInfos.find(lhbMsg->getSrcNode());

    if (it != peerInfos.end()) {

        for (unsigned int i=0; i<lhbMsg->getMembersArraySize(); i++) {

            it->second->updateDistance(lhbMsg->getMembers(i), lhbMsg->getDistances(i));

        }

    }

    // Maintain cluster memberships

    if (lhbMsg->getLayer() > getHighestLayer()) {

        /* Node is not part of this cluster, remove it */
        sendRemoveTo(lhbMsg->getSrcNode(), lhbMsg->getLayer());

        if (debug_heartbeats)
            EV << "Node is not part of this cluster (" << lhbMsg->getLayer() << "), removing it..." << endl;

        delete lhbMsg;
        return;

    }

    if (!clusters[lhbMsg->getLayer()].getLeader().isUnspecified() && 
            clusters[lhbMsg->getLayer()].getLeader() == thisNode) {

        if (debug_heartbeats)
            EV << "Leader collision...";

        if (lhbMsg->getSrcNode() < thisNode) {

            if (debug_heartbeats)
                EV << "...making other leader." << endl;

            if (lhbMsg->getLayer() + 1 <= getHighestLayer()) {
                gracefulLeave(lhbMsg->getLayer() + 1);
            }

            /* Fix visualisation - remove arrows */
            int hbLayer = lhbMsg->getLayer();
            for (TaSet::iterator itn = clusters[hbLayer].begin(); itn != clusters[hbLayer].end(); ++itn) {
                deleteOverlayNeighborArrow(*itn);
            }

            clusters[lhbMsg->getLayer()].add(lhbMsg->getSrcNode());
            clusters[lhbMsg->getLayer()].setLeader(lhbMsg->getSrcNode());
            LeaderTransfer(lhbMsg->getLayer(), lhbMsg->getSrcNode());
        }
        else {
            if (debug_heartbeats)
                EV << "...remaining leader." << endl;
            delete lhbMsg;
            return;
        }
    }
    else if (!clusters[lhbMsg->getLayer()].getLeader().isUnspecified() &&
            clusters[lhbMsg->getLayer()].getLeader() != lhbMsg->getSrcNode()) {
        if (debug_heartbeats)
            EV << "Possible multiple leaders detected... sending remove to " << clusters[lhbMsg->getLayer()].getLeader() << " leader.\n";
        sendRemoveTo(clusters[lhbMsg->getLayer()].getLeader(), lhbMsg->getLayer());
        
    }

    /* Everything is in order. Process HB */
    bool leaderChanged = clusters[lhbMsg->getLayer()].getLeader().isUnspecified() || clusters[lhbMsg->getLayer()].getLeader() != lhbMsg->getSrcNode();

    for (int m=lhbMsg->getLayer(); m<maxLayers; m++) {
        for (TaSet::iterator itn = clusters[m].begin(); itn != clusters[m].end(); ++itn) {
            deleteOverlayNeighborArrow(*itn);
        }
        clusters[m].clear();
    }

    for (unsigned int i=0; i<lhbMsg->getMembersArraySize(); i++) {

        //Check if member is already part of cluster

        /* Check if peer info already exists */
        std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(lhbMsg->getMembers(i));

        if (it != peerInfos.end()) { /* We already know this node */

        }
        else { /* Create PeerInfo object */

            NicePeerInfo* pi = new NicePeerInfo(this);

            pi->set_last_HB_arrival(simTime().dbl());

            peerInfos.insert(std::make_pair(lhbMsg->getMembers(i), pi));

        }

        clusters[lhbMsg->getLayer()].add(lhbMsg->getMembers(i));

    }

    clusters[lhbMsg->getLayer()].setLeader(lhbMsg->getSrcNode());
    if (!leaderChanged)
        clusters[lhbMsg->getLayer()].confirmLeader();

    if (lhbMsg->getSupercluster_membersArraySize() > 0) {

        for (TaSet::iterator itn = clusters[lhbMsg->getLayer() + 1].begin(); itn != clusters[lhbMsg->getLayer() + 1].end(); ++itn) {
            deleteOverlayNeighborArrow(*itn);
        }
        clusters[lhbMsg->getLayer()+1].clear();

        for (unsigned int i=0; i<lhbMsg->getSupercluster_membersArraySize(); i++) {

            /* Check if peer info already exists */
            std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(lhbMsg->getSupercluster_members(i));

            if (it != peerInfos.end()) { /* We already know this node */

            }
            else { /* Create PeerInfo object */

                NicePeerInfo* pi = new NicePeerInfo(this);

                pi->set_last_HB_arrival(simTime().dbl());

                peerInfos.insert(std::make_pair(lhbMsg->getSupercluster_members(i), pi));

            }

            clusters[lhbMsg->getLayer()+1].add(lhbMsg->getSupercluster_members(i));

        }

        clusters[lhbMsg->getLayer()+1].setLeader(lhbMsg->getSupercluster_leader());

        it = peerInfos.find(lhbMsg->getSrcNode());

        if (it != peerInfos.end()) {

            for (unsigned int k=0; k<lhbMsg->getMembersArraySize(); k++) {

                it->second->updateDistance(lhbMsg->getMembers(k), lhbMsg->getDistances(k));

            }

        }
        else {

            NicePeerInfo* pi = new NicePeerInfo(this);

            pi->set_last_HB_arrival(simTime().dbl());

            peerInfos.insert(std::make_pair(lhbMsg->getSrcNode(), pi));

        }
    }

    if (debug_heartbeats)
        EV << simTime() << " : " << thisNode.getIp() << " : handleNiceLeaderHeartbeat() finished.  " << endl;

void oversim::Nice::handleNiceLeaderHeartbeatOrTransfer ( NiceMessage msg  )  [private]
void oversim::Nice::handleNiceLeaderTransfer ( NiceLeaderHeartbeat transferMsg  )  [private]

Definition at line 1115 of file Nice.cc.

Referenced by handleUDPMessage().

{

    if (debug_heartbeats)
        EV << simTime() << " : " << thisNode.getIp() << " : NICE_LEADERTRANSFER from " << transferMsg->getSrcNode() << " for " << transferMsg->getLayer() << endl;

    if (!clusters[transferMsg->getLayer()].getLeader().isUnspecified()) {

        /* React only if I am not already leader */
        if (clusters[transferMsg->getLayer()].getLeader() != thisNode) {

            if (debug_heartbeats)
                EV << "I am not already leader of this cluster layer." << endl;

            for (TaSet::iterator itn = clusters[transferMsg->getLayer()].begin(); itn != clusters[transferMsg->getLayer()].end(); ++itn) {
                deleteOverlayNeighborArrow(*itn);
            }
            clusters[transferMsg->getLayer()].clear();
            clusters[transferMsg->getLayer()].add(thisNode);
            clusters[transferMsg->getLayer()].setLeader(thisNode);

            for (unsigned int i=0; i<transferMsg->getMembersArraySize(); i++) {

                if (debug_heartbeats)
                    EV << "Adding: " << transferMsg->getMembers(i) << endl;

                clusters[transferMsg->getLayer()].add(transferMsg->getMembers(i));
                showOverlayNeighborArrow(transferMsg->getMembers(i), false, clusterarrows[transferMsg->getLayer()]);

                std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(transferMsg->getMembers(i));

                if (it != peerInfos.end()) {

                    /* We already know this node */
                    it->second->touch();

                }
                else {

                    //We don't know him yet
                    NicePeerInfo* pi = new NicePeerInfo(this);

                    pi->set_last_HB_arrival(simTime().dbl());

                    peerInfos.insert(std::make_pair(transferMsg->getMembers(i), pi));

                }

            }

            if (transferMsg->getSupercluster_membersArraySize() > 0) {

                for (TaSet::iterator itn = clusters[transferMsg->getLayer() + 1].begin(); itn != clusters[transferMsg->getLayer() + 1].end(); ++itn) {
                    deleteOverlayNeighborArrow(*itn);
                }
                clusters[transferMsg->getLayer()+1].clear();

                for (unsigned int i=0; i<transferMsg->getSupercluster_membersArraySize(); i++) {

                    clusters[transferMsg->getLayer()+1].add(transferMsg->getSupercluster_members(i));

                    std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(transferMsg->getSupercluster_members(i));

                    if (it != peerInfos.end()) {

                        /* We already know this node */
                        it->second->touch();

                    }
                    else {

                        //We don't know him yet
                        NicePeerInfo* pi = new NicePeerInfo(this);

                        pi->set_last_HB_arrival(simTime().dbl());

                        peerInfos.insert(std::make_pair(transferMsg->getSupercluster_members(i), pi));

                    }

                }

                // experimental
                clusters[transferMsg->getLayer()+1].add(thisNode);

                if (!transferMsg->getSupercluster_leader().isUnspecified()) {

                    clusters[transferMsg->getLayer()+1].setLeader(transferMsg->getSupercluster_leader());

                    if ((clusters[transferMsg->getLayer()+1].getLeader() == thisNode) &&
                            (clusters[transferMsg->getLayer()+2].getSize() == 0)) {

                        for (unsigned int i=0; i<transferMsg->getSupercluster_membersArraySize(); i++) {

                            showOverlayNeighborArrow(transferMsg->getSupercluster_members(i), false, clusterarrows[transferMsg->getLayer()+1]);

                        }

                    }
                    else {

                        JoinCluster(transferMsg->getSupercluster_leader(), transferMsg->getLayer()+1);

                    }

                }

            }
            else {

                if (!isRendevouzPoint && RendevouzPoint != transferMsg->getSrcNode()) {
                    BasicJoinLayer(transferMsg->getLayer() + 1);
                }

            }

            for (int i=0; i<maxLayers; i++) {

                if (clusters[i].contains(thisNode))
                    getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 1, clustercolors[i]);

            }

            clusters[transferMsg->getLayer()].setLastLT();


        }
        else {

            for (unsigned int i=0; i<transferMsg->getMembersArraySize(); i++) {

                if (debug_heartbeats)
                    EV << "Adding: " << transferMsg->getMembers(i) << endl;

                clusters[transferMsg->getLayer()].add(transferMsg->getMembers(i));
                showOverlayNeighborArrow(transferMsg->getMembers(i), false, clusterarrows[transferMsg->getLayer()]);

                std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(transferMsg->getMembers(i));

                if (it == peerInfos.end()) {

                    //We don't know him yet
                    NicePeerInfo* pi = new NicePeerInfo(this);

                    pi->set_last_HB_arrival(simTime().dbl());

                    peerInfos.insert(std::make_pair(transferMsg->getMembers(i), pi));

                }

            }

        }

    }

    if (pimp)
        sendHeartbeats();

    if (debug_heartbeats)
        EV << simTime() << " : " << thisNode.getIp() << " : handleNiceLeaderTransfer() finished.  " << endl;

void oversim::Nice::handleNiceMulticast ( NiceMulticastMessage multicastMsg  )  [private]

Definition at line 1383 of file Nice.cc.

Referenced by handleUDPMessage().

{
    RECORD_STATS(++numReceived; totalReceivedBytes += multicastMsg->getByteLength());

    /* If it is mine, count */
    if (multicastMsg->getSrcNode() == thisNode) {

        RECORD_STATS(++numOwnMessagesReceived);

    }
    else {

        unsigned int hopCount = multicastMsg->getHopCount();
        hopCount++;

        if (hopCount < 8) {

            RECORD_STATS(++numForward; totalForwardBytes += multicastMsg->getByteLength());

            NiceMulticastMessage* forOverlay = static_cast<NiceMulticastMessage*>(multicastMsg->dup());
            forOverlay->setHopCount(hopCount);
            sendDataToOverlay(forOverlay);

            send(multicastMsg->decapsulate(), "appOut");

        }
    }

void oversim::Nice::handleNicePeerTemporary ( NiceMessage msg  )  [private]

Definition at line 1414 of file Nice.cc.

Referenced by handleUDPMessage().

{
    // Add node to tempPeers
    tempPeers.insert(std::make_pair(msg->getSrcNode(), simTime()));

void oversim::Nice::handleNicePeerTemporaryRelease ( NiceMessage msg  )  [private]

Definition at line 1422 of file Nice.cc.

Referenced by handleUDPMessage().

{
    // Remove node from tempPeers
    tempPeers.erase(msg->getSrcNode());
    deleteOverlayNeighborArrow(msg->getSrcNode());

void oversim::Nice::handleNicePingProbe ( NiceMessage msg  )  [private]

Definition at line 1431 of file Nice.cc.

Referenced by handleUDPMessage().

{
    // Only answer if I am part of requested layer
    if (clusters[msg->getLayer()].contains(thisNode)) {

        NiceMessage* probe = new NiceMessage("NICE_PING_PROBE");
        probe->setSrcNode(thisNode);
        probe->setCommand(NICE_PING_PROBE_RESPONSE);
        probe->setLayer(msg->getLayer());

        probe->setBitLength(NICEMESSAGE_L(probe));

        sendMessageToUDP(msg->getSrcNode(), probe);

    }
    else {

        //Do nothing

    }

void oversim::Nice::handleNicePingProbeResponse ( NiceMessage msg  )  [private]

Definition at line 1455 of file Nice.cc.

Referenced by handleUDPMessage().

{
    //Only react if still in same cluster as when asked
    if (msg->getLayer() == getHighestLayer()+1) {

        std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(msg->getSrcNode());

        if (it != peerInfos.end()) {

            double distance = simTime().dbl() - it->second->getDES();

            it->second->set_distance(distance);
            it->second->touch();

        }

    }

void oversim::Nice::handleNicePollRp ( NiceMessage msg  )  [private]

Definition at line 1476 of file Nice.cc.

Referenced by handleUDPMessage().

{
    if (isRendevouzPoint) {

        NiceMessage* response = new NiceMessage("NICE_POLL_RP_RESPONSE");
        response->setSrcNode(thisNode);
        response->setCommand(NICE_POLL_RP_RESPONSE);
        response->setLayer(getHighestLeaderLayer());
        response->setBitLength(NICEMESSAGE_L(response));

        sendMessageToUDP(msg->getSrcNode(), response);

    }

void oversim::Nice::handleNicePollRpResponse ( NiceMessage msg  )  [private]
void oversim::Nice::handleNiceQuery ( NiceMessage queryMsg  )  [private]

Definition at line 621 of file Nice.cc.

Referenced by handleUDPMessage().

{

    if (debug_queries)
        EV << simTime() << " : " << thisNode.getIp() << " : handleNiceQuery()" << endl;

    short layer = queryMsg->getLayer();
    if (layer >= maxLayers) {
        if (debug_queries)
            EV << "Layer " << layer << " >=  max layer " << maxLayers << " ! Returning." << endl;
        delete queryMsg;
        return;
    }

    if (debug_queries)
        EV << " layer before: " << layer << endl;

    if (layer > getHighestLeaderLayer()) {
        if (isRendevouzPoint) {
            if (debug_queries)
                EV << " getHighestLeaderLayer(): " << getHighestLeaderLayer() << " ! RP self-promoting." << endl;

            for (int i = getHighestLeaderLayer() + 1; i <= layer; ++i) {
                clusters[i].add(thisNode);
                clusters[i].setLeader(thisNode);
            }
        }
        else {
            if (debug_queries)
                EV << " getHighestLeaderLayer(): " << getHighestLeaderLayer() << " ! Returning." << endl;

            delete queryMsg;
            return;
        }
    }

    if (layer < 0) {

        if (isRendevouzPoint) {

            /* If layer is < 0, response with highest layer I am leader of */
            if (debug_queries)
                EV << " I am RP." << endl;
            layer = getHighestLeaderLayer();

        }
        else {

            if (debug_queries)
                EV << " I am not RP. Return." << endl;

            if (pimp) {

                /* forward to Rendevouz Point */
                NiceMessage* dup = static_cast<NiceMessage*>(queryMsg->dup());
                sendMessageToUDP(RendevouzPoint, dup);

            }

            delete queryMsg;
            return;

        }

    }

    if (debug_queries)
        EV << " layer after: " << layer << endl;

    if (!clusters[layer].getLeader().isUnspecified()) {

        if (clusters[layer].getLeader() != thisNode) {

            if (pimp) {

                NiceMessage* dup = static_cast<NiceMessage*>(queryMsg->dup());
                sendMessageToUDP(clusters[layer].getLeader(), dup);

            }

            if (debug_queries)
                EV << " I am not leader of this cluster. return." << endl;

            delete queryMsg;
            return;

        }

    }
    else {

        delete queryMsg;
        return;

    }

    NiceMemberMessage* response = new NiceMemberMessage("NICE_QUERY_RESPONSE");
    response->setSrcNode(thisNode);
    response->setCommand(NICE_QUERY_RESPONSE);
    response->setLayer(layer);

    /* Fill in current cluster members except me */
    response->setMembersArraySize(clusters[layer].getSize()-1);

    int j=0;

    for (int i = 0; i < clusters[layer].getSize(); i++) {

        if (clusters[layer].get(i) != thisNode) {

            response->setMembers(j, clusters[layer].get(i));
            if (debug_queries)
                EV << " Response: " << i << " : " << clusters[layer].get(i) << endl;
            j++;

        }

    }

    response->setBitLength(NICEMEMBERMESSAGE_L(response));

    sendMessageToUDP(queryMsg->getSrcNode(), response);

    if (debug_queries)
        EV << " Sent response to: " << queryMsg->getSrcNode() << endl;

    if (debug_queries)
        EV << simTime() << " : " << thisNode.getIp() << " : handleNiceQuery() finished." << endl;

void oversim::Nice::handleNiceQueryResponse ( NiceMemberMessage queryRspMsg  )  [private]

Definition at line 1504 of file Nice.cc.

Referenced by handleUDPMessage().

{

    cancelEvent(queryTimer);

    short layer = queryRspMsg->getLayer();

    /* Check layer response */
    if (layer == targetLayer) {

        /* Use member information for own cluster update */
        for (unsigned int i = 0; i < queryRspMsg->getMembersArraySize(); i++) {

            clusters[layer].add(queryRspMsg->getMembers(i));

        }

        clusters[layer].add(queryRspMsg->getSrcNode());

        /* Initiate joining of lowest layer */
        JoinCluster(queryRspMsg->getSrcNode(), layer);

        changeState(READY);

    }
    else {

        /* Evaluate RTT to queried node */
        query_start = simTime() - query_start;

        /* Find out who is nearest cluster member in response, if nodes are given */
        if (queryRspMsg->getMembersArraySize() > 0) {

            NiceMessage* joineval = new NiceMessage("NICE_JOINEVAL");
            joineval->setSrcNode(thisNode);
            joineval->setCommand(NICE_JOINEVAL);
            joineval->setLayer(layer);

            joineval->setBitLength(NICEMESSAGE_L(joineval));

            /* Initiate evaluation with all cluster members */
            for (unsigned int i = 0; i < queryRspMsg->getMembersArraySize(); i++) {

                NiceMessage* dup = static_cast<NiceMessage*>(joineval->dup());

                sendMessageToUDP(queryRspMsg->getMembers(i), dup);

            }

            delete joineval;

        }
        else { // Directly query same node again for lower layer

            Query(queryRspMsg->getSrcNode(), queryRspMsg->getLayer()-1);

        }

        evalLayer = layer;
        query_compare = simTime();

    }

void oversim::Nice::handleNiceRemove ( NiceMessage msg  )  [private]

Definition at line 1570 of file Nice.cc.

Referenced by handleUDPMessage().

{
    if (debug_removes)
        EV << simTime() << " : " << thisNode.getIp() << " : NICE_REMOVE" << endl;

    if (msg->getSrcNode() == thisNode) {
        if (debug_removes)
            EV << simTime() << " : " << thisNode.getIp() << " : received remove from self. Disregard.";
        delete msg;
        return;
    }

    short layer = msg->getLayer();

    if (pimp) {
        if (!clusters[layer].getLeader().isUnspecified()) {
            if (clusters[layer].getLeader() != thisNode && (clusters[layer].getLeader() != msg->getSrcNode())) {

                NiceMessage* dup = static_cast<NiceMessage*>(msg->dup());
                sendMessageToUDP(clusters[layer].getLeader(), dup);
                delete msg;
                return;
            }
        }
    }

    if (debug_removes)
        EV << simTime() << " : " << thisNode.getIp() << " : removing " << msg->getSrcNode() << " from layer " << layer << endl;

    if (!clusters[msg->getLayer()].getLeader().isUnspecified()) {

        if (clusters[msg->getLayer()].getLeader() == thisNode) {

            // check prevents visualization arrows to be deleted by error
            if (clusters[msg->getLayer()].contains(msg->getSrcNode())) {

                clusters[msg->getLayer()].remove(msg->getSrcNode());
                deleteOverlayNeighborArrow(msg->getSrcNode());
                updateVisualization();

            }

        }
    }

    if (debug_removes)
        EV << simTime() << " : " << thisNode.getIp() << " : NICE_REMOVE finished." << endl;

void oversim::Nice::handleNodeLeaveNotification (  )  [protected, virtual]

This method gets call **.gracefulLeaveDelay seconds before it is killed.

Reimplemented from BaseOverlay.

Definition at line 234 of file Nice.cc.

                                       {
    if (isRendevouzPoint) {
        opp_error("The NICE Rendevouz Point is being churned out and the simulation cannot continue. "
                "Please, check your config and make sure that the Chrun Generator's configuration is correct. "
                "Specifically, the Rendevouz Point must not get churned out during the simulation.");

void oversim::Nice::handleTimerEvent ( cMessage *  msg  )  [virtual]

Definition at line 318 of file Nice.cc.

{

    if (msg->isName("visualizationTimer")) {

        updateVisualization();
        scheduleAt(simTime() + 1, visualizationTimer);

    }
    else if (msg->isName("heartbeatTimer")) {

        sendHeartbeats();
        scheduleAt(simTime() + heartbeatInterval, heartbeatTimer);

    }
    else if (msg->isName("maintenanceTimer")) {

        maintenance();
        cancelEvent(maintenanceTimer);
        scheduleAt(simTime() + maintenanceInterval, maintenanceTimer);

    }
    else if (msg->isName("queryTimer")) {

        RECORD_STATS(++numInconsistencies; ++numQueryTimeouts);
        if (!tempResolver.isUnspecified() && 
                (tempResolver == RendevouzPoint ||
                 (!polledRendevouzPoint.isUnspecified() && tempResolver == polledRendevouzPoint))) {
            Query(RendevouzPoint, joinLayer);
        }
        else {
            Query(tempResolver, joinLayer);
        }

    }
    else if (msg->isName("rpPollTimer")) {

        pollRP(-1);

    }

void oversim::Nice::handleUDPMessage ( BaseOverlayMessage msg  )  [virtual]

Processes messages from underlay.

Parameters:
msg Message from UDP

Reimplemented from BaseOverlay.

Definition at line 366 of file Nice.cc.

{

    // try message cast to NICE base message
    if (dynamic_cast<NiceMessage*>(msg) != NULL) {

        NiceMessage* niceMsg = check_and_cast<NiceMessage*>(msg);

        // First of all, update activity information for sourcenode
        std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(niceMsg->getSrcNode());

        if (it != peerInfos.end()) {

            it->second->touch();

        }

        /* Dispatch message, possibly downcasting to a more concrete type */
        switch (niceMsg->getCommand()) {

            /* More concrete types, to which the message is cast if needed */
            NiceMemberMessage* queryRspMsg;
            NiceClusterMerge* mergeMsg;
            NiceMulticastMessage* multicastMsg;

            case NICE_QUERY:

                handleNiceQuery(niceMsg);

                break;

            case NICE_QUERY_RESPONSE:

                queryRspMsg = check_and_cast<NiceMemberMessage*>(niceMsg);
                handleNiceQueryResponse(queryRspMsg);

                break;

            case NICE_JOIN_CLUSTER:

                handleNiceJoinCluster(niceMsg);

                break;

            case NICE_POLL_RP:

                handleNicePollRp(niceMsg);

                break;

            case NICE_POLL_RP_RESPONSE:

                handleNicePollRpResponse(niceMsg);

                break;

            case NICE_HEARTBEAT:

                handleNiceHeartbeat(check_and_cast<NiceHeartbeat*>(niceMsg));

                break;

            case NICE_LEADERHEARTBEAT:

                handleNiceLeaderHeartbeat(check_and_cast<NiceLeaderHeartbeat*>(niceMsg));

                break;

            case NICE_LEADERTRANSFER:

                handleNiceLeaderTransfer(check_and_cast<NiceLeaderHeartbeat*>(niceMsg));

                break;

            case NICE_JOINEVAL:

                handleNiceJoineval(niceMsg);

                break;

            case NICE_JOINEVAL_RESPONSE:

                handleNiceJoinevalResponse(niceMsg);

                break;

            case NICE_REMOVE:

                handleNiceRemove(niceMsg);

                break;

            case NICE_PEER_TEMPORARY:

                handleNicePeerTemporary(niceMsg);

                break;

            case NICE_PEER_TEMPORARY_RELEASE:

                handleNicePeerTemporaryRelease(niceMsg);

                break;

            case NICE_PING_PROBE:

                handleNicePingProbe(niceMsg);

                break;

            case NICE_PING_PROBE_RESPONSE:

                handleNicePingProbeResponse(niceMsg);

                break;

            case NICE_FORCE_MERGE:

                handleNiceForceMerge(niceMsg);

                break;

            case NICE_CLUSTER_MERGE_REQUEST:

                mergeMsg = check_and_cast<NiceClusterMerge*>(niceMsg);

                handleNiceClusterMergeRequest(mergeMsg);

                break;

            case NICE_MULTICAST:

                multicastMsg = check_and_cast<NiceMulticastMessage*>(msg);

                handleNiceMulticast(multicastMsg);

                break;

            default:
                
                delete niceMsg;
        }
    }
    else {
        delete msg;

void oversim::Nice::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 120 of file Nice.cc.

{

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

    /* Set appearance of node in visualization */
    getParentModule()->getParentModule()->getDisplayString().setTagArg("i", 0, "device/pc_vs");
    getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 0, "block/circle_vs");

    /* Initially clear all clusters */
    for (int i=0; i<maxLayers; i++) {

        for (TaSet::iterator itn = clusters[i].begin(); itn != clusters[i].end(); ++itn) {
            deleteOverlayNeighborArrow(*itn);
        }
        clusters[i].clear();

    }

    /* Initialize Self-Messages */

    // Periodic Heartbeat Messages
    heartbeatInterval = par("heartbeatInterval");
    heartbeatTimer = new cMessage("heartbeatTimer");

    // Periodic Protocol Maintenance
    maintenanceInterval = par("maintenanceInterval");
    maintenanceTimer = new cMessage("maintenanceTimer");

    queryInterval = par("queryInterval");
    queryTimer = new cMessage("queryTimer");

    rpPollTimer = new cMessage("rpPollTimer");
    rpPollTimerInterval = par("rpPollTimerInterval");

    peerTimeoutHeartbeats = par("peerTimeoutHeartbeats");

    pimp = par("enhancedMode");

    isRendevouzPoint = false;

    polledRendevouzPoint = TransportAddress::UNSPECIFIED_NODE;

    /* DEBUG */
    clusterrefinement = par("debug_clusterrefinement");
    debug_heartbeats = par("debug_heartbeats");
    debug_visualization = par("debug_visualization");
    debug_join = par("debug_join");
    debug_peertimeouts = par("debug_peertimeouts");
    debug_removes = par("debug_removes");
    debug_queries = par("debug_queries");

    visualizationTimer = new cMessage("visualizationTimer");

    /* Read cluster parameter k */
    k = par("k");

    CLUSTERLEADERBOUND = par("clusterLeaderBound");
    CLUSTERLEADERCOMPAREDIST = par("clusterLeaderCompareDist");
    SC_PROC_DISTANCE = par("scProcDistance");
    SC_MIN_OFFSET = par("scMinOffset");

    /* Add own node to peerInfos */
    NicePeerInfo* pi = new NicePeerInfo(this);
    pi->set_distance(0);
    peerInfos.insert(std::make_pair(thisNode, pi));

    /* Set evaluation layer to not specified */
    evalLayer = -1;
    joinLayer = -1;

    first_leader = TransportAddress::UNSPECIFIED_NODE;
    second_leader = TransportAddress::UNSPECIFIED_NODE;

    // add some watches
    WATCH(thisNode);
    WATCH_POINTER_MAP(peerInfos);
    WATCH(evalLayer);
    WATCH(query_start);
    WATCH(heartbeatTimer);
    WATCH_MAP(tempPeers);
    WATCH(RendevouzPoint);
    WATCH(isRendevouzPoint);

    WATCH(numInconsistencies);
    WATCH(numQueryTimeouts);
    WATCH(numPeerTimeouts);
    WATCH(numTempPeerTimeouts);
    WATCH(numStructurePartitions);
    WATCH(numOwnMessagesReceived);
    WATCH(totalSCMinCompare);
    WATCH(numJoins);
    WATCH(totalForwardBytes);
    WATCH(numReceived);
    WATCH(totalReceivedBytes);
    WATCH(numHeartbeat);
    WATCH(totalHeartbeatBytes);

void oversim::Nice::JoinCluster ( const TransportAddress leader,
short  layer 
) [private]

Definition at line 1668 of file Nice.cc.

Referenced by maintenance().

{

    if (debug_join)
        EV << simTime() << " : " << thisNode.getIp() << " : JoinCluster()" << endl;

    NiceMessage* msg = new NiceMessage("NICE_JOIN_CLUSTER");
    msg->setSrcNode(thisNode);
    msg->setCommand(NICE_JOIN_CLUSTER);
    msg->setLayer(layer);
    msg->setBitLength(NICEMESSAGE_L(msg));

    sendMessageToUDP(leader, msg);

    /* Create peer context to leader */
    /* Check if peer info already exists */
    std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(leader);

    if (it != peerInfos.end()) { /* We already know this node */

    }
    else { /* Create PeerInfo object */

        NicePeerInfo* pi = new NicePeerInfo(this);

        peerInfos.insert(std::make_pair(leader, pi));

    }

    /* Locally add thisNode, too */
    clusters[layer].add(thisNode);

    /* Set leader for cluster */
    clusters[layer].add(leader);
    clusters[layer].setLeader(leader);

    for (short i=0; i<maxLayers; i++) {

        if (clusters[i].getSize() > 0) {

            if (clusters[i].contains(thisNode)) {

                getParentModule()->getParentModule()->getDisplayString().setTagArg
                ("i2", 1, clustercolors[i]);

            }

        }

    }

    // If not already running, schedule some timers
    if (!heartbeatTimer->isScheduled()) {

        scheduleAt(simTime() + heartbeatInterval, heartbeatTimer);

    }
    if (!maintenanceTimer->isScheduled()) {

        scheduleAt(simTime() + heartbeatInterval, maintenanceTimer);

    }

    if (isTempPeered) {

        // Release temporary peering
        NiceMessage* msg = new NiceMessage("NICE_PEER_TEMPORARY_RELEASE");
        msg->setSrcNode(thisNode);
        msg->setCommand(NICE_PEER_TEMPORARY_RELEASE);
        msg->setLayer(-1);
        msg->setBitLength(NICEMESSAGE_L(msg));

        sendMessageToUDP(RendevouzPoint, msg);

        isTempPeered = false;

    }

    if (debug_join)
        EV << simTime() << " : " << thisNode.getIp() << " : JoinCluster() finished." << endl;

void oversim::Nice::joinOverlay (  )  [protected, virtual]

Join the overlay with a given nodeID in thisNode.key.

Join the overlay with a given nodeID in thisNode.key. This method may be called by an application to join the overlay with a specific nodeID. It is also called if the node's IP address changes.

Reimplemented from BaseOverlay.

Definition at line 228 of file Nice.cc.

void oversim::Nice::LeaderTransfer ( int  layer,
TransportAddress  leader 
) [private]

Definition at line 3169 of file Nice.cc.

{
    ASSERT(clusters[layer].contains(leader));

    if (isRendevouzPoint) {
        opp_error("The RendevouzPoint is handing off leadership and the simulation cannot continue. This is a bug in the Nice implementation in OverSim, please check the backtrace and fix it or submit a bug report.");
    }

    TaSet cluster(clusters[layer].begin(), clusters[layer].end());

    if (layer == maxLayers - 1)
        LeaderTransfer(layer, leader, cluster, TransportAddress::UNSPECIFIED_NODE, TaSet());
    else

void oversim::Nice::LeaderTransfer ( int  layer,
TransportAddress  leader,
TaSet  cluster,
TransportAddress  sc_leader,
TaSet  superCluster 
) [private]

Definition at line 3133 of file Nice.cc.

Referenced by ClusterSplit(), gracefulLeave(), and maintenance().

{

    NiceLeaderHeartbeat* msg = new NiceLeaderHeartbeat("NICE_LEADERTRANSFER");
    msg->setSrcNode(thisNode);
    msg->setCommand(NICE_LEADERTRANSFER);
    msg->setLayer(layer);

    msg->setMembersArraySize(cluster.size());

    // fill in members
    TaSet::iterator it = cluster.begin();
    int i = 0;
    while (it != cluster.end()) {
        msg->setMembers(i++, *it);
        it++;
    }

    // fill in supercluster members, if existent
    msg->setSupercluster_leader(sc_leader);

    msg->setSupercluster_membersArraySize(superCluster.size());

    it = superCluster.begin();
    i = 0;
    while (it != superCluster.end()) {
        msg->setSupercluster_members(i++, *it);
        ++it;
    }

    msg->setBitLength(NICELEADERHEARTBEAT_L(msg));

    sendMessageToUDP(leader, msg);

void oversim::Nice::maintenance (  )  [private]

Definition at line 2350 of file Nice.cc.

Referenced by handleTimerEvent().

{
    // care for structure connection timer
    if (RendevouzPoint.isUnspecified()) {

        EV << "No RendevouzPoint! " << endl;

    }

    int highestLayer = getHighestLayer();
    bool leaderDied = false;
    clusters[highestLayer].isLeaderConfirmed();
    TransportAddress newLeader;
    TransportAddress oldLeader = clusters[highestLayer].getLeader();
    cleanPeers();
    // Cluster Leader died. Select new. If the old leader is unspecified, then we're
    // probably waiting to join the layer.
    if (clusters[highestLayer].getLeader().isUnspecified() && !oldLeader.isUnspecified()) {
        leaderDied = true;
        RECORD_STATS(++numStructurePartitions; ++numInconsistencies);
        newLeader = findCenter(clusters[highestLayer]).first;
    }

    splitNeeded();
    mergeNeeded();

    if (leaderDied && RendevouzPoint != oldLeader) {
        clusters[highestLayer].setLeader(newLeader);
        if (newLeader == thisNode) {
            clusters[highestLayer + 1].add(newLeader);
            BasicJoinLayer(highestLayer + 1);
        }
        else {
            LeaderTransfer(highestLayer, newLeader);
        }
    }
    else if (getHighestLayer() == getHighestLeaderLayer()) {
        if (!isRendevouzPoint) {
            pollRP(-1);
            BasicJoinLayer(getHighestLayer() + 1);
        }
    }

    highestLayer = getHighestLayer();
    for (int i = highestLayer + 1; i < maxLayers; ++i) {
        if (clusters[i].getSize() != 0) {
            EV << "Stale data for cluster " << i << endl;
            for (TaSet::iterator itn = clusters[i].begin(); itn != clusters[i].end(); ++itn) {
                deleteOverlayNeighborArrow(*itn);
            }
            clusters[i].clear();
        }
    }

    // if highest super cluster has more than one member, try to find a closer leader.
    // However, the Rendevouz Point must can't move between clusters.
    if (!isRendevouzPoint && highestLayer < maxLayers - 1 && clusters[highestLayer + 1].getSize() > 1) {

        if (clusterrefinement)
            EV << simTime() << " : " << thisNode.getIp() << " : Look for better parent node in cluster : " << highestLayer + 1 << " ..."<< endl;

        TransportAddress highestLeader = clusters[highestLayer].getLeader();
        std::map<TransportAddress, NicePeerInfo*>::iterator it;
        if (!highestLeader.isUnspecified()) {
            it = peerInfos.find(highestLeader);
        }
        else {
            it = peerInfos.end();
        }

        if (it != peerInfos.end() && it->second->get_distance() > 0) {

            double distance = it->second->get_distance() - ((it->second->get_distance()/100.0) * SC_PROC_DISTANCE);

            double smallest = 10000.0;
            TransportAddress candidate = TransportAddress::UNSPECIFIED_NODE;

            for (int i=0; i < clusters[highestLayer+1].getSize(); i++) {

                if (clusters[highestLayer+1].get(i) != clusters[highestLayer].getLeader()) {

                    std::map<TransportAddress, NicePeerInfo*>::iterator it2 = peerInfos.find(clusters[highestLayer+1].get(i));

                    if (it2 != peerInfos.end()) {

                        if ((it2->second->get_distance() < smallest) && (it2->second->get_distance() > 0)) {
                            smallest = it2->second->get_distance();
                            candidate = it2->first;
                        }

                    }

                }

            }

            std::set<TransportAddress> clusterset;

            for (int m=0; m<clusters[getHighestLayer()+1].getSize(); m++) {

                clusterset.insert(clusters[getHighestLayer()+1].get(m));

            }

            simtime_t meanDistance = getMeanDistance(clusterset);

            simtime_t minCompare = (meanDistance/100.0)*SC_MIN_OFFSET;

            RECORD_STATS(totalSCMinCompare += minCompare.dbl());

            if (minCompare < 0.005)
                minCompare = 0.005;

            if ((smallest < distance) && ((distance - smallest) > minCompare.dbl())) { // change supercluster


                if (clusterrefinement) {
                    EV << simTime() <<" : " << thisNode.getIp() << ": Change SuperCluster! to " << candidate.getIp() << endl;
                    EV << "Old distance ():  " << it->second->get_distance() << endl;
                    EV << "SC_PROC_DISTANCE:  " << SC_PROC_DISTANCE << endl;
                    EV << "Compare distance:  " << distance << endl;
                    EV << "New distance:  " << smallest << endl;
                    EV << "New SC_MIN_OFFSET:  " << SC_MIN_OFFSET << endl;
                }

                // leave old
                Remove(highestLayer);

                // join new
                JoinCluster(candidate, highestLayer);

                return;

            }
        }
        else {

            //Do nothing

        }

    }

    if (!isRendevouzPoint) {

        // Try to find better leader.
        for (int i = getHighestLeaderLayer(); i >= 0; i--) {

            if (clusters[i].getSize() > 1 && clusters[i].isLeaderConfirmed()) {

                bool allDistancesKnown = true;

                if (clusterrefinement)
                    EV << simTime() << " : " << thisNode.getIp() << " : Find better cluster leader in ..." << i << endl;

                /* Only make decisions if node has total distance knowledge in this cluster */
                for (int j = 0; j < clusters[i].getSize() && allDistancesKnown; j++) {

                    /* Check if peer info already exists */
                    std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(clusters[i].get(j));

                    if (it != peerInfos.end()) {

                        simtime_t distance = it->second->get_distance();

                        //EV << "My distance to " << it->first << " : " << distance << endl;

                        if (distance < 0) {
                            allDistancesKnown = false;
                            continue;
                        }

                        for (int k = 0; k < clusters[i].getSize(); k++) {

                            if ((it->first != thisNode) && (clusters[i].get(k) != it->first)) {

                                if (it->second->getDistanceTo(clusters[i].get(k)) < 0) {
                                    allDistancesKnown = false;
                                    break;
                                }
                            }

                        }

                    }
                    else {

                        allDistancesKnown = false;

                    }

                }

                if (allDistancesKnown) {

                    if (clusterrefinement)
                        EV << "Complete distance knowledge available." << endl;

                    // Perform check for better cluster leader
                    TransportAddress new_leader = findCenter(clusters[i]).first;

                    if (clusterrefinement)
                        EV << "NEW LEADER laut " << thisNode.getIp() << " --> " << new_leader.getIp() << endl;

                    std::set<TransportAddress> clusterset;

                    for (int m=0; m<clusters[i].getSize(); m++) {

                        clusterset.insert(clusters[i].get(m));

                    }


                    simtime_t meanDistance = getMeanDistance(clusterset);
                    simtime_t oldDistance = getMaxDistance(clusters[i].getLeader(), clusterset);
                    simtime_t newDistance = getMaxDistance(new_leader, clusterset);
                    simtime_t compareDistance = (oldDistance - ((oldDistance/100.0)*CLUSTERLEADERCOMPAREDIST));

                    simtime_t minCompare = (meanDistance/100.0)*CLUSTERLEADERBOUND;

                    if (minCompare < 0.005)
                        minCompare = 0.005;

                    if ((newDistance.dbl() < compareDistance.dbl()) && ((compareDistance.dbl() - newDistance.dbl()) > minCompare.dbl())) {

                        if (clusterrefinement)
                            EV << "CHANGE " << CLUSTERLEADERCOMPAREDIST << endl;

                        if (new_leader != thisNode) {

                            // Set new leader for this cluster
                            clusters[i].setLeader(new_leader);

                            for (int j=0; j<clusters[i].getSize(); j++) {

                                deleteOverlayNeighborArrow(clusters[i].get(j));

                            }

                            gracefulLeave(i);
                            LeaderTransfer(i, new_leader);

                            getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 0, "block/circle_vs");

                        }

                    }

                    if (clusterrefinement) {
                        EV << "MaxDistance " << new_leader.getIp() << " : " << getMaxDistance(new_leader, clusterset) << endl;
                        EV << "MaxDistance " << clusters[i].getLeader() << " : " << getMaxDistance(clusters[i].getLeader(), clusterset) << endl;
                        EV << "MaxDistance " << thisNode.getIp() << " : " << getMaxDistance(thisNode, clusterset) << endl;
                    }


                }

            } // if cluster i has other members

        } // for i from highest leader layer to 0

    } // if this is not the rendevouz point

bool oversim::Nice::mergeNeeded (  )  [private]

Merges clusters if needed.

mergeNeeded

Returns true if a merge was made, false otherwise.

Definition at line 2227 of file Nice.cc.

Referenced by maintenance().

{
    if (isRendevouzPoint) {
        // The Rendevouz Point can't initiate a merge, since that would
        // compromise its status as a Rendevouz Point.
        return false;
    }

    // The layer at which we must merge
    int mergeLayer;
    int highestLeaderLayer = getHighestLeaderLayer();
    
    // Find lowest layer that needs merging.
    // The node will disappear from all higher layers.
    for (mergeLayer= 0; mergeLayer <= highestLeaderLayer && mergeLayer < maxLayers - 1; ++mergeLayer) {
        /* Do not attempt merging if we're not sure we belong as leader */
        if (clusters[mergeLayer].getSize() < k && clusters[mergeLayer].isLeaderConfirmed() &&
                clusters[mergeLayer + 1].isLeaderConfirmed()) {
            ClusterMerge(mergeLayer);

            // The merge may fail, check if it did.
            // If it really did, we should try to see if there's some other layer that we may merge.
            if (!clusters[mergeLayer + 1].contains(thisNode)) {
                return true;
            }
        }
    }
    

void oversim::Nice::pollRP ( int  layer  )  [private]

Definition at line 3465 of file Nice.cc.

Referenced by changeState(), handleTimerEvent(), and maintenance().

{

    if (debug_queries)
        EV << simTime() << " : " << thisNode.getIp() << " : pollRP()" << endl;

    NiceMessage* msg = new NiceMessage("NICE_POLL_RP");
    msg->setSrcNode(thisNode);
    msg->setCommand(NICE_POLL_RP);
    msg->setLayer(layer);
    msg->setBitLength(NICEMESSAGE_L(msg));

    cancelEvent(rpPollTimer);
    scheduleAt(simTime() + rpPollTimerInterval, rpPollTimer);

    sendMessageToUDP(RendevouzPoint, msg);

    polledRendevouzPoint = RendevouzPoint;

    if (debug_queries)
        EV << simTime() << " : " << thisNode.getIp() << " : pollRP() finished." << endl;

void oversim::Nice::Query ( const TransportAddress node,
short  layer 
) [private]

Definition at line 592 of file Nice.cc.

Referenced by BasicJoinLayer(), and handleTimerEvent().

{
    if (debug_queries)
        EV << simTime() << " : " << thisNode.getIp() << " : Query()" << endl;


    NiceMessage* msg = new NiceMessage("NICE_QUERY");
    msg->setSrcNode(thisNode);
    msg->setCommand(NICE_QUERY);
    msg->setLayer(layer);
    msg->setBitLength(NICEMESSAGE_L(msg));

    query_start = simTime();
    tempResolver = destination;

    cancelEvent(queryTimer);
    scheduleAt(simTime() + queryInterval, queryTimer);

    joinLayer = layer;

    sendMessageToUDP(destination, msg);

    if (debug_queries)
        EV << simTime() << " : " << thisNode.getIp() << " : Query() finished." << endl;

void oversim::Nice::Remove ( int  layer  )  [private]

Definition at line 3188 of file Nice.cc.

Referenced by gracefulLeave(), and maintenance().

{
    if (debug_removes)
        EV << simTime() << " : " << thisNode.getIp() << " : Remove()" << endl;

    int highestLayer = getHighestLayer();
    ASSERT(layer <= highestLayer);

    NiceMessage* msg = new NiceMessage("NICE_REMOVE");
    msg->setSrcNode(thisNode);
    msg->setCommand(NICE_REMOVE);
    msg->setLayer(layer);

    msg->setBitLength(NICEMESSAGE_L(msg));

    sendMessageToUDP(clusters[layer].getLeader(), msg);

    clusters[layer].remove(thisNode);

    for (short i=0; i<maxLayers; i++) {

        if (clusters[i].getSize() > 0) {

            if (clusters[i].contains(thisNode)) {

                getParentModule()->getParentModule()->getDisplayString().setTagArg
                ("i2", 1, clustercolors[i]);

            }

        }

    }

    if (debug_removes)
        EV << simTime() << " : " << thisNode.getIp() << " : Remove() finished." << endl;

void oversim::Nice::sendDataToOverlay ( NiceMulticastMessage appMsg  )  [private]

Definition at line 3363 of file Nice.cc.

Referenced by handleAppMessage().

{

    for (int layer=0; layer <= getHighestLayer(); layer++) {

        if ( appMsg->getLayer() != layer ) {

            for (int j=0; j<clusters[layer].getSize(); j++) {

                if (!(clusters[layer].contains(appMsg->getLastHop())) || appMsg->getSrcNode() == thisNode) {

                    const TransportAddress& member = clusters[layer].get(j);

                    if (!(member == thisNode)) {

                        NiceMulticastMessage* dup = static_cast<NiceMulticastMessage*>(appMsg->dup());

                        dup->setLayer( layer );
                        dup->setLastHop(thisNode);

                        sendMessageToUDP(member, dup);

                    }

                }

            } // for

        }

    }

    // Also forward data to temporary peers
    std::map<TransportAddress, simtime_t>::iterator it = tempPeers.begin();

    while (it != tempPeers.end()) {

        NiceMulticastMessage* dup = static_cast<NiceMulticastMessage*>(appMsg->dup());

        dup->setSrcNode(thisNode);

        sendMessageToUDP(it->first, dup);

        it++;

    }

    delete appMsg;

void oversim::Nice::sendHeartbeats (  )  [private]

Definition at line 1755 of file Nice.cc.

Referenced by ClusterSplit(), and handleTimerEvent().

{

    /* Go through all cluster layers from top to bottom */

    for (int i=getHighestLayer(); i >= 0; i--) {

        /* Determine if node is cluster leader in this layer */
        if (!clusters[i].getLeader().isUnspecified()) {

            if (clusters[i].getLeader() == thisNode) {
                clusters[i].confirmLeader();

                /* Build heartbeat message with info on all current members */
                NiceLeaderHeartbeat* msg = new NiceLeaderHeartbeat("NICE_LEADERHEARTBEAT");
                msg->setSrcNode(thisNode);
                msg->setCommand(NICE_LEADERHEARTBEAT);
                msg->setLayer(i);
                msg->setOne_hop_distance(simTime().dbl());
                msg->setK(k);
                msg->setSc_tolerance(SC_PROC_DISTANCE);

                msg->setMembersArraySize(clusters[i].getSize());

                /* Fill in members */
                for (int j = 0; j < clusters[i].getSize(); j++) {

                    msg->setMembers(j, clusters[i].get(j));

                }

                /* Fill in distances to members */
                msg->setDistancesArraySize(clusters[i].getSize());

                for (int j = 0; j < clusters[i].getSize(); j++) {

                    std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(clusters[i].get(j));

                    if (it != peerInfos.end()) {

                        msg->setDistances(j, it->second->get_distance());

                    }
                    else {

                        msg->setDistances(j, -1);

                    }

                }

                /* Fill in Supercluster members, if existent */
                if (clusters[i+1].getSize() > 0) {

                    msg->setSupercluster_leader(clusters[i+1].getLeader());

                    msg->setSupercluster_membersArraySize(clusters[i+1].getSize());

                    for (int j = 0; j < clusters[i+1].getSize(); j++) {

                        msg->setSupercluster_members(j, clusters[i+1].get(j));

                    }

                }

                /* Send Heartbeat to all members in cluster, except me */
                for (int j = 0; j < clusters[i].getSize(); j++) {

                    if (clusters[i].get(j) != thisNode) {

                        NiceLeaderHeartbeat *copy = static_cast<NiceLeaderHeartbeat*>(msg->dup());

                        /* Get corresponding sequence numbers out of peerInfo */
                        std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(clusters[i].get(j));

                        if (it != peerInfos.end()) {

                            unsigned int seqNo = it->second->get_last_sent_HB();

                            copy->setSeqNo(++seqNo);

                            it->second->set_backHB(it->second->get_backHBPointer(), seqNo, simTime().dbl());
                            it->second->set_last_sent_HB(seqNo);
                            it->second->set_backHBPointer(!it->second->get_backHBPointer());

                            copy->setSeqRspNo(it->second->get_last_recv_HB());

                            if (it->second->get_last_HB_arrival() > 0) {

                                copy->setHb_delay(simTime().dbl() - it->second->get_last_HB_arrival());

                            }
                            else {

                                copy->setHb_delay(0.0);

                            }

                        }

                        copy->setBitLength(NICELEADERHEARTBEAT_L(msg));

                        RECORD_STATS(++numHeartbeat; totalHeartbeatBytes += copy->getByteLength());

                        sendMessageToUDP(clusters[i].get(j), copy);

                    }

                }

                delete msg;

            }
            else { // I am normal cluster member

                /* Build heartbeat message with info on all current members */
                NiceHeartbeat* msg = new NiceHeartbeat("NICE_HEARTBEAT");
                msg->setSrcNode(thisNode);
                msg->setCommand(NICE_HEARTBEAT);
                msg->setLayer(i);
                msg->setOne_hop_distance(simTime().dbl());

                msg->setSublayermembers(0);
                if (i>0) {
                    if (clusters[i-1].getLeader() == thisNode)
                        msg->setSublayermembers(clusters[i-1].getSize());

                }

                msg->setMembersArraySize(clusters[i].getSize());

                /* Fill in members */
                for (int j = 0; j < clusters[i].getSize(); j++) {

                    msg->setMembers(j, clusters[i].get(j));

                }

                /* Fill in distances to members */
                msg->setDistancesArraySize(clusters[i].getSize());

                for (int j = 0; j < clusters[i].getSize(); j++) {

                    std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(clusters[i].get(j));

                    if (it != peerInfos.end()) {

                        msg->setDistances(j, it->second->get_distance());

                    }
                    else {

                        msg->setDistances(j, -1);

                    }

                }

                /* Send Heartbeat to all members in cluster, except me */
                for (int j = 0; j < clusters[i].getSize(); j++) {

                    if (clusters[i].get(j) != thisNode) {

                        NiceHeartbeat *copy = static_cast<NiceHeartbeat*>(msg->dup());

                        /* Get corresponding sequence number out of peerInfo */
                        std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(clusters[i].get(j));

                        if (it != peerInfos.end()) {

                            unsigned int seqNo = it->second->get_last_sent_HB();

                            copy->setSeqNo(++seqNo);

                            it->second->set_backHB(it->second->get_backHBPointer(), seqNo, simTime().dbl());
                            it->second->set_backHBPointer(!it->second->get_backHBPointer());
                            it->second->set_last_sent_HB(seqNo);

                            copy->setSeqRspNo(it->second->get_last_recv_HB());

                            copy->setHb_delay(simTime().dbl() - it->second->get_last_HB_arrival());

                        }

                        copy->setBitLength(NICEHEARTBEAT_L(msg));

                        RECORD_STATS(++numHeartbeat; totalHeartbeatBytes += copy->getByteLength());

                        sendMessageToUDP(clusters[i].get(j), copy);

                    }

                }

                delete msg;

            }
        }

    }

    // Additionally, ping all supercluster members, if existent
    if (clusters[getHighestLayer()+1].getSize() > 0 && !clusters[getHighestLayer()].getLeader().isUnspecified()) {

        NiceMessage* msg = new NiceMessage("NICE_PING_PROBE");
        msg->setSrcNode(thisNode);
        msg->setCommand(NICE_PING_PROBE);
        msg->setLayer(getHighestLayer()+1);

        msg->setBitLength(NICEMESSAGE_L(msg));

        for (int i=0; i<clusters[getHighestLayer()+1].getSize(); i++) {

            if (clusters[getHighestLayer()+1].get(i) != clusters[getHighestLayer()].getLeader()) {

                NiceMessage* dup = static_cast<NiceMessage*>(msg->dup());

                sendMessageToUDP(clusters[getHighestLayer()+1].get(i), dup);

                std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(clusters[getHighestLayer()+1].get(i));

                if (it != peerInfos.end()) {

                    it->second->set_distance_estimation_start(simTime().dbl());

                }

            }

        }

        delete msg;

    }

void oversim::Nice::sendHeartbeatTo ( const TransportAddress node,
int  layer 
) [private]

Definition at line 1997 of file Nice.cc.

{

    if (clusters[layer].getLeader() == thisNode) {

        /* Build heartbeat message with info on all current members */
        NiceLeaderHeartbeat* msg = new NiceLeaderHeartbeat("NICE_LEADERHEARTBEAT");
        msg->setSrcNode(thisNode);
        msg->setCommand(NICE_LEADERHEARTBEAT);
        msg->setLayer(layer);

        msg->setMembersArraySize(clusters[layer].getSize());

        /* Fill in members */
        for (int j = 0; j < clusters[layer].getSize(); j++) {

            msg->setMembers(j, clusters[layer].get(j));

        }

        /* Fill in distances to members */
        msg->setDistancesArraySize(clusters[layer].getSize());

        for (int j = 0; j < clusters[layer].getSize(); j++) {

            std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(clusters[layer].get(j));

            if (it != peerInfos.end()) {

                msg->setDistances(j, it->second->get_distance());

            }
            else {

                msg->setDistances(j, -1);

            }

        }

        /* Fill in Supercluster members, if existent */
        if (clusters[layer+1].getSize() > 0) {

            msg->setSupercluster_leader(clusters[layer+1].getLeader());

            msg->setSupercluster_membersArraySize(clusters[layer+1].getSize());

            for (int j = 0; j < clusters[layer+1].getSize(); j++) {

                msg->setSupercluster_members(j, clusters[layer+1].get(j));

            }

        }

        /* Get corresponding sequence numbers out of peerInfo */
        std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(node);

        if (it != peerInfos.end()) {

            unsigned int seqNo = it->second->get_last_sent_HB();

            msg->setSeqNo(++seqNo);

            it->second->set_backHB(it->second->get_backHBPointer(), seqNo, simTime().dbl());
            it->second->set_last_sent_HB(seqNo);
            it->second->set_backHBPointer(!it->second->get_backHBPointer());

            msg->setSeqRspNo(it->second->get_last_recv_HB());

            msg->setHb_delay(simTime().dbl() - it->second->get_last_HB_arrival());

        }

        msg->setBitLength(NICELEADERHEARTBEAT_L(msg));

        RECORD_STATS(++numHeartbeat; totalHeartbeatBytes += msg->getByteLength());

        sendMessageToUDP(node, msg);

    }
    else {

        // build heartbeat message with info on all current members
        NiceHeartbeat* msg = new NiceHeartbeat("NICE_HEARTBEAT");
        msg->setSrcNode(thisNode);
        msg->setCommand(NICE_HEARTBEAT);
        msg->setLayer(layer);

        msg->setMembersArraySize(clusters[layer].getSize());

        // fill in members
        for (int j = 0; j < clusters[layer].getSize(); j++) {

            msg->setMembers(j, clusters[layer].get(j));

        }

        // fill in distances to members
        msg->setDistancesArraySize(clusters[layer].getSize());

        for (int j = 0; j < clusters[layer].getSize(); j++) {

            std::map<TransportAddress, NicePeerInfo*>::iterator it = peerInfos.find(clusters[layer].get(j));

            if (it != peerInfos.end()) {

                msg->setDistances(j, it->second->get_distance());

            }
            else if (clusters[layer].get(j) == thisNode) {

                msg->setDistances(j, 0);

            }
            else {

                msg->setDistances(j, -1);

            }

        }

        msg->setBitLength(NICEHEARTBEAT_L(msg));

        RECORD_STATS(++numHeartbeat; totalHeartbeatBytes += msg->getByteLength());

        sendMessageToUDP(node, msg);

    }

void oversim::Nice::sendRemoveTo ( const TransportAddress node,
int  layer 
) [private]

sendRemoveTo

Definition at line 2133 of file Nice.cc.

{
    NiceMessage* msg = new NiceMessage("NICE_REMOVE");
    msg->setSrcNode(thisNode);
    msg->setCommand(NICE_REMOVE);
    msg->setLayer(layer);

    msg->setBitLength(NICEMESSAGE_L(msg));

bool oversim::Nice::splitNeeded (  )  [private]

Splits clusters if needed.

splitNeeded

Returns true if a split was made, false otherwise.

Definition at line 2206 of file Nice.cc.

Referenced by maintenance().

{
    bool splitMade = false;
    // Check if cluster split is necessary
    // Find lowest layer that needs splitting and split it. If we're still cluster leader, continue up.
    for (int i = 0, highest = std::min(getHighestLeaderLayer(), maxLayers - 2);
            i <= highest && !clusters[i].getLeader().isUnspecified() && clusters[i].getLeader() == thisNode;
            ++i) {
        if (clusters[i].getSize() > 3 * k + 1 &&
                clusters[i].isLeaderConfirmed() &&
                (i == maxLayers - 1 || clusters[i + 1].getSize() == 0 || clusters[i + 1].isLeaderConfirmed())) {
            splitMade = true;
            ClusterSplit(i);
        }
    }

void oversim::Nice::updateVisualization (  )  [private]

Definition at line 3418 of file Nice.cc.

Referenced by ClusterSplit(), and handleTimerEvent().

{

    if (debug_visualization)
        EV << simTime() << " : " << thisNode.getIp() << " : updateVisualization" << endl;

    /* Update node symbol */
    getParentModule()->getParentModule()
    ->getDisplayString().setTagArg("i2", 0, "block/circle_vs");

    if (isRendevouzPoint) {

        getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 0, "block/star_vs");

    }

    /* Update node color */
    if (debug_visualization)
        EV << "getHighestLayer(): " << getHighestLayer() << endl;

    getParentModule()->getParentModule()
    ->getDisplayString().setTagArg("i2", 1, clustercolors[getHighestLayer()]);

    //redraw
    for (int i=0; clusters[i].contains(thisNode); i++) {

        if (!(clusters[i].getLeader().isUnspecified())) {

            if (clusters[i].getLeader() == thisNode) {

                for (int j=0; j<clusters[i].getSize();j++) {

                    if (debug_visualization)
                        EV << "draw to: " << clusters[i].get(j) << endl;

                    showOverlayNeighborArrow(clusters[i].get(j), false, clusterarrows[i]);

                }

            }

        }
    }


Friends And Related Function Documentation

friend class NicePeerInfo [friend]

Definition at line 65 of file Nice.h.

Referenced by initializeOverlay().


Member Data Documentation

Definition at line 186 of file Nice.h.

Referenced by initializeOverlay(), and maintenance().

Definition at line 187 of file Nice.h.

Referenced by initializeOverlay(), and maintenance().

Definition at line 146 of file Nice.h.

Referenced by initializeOverlay(), and maintenance().

Definition at line 147 of file Nice.h.

Referenced by initializeOverlay().

Definition at line 149 of file Nice.h.

Referenced by finishOverlay(), and initializeOverlay().

Definition at line 150 of file Nice.h.

Referenced by initializeOverlay().

Definition at line 152 of file Nice.h.

Referenced by handleNiceQuery(), initializeOverlay(), and Query().

Definition at line 151 of file Nice.h.

Referenced by initializeOverlay(), and Remove().

Definition at line 148 of file Nice.h.

Referenced by initializeOverlay(), and updateVisualization().

int oversim::Nice::evalLayer [private]

Definition at line 161 of file Nice.h.

Referenced by initializeOverlay().

simtime_t oversim::Nice::first_HB [private]

Definition at line 138 of file Nice.h.

Definition at line 139 of file Nice.h.

Referenced by initializeOverlay().

simtime_t oversim::Nice::heartbeatInterval [private]

Definition at line 116 of file Nice.h.

Referenced by changeState(), handleTimerEvent(), and initializeOverlay().

cMessage* oversim::Nice::heartbeatTimer [private]

Definition at line 115 of file Nice.h.

Referenced by changeState(), handleTimerEvent(), initializeOverlay(), and ~Nice().

Definition at line 184 of file Nice.h.

Referenced by BasicJoinLayer().

int oversim::Nice::joinLayer [private]

Definition at line 162 of file Nice.h.

Referenced by handleTimerEvent(), initializeOverlay(), and Query().

unsigned short oversim::Nice::k [private]

Definition at line 155 of file Nice.h.

Referenced by initializeOverlay(), maintenance(), and sendHeartbeats().

std::vector<std::pair<TransportAddress, simtime_t> > oversim::Nice::leaderHeartbeats [private]

Definition at line 143 of file Nice.h.

Definition at line 120 of file Nice.h.

Referenced by changeState(), handleTimerEvent(), and initializeOverlay().

cMessage* oversim::Nice::maintenanceTimer [private]

Definition at line 119 of file Nice.h.

Referenced by changeState(), handleTimerEvent(), initializeOverlay(), and ~Nice().

const short oversim::Nice::maxLayers = 10 [static, private]

Definition at line 63 of file Nice.h.

Referenced by handleNiceQuery(), and initializeOverlay().

Definition at line 208 of file Nice.h.

Referenced by finishOverlay().

Definition at line 216 of file Nice.h.

Referenced by finishOverlay(), initializeOverlay(), sendHeartbeats(), and sendHeartbeatTo().

Definition at line 192 of file Nice.h.

Referenced by finishOverlay(), handleTimerEvent(), initializeOverlay(), and maintenance().

int oversim::Nice::numJoins [private]

Definition at line 206 of file Nice.h.

Referenced by finishOverlay(), and initializeOverlay().

Definition at line 202 of file Nice.h.

Referenced by finishOverlay(), and initializeOverlay().

Definition at line 196 of file Nice.h.

Referenced by finishOverlay(), and initializeOverlay().

Definition at line 194 of file Nice.h.

Referenced by finishOverlay(), handleTimerEvent(), and initializeOverlay().

Definition at line 212 of file Nice.h.

Referenced by finishOverlay(), and initializeOverlay().

Definition at line 200 of file Nice.h.

Referenced by finishOverlay(), initializeOverlay(), and maintenance().

Definition at line 198 of file Nice.h.

Referenced by finishOverlay(), and initializeOverlay().

Definition at line 130 of file Nice.h.

Referenced by initializeOverlay().

int oversim::Nice::pimp [private]

Definition at line 106 of file Nice.h.

Referenced by ClusterSplit(), handleNiceQuery(), and initializeOverlay().

Definition at line 165 of file Nice.h.

Referenced by handleTimerEvent(), and initializeOverlay().

simtime_t oversim::Nice::query_compare [private]

Definition at line 174 of file Nice.h.

simtime_t oversim::Nice::query_start [private]

Definition at line 168 of file Nice.h.

Referenced by initializeOverlay(), and Query().

simtime_t oversim::Nice::queryInterval [private]

Definition at line 124 of file Nice.h.

Referenced by initializeOverlay(), and Query().

cMessage* oversim::Nice::queryTimer [private]

Definition at line 123 of file Nice.h.

Referenced by initializeOverlay(), Query(), and ~Nice().

cMessage* oversim::Nice::rpPollTimer [private]

Definition at line 127 of file Nice.h.

Referenced by initializeOverlay(), and ~Nice().

Definition at line 128 of file Nice.h.

Referenced by initializeOverlay().

double oversim::Nice::SC_MIN_OFFSET [private]

Definition at line 189 of file Nice.h.

Referenced by initializeOverlay(), and maintenance().

Definition at line 188 of file Nice.h.

Referenced by initializeOverlay(), maintenance(), and sendHeartbeats().

simtime_t oversim::Nice::second_HB [private]

Definition at line 140 of file Nice.h.

Definition at line 141 of file Nice.h.

Referenced by initializeOverlay().

short oversim::Nice::targetLayer [private]

Definition at line 177 of file Nice.h.

Referenced by BasicJoinLayer().

std::map<TransportAddress, simtime_t> oversim::Nice::tempPeers [private]

Definition at line 183 of file Nice.h.

Referenced by initializeOverlay(), and sendDataToOverlay().

Definition at line 171 of file Nice.h.

Referenced by handleTimerEvent(), and Query().

Definition at line 210 of file Nice.h.

Referenced by finishOverlay(), and initializeOverlay().

Definition at line 214 of file Nice.h.

Referenced by finishOverlay(), and initializeOverlay().

Definition at line 204 of file Nice.h.

Referenced by finishOverlay(), initializeOverlay(), and maintenance().

cMessage* oversim::Nice::visualizationTimer [private]

Definition at line 133 of file Nice.h.

Referenced by changeState(), handleTimerEvent(), initializeOverlay(), and ~Nice().


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