OverSim
oversim::Nice Class Reference

NICE overlay module. More...

#include <Nice.h>

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

Public Types

typedef std::set
< TransportAddress
TaSet
typedef std::set
< TransportAddress >::iterator 
TaSetIt
- Public Types inherited from BaseOverlay
enum  States {
  INIT = 0, BOOTSTRAP = 1, DISCOVERY = 2, PREJOIN = 3,
  JOIN = 4, POSTJOIN = 5, READY = 6, REFRESH = 7,
  SHUTDOWN = 8, FAILED = 9, RSET = JOIN, BSET = POSTJOIN
}
- Public Types inherited from BaseTcpSupport
enum  EvCode {
  NO_EST_CONNECTION, PEER_CLOSED, PEER_TIMEDOUT, PEER_REFUSED,
  CONNECTION_RESET, CONNECTION_SUCC_ClOSED
}

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
- Public Member Functions inherited from BaseOverlay
 BaseOverlay ()
virtual ~BaseOverlay ()
 Virtual destructor.
States getState ()
bool isMalicious ()
 Returns true, if node is malicious.
bool isInSimpleMultiOverlayHost ()
 Returns true if overlay is one in an array, inside a SimpleMultiOverlayHost.
const simtime_t & getCreationTime ()
void join (const OverlayKey &nodeID=OverlayKey::UNSPECIFIED_KEY)
 Join the overlay with a given nodeID.
virtual NodeVectorlocal_lookup (const OverlayKey &key, int num, bool safe)
 finds nodes closest to the given OverlayKey
virtual NodeVectorneighborSet (int num)
virtual bool isSiblingFor (const NodeHandle &node, const OverlayKey &key, int numSiblings, bool *err)
 Query if a node is among the siblings for a given key.
virtual int getMaxNumSiblings ()
 Query the maximum number of siblings (nodes close to a key) that are maintained by this overlay protocol.
virtual int getMaxNumRedundantNodes ()
 Query the maximum number of redundant next hop nodes that are returned by findNode().
void sendMessageToUDP (const TransportAddress &dest, cPacket *msg, simtime_t delay=SIMTIME_ZERO)
 Sends message to underlay.
void sendToKey (const OverlayKey &key, BaseOverlayMessage *message, int numSiblings=1, const std::vector< TransportAddress > &sourceRoute=TransportAddress::UNSPECIFIED_NODES, RoutingType routingType=DEFAULT_ROUTING)
 Sends a message to an overlay node, with the generic routing algorithm.
virtual OverlayKey distance (const OverlayKey &x, const OverlayKey &y, bool useAlternative=false) const
 This method should implement the distance between two keys.
void registerComp (CompType compType, cModule *module)
cModule * getCompModule (CompType compType)
cGate * getCompRpcGate (CompType compType)
void sendMessageToAllComp (cMessage *msg, CompType srcComp)
bool providesKbr ()
virtual uint8_t getBitsPerDigit ()
bool getMeasureAuthBlock ()
BootstrapListgetBootstrapList () const
virtual OverlayKey estimateMeanDistance ()
 returns mean distance between OverlayKeys in the network
virtual uint32_t estimateOverlaySize ()
 estimates the current number of nodes online
- Public Member Functions inherited from BaseRpc
 BaseRpc ()
const NodeHandlegetThisNode ()
 Returns the NodeHandle of this node.
simtime_t getUdpTimeout ()
- Public Member Functions inherited from RpcListener
virtual ~RpcListener ()
 destructor
- Public Member Functions inherited from BaseTcpSupport
virtual void socketDataArrived (int connId, void *yourPtr, cPacket *msg, bool urgent)
virtual void socketEstablished (int connId, void *yourPtr)
virtual void socketPeerClosed (int connId, void *yourPtr)
virtual void socketFailure (int connId, void *yourPtr, int code)
virtual void socketStatusArrived (int connId, void *yourPtr, TCPStatusInfo *status)
- Public Member Functions inherited from TopologyVis
 TopologyVis ()
void showOverlayNeighborArrow (const NodeHandle &neighbor, bool flush=true, const char *displayString=NULL)
 Draws an arrow from this node to neighbor.
void deleteOverlayNeighborArrow (const NodeHandle &neighbor)
 Removes an arrow from this node to neighbor.

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.
- Protected Member Functions inherited from BaseOverlay
int numInitStages () const
 Sets init stage.
void bindToPort (int port)
 Tells UDP we want to get all packets arriving on the given port.
virtual void route (const OverlayKey &key, CompType destComp, CompType srcComp, cPacket *msg, const std::vector< TransportAddress > &sourceRoute=TransportAddress::UNSPECIFIED_NODES, RoutingType routingType=DEFAULT_ROUTING)
 Routes message through overlay.
void callDeliver (BaseOverlayMessage *msg, const OverlayKey &destKey)
 Calls deliver function in application.
void callForward (const OverlayKey &key, BaseRouteMessage *msg, const NodeHandle &nextHopNode)
 Calls forward function in application.
void callUpdate (const NodeHandle &node, bool joined)
 Informs application about state changes of nodes or newly joined nodes.
void handleMessage (cMessage *msg)
 Checks for message type and calls corresponding method.
void handleBaseOverlayMessage (BaseOverlayMessage *msg, const OverlayKey &destKey=OverlayKey::UNSPECIFIED_KEY)
 Handles a BaseOverlayMessage

virtual void receiveChangeNotification (int category, const cPolymorphic *details)
 callback-method for events at the NotificationBoard
virtual void handleTransportAddressChangedNotification ()
 This method gets call if the node has a new TransportAddress (IP address) because he changed his access network.
virtual void handleNodeGracefulLeaveNotification ()
 This method gets call **.gracefulLeaveDelay seconds before it is killed if this node is among the gracefulLeaveProbability nodes.
virtual void recordOverlaySentStats (BaseOverlayMessage *msg)
 Collect overlay specific sent messages statistics.
void setOverlayReady (bool ready)
 Sets the overlay ready icon and register/deregisters the node at the GlobalNodeList.
virtual AbstractLookupcreateLookup (RoutingType routingType=DEFAULT_ROUTING, const BaseOverlayMessage *msg=NULL, const cPacket *findNodeExt=NULL, bool appLookup=false)
 Creates an abstract iterative lookup instance.
virtual void removeLookup (AbstractLookup *lookup)
 Removes the abstract lookup instance.
virtual NodeVectorfindNode (const OverlayKey &key, int numRedundantNodes, int numSiblings, BaseOverlayMessage *msg=NULL)
 Implements the find node call.
virtual void joinForeignPartition (const NodeHandle &node)
 Join another overlay partition with the given node as bootstrap node.
virtual bool handleFailedNode (const TransportAddress &failed)
 Handles a failed node.
virtual void lookupRpc (LookupCall *call)
virtual void nextHopRpc (NextHopCall *call)
void countFindNodeCall (const FindNodeCall *call)
void countFailedNodeCall (const FailedNodeCall *call)
bool internalHandleRpcCall (BaseCallMessage *msg)
 Handles internal rpc requests.
void internalHandleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt)
 Handles rpc responses internal in base classes

void internalHandleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, cPolymorphic *context, int rpcId, const OverlayKey &destKey)
 Handles rpc timeouts internal in base classes

void internalSendRouteRpc (BaseRpcMessage *message, const OverlayKey &destKey, const std::vector< TransportAddress > &sourceRoute, RoutingType routingType)
CompType getThisCompType ()
 Return the component type of this module.
- Protected Member Functions inherited from BaseRpc
void initRpcs ()
 Initializes Remote-Procedure state.
void finishRpcs ()
 Deinitializes Remote-Procedure state.
virtual void internalHandleRpcMessage (BaseRpcMessage *msg)
 Handles incoming rpc messages and delegates them to the corresponding listeners or handlers.
uint32_t sendRouteRpcCall (CompType destComp, const TransportAddress &dest, const OverlayKey &destKey, BaseCallMessage *msg, cPolymorphic *context=NULL, RoutingType routingType=DEFAULT_ROUTING, simtime_t timeout=-1, int retries=0, int rpcId=-1, RpcListener *rpcListener=NULL)
 Routes a Remote-Procedure-Call message to an OverlayKey.
uint32_t sendRouteRpcCall (CompType destComp, const OverlayKey &destKey, BaseCallMessage *msg, cPolymorphic *context=NULL, RoutingType routingType=DEFAULT_ROUTING, simtime_t timeout=-1, int retries=0, int rpcId=-1, RpcListener *rpcListener=NULL)
 Routes a Remote-Procedure-Call message to an OverlayKey.
uint32_t sendRouteRpcCall (CompType destComp, const TransportAddress &dest, BaseCallMessage *msg, cPolymorphic *context=NULL, RoutingType routingType=DEFAULT_ROUTING, simtime_t timeout=-1, int retries=0, int rpcId=-1, RpcListener *rpcListener=NULL)
 Sends a Remote-Procedure-Call message using the overlay's UDP port
This replaces ROUTE_DIRECT calls!
uint32_t sendUdpRpcCall (const TransportAddress &dest, BaseCallMessage *msg, cPolymorphic *context=NULL, simtime_t timeout=-1, int retries=0, int rpcId=-1, RpcListener *rpcListener=NULL)
 Sends a Remote-Procedure-Call message to the underlay

uint32_t sendInternalRpcCall (CompType destComp, BaseCallMessage *msg, cPolymorphic *context=NULL, simtime_t timeout=-1, int retries=0, int rpcId=-1, RpcListener *rpcListener=NULL)
 Sends an internal Remote-Procedure-Call between two tiers

void cancelRpcMessage (uint32_t nonce)
 Cancels a Remote-Procedure-Call.
void cancelAllRpcs ()
 Cancels all RPCs.
void sendRpcResponse (TransportType transportType, CompType destComp, const TransportAddress &dest, const OverlayKey &destKey, BaseCallMessage *call, BaseResponseMessage *response)
 Send Remote-Procedure response message and deletes call message.
void sendRpcResponse (BaseCallMessage *call, BaseResponseMessage *response)
 Send Remote-Procedure response message to UDP and deletes call message.
int pingNode (const TransportAddress &dest, simtime_t timeout=-1, int retries=0, cPolymorphic *context=NULL, const char *caption="PING", RpcListener *rpcListener=NULL, int rpcId=-1, TransportType transportType=INVALID_TRANSPORT)
 ping a node by its TransportAddress
virtual bool handleRpcCall (BaseCallMessage *msg)
 Processes Remote-Procedure-Call invocation messages.
virtual void pingResponse (PingResponse *pingResponse, cPolymorphic *context, int rpcId, simtime_t rtt)
virtual void pingTimeout (PingCall *pingCall, const TransportAddress &dest, cPolymorphic *context, int rpcId)
bool internalHandleMessage (cMessage *msg)
- Protected Member Functions inherited from RpcListener
virtual void handleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt)
 This method is called if an RPC response has been received.
virtual void handleRpcResponse (BaseResponseMessage *msg, const RpcState &rpcState, simtime_t rtt)
 This method is called if an RPC response has been received.
virtual void handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, cPolymorphic *context, int rpcId, const OverlayKey &destKey)
 This method is called if an RPC timeout has been reached.
virtual void handleRpcTimeout (const RpcState &rpcState)
 This method is called if an RPC timeout has been reached.
- Protected Member Functions inherited from BaseTcpSupport
void handleTCPMessage (cMessage *msg)
 Member function to handle incoming TCP messages.
void bindAndListenTcp (int port)
 Member function to bind service to the specified port and listen afterwards.
bool isAlreadyConnected (TransportAddress address)
 Member function to check if the service is already connected.
void establishTcpConnection (TransportAddress address)
 Member function to establish a connection to the specified node.
void sendTcpData (cPacket *msg, TransportAddress address)
 Member function to send TCP data to the specified node.
virtual void handleConnectionEvent (EvCode code, TransportAddress address)
 Member function to handle passive connection events.
virtual void handleDataReceived (TransportAddress address, cPacket *msg, bool urgent)
 Member function to handle incoming data.
virtual void handleIncomingConnection (TransportAddress address)
 Member function to handle newly opened connections.
void closeTcpConnection (TransportAddress address)
 Member function to close an established connection.
void setTcpOut (cGate *gate)
 Member function to set local gate towards the TCP module during init phase.
cGate * getTcpOut ()
 Member function to get local gate towards the TCP module.
- Protected Member Functions inherited from TopologyVis
void initVis (cModule *terminal)

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

Additional Inherited Members

- Protected Types inherited from BaseOverlay
typedef UNORDERED_SET
< AbstractLookup
*, lookupHashFcn,
lookupHashFcn
LookupSet
- Protected Attributes inherited from BaseOverlay
int numAppDataForwarded
 number of forwarded app data packets
int bytesAppDataForwarded
 number of forwarded app data bytes at out-gate
int numAppLookupForwarded
 number of forwarded app lookup packets
int bytesAppLookupForwarded
 number of forwarded app lookup bytes at out-gate
int numMaintenanceForwarded
 number of forwarded maintenance packets
int bytesMaintenanceForwarded
 number of forwarded maintenance bytes at out-gate
int numFindNodeSent
int bytesFindNodeSent
int numFindNodeResponseSent
int bytesFindNodeResponseSent
int numFailedNodeSent
int bytesFailedNodeSent
int numFailedNodeResponseSent
int bytesFailedNodeResponseSent
std::vector< HopDelayRecord * > singleHopDelays
simtime_t creationTime
 simtime when the node has been created
GlobalNodeListglobalNodeList
 pointer to GlobalNodeList in this node
NotificationBoard * notificationBoard
 pointer to NotificationBoard in this node
UnderlayConfiguratorunderlayConfigurator
 pointer to UnderlayConfigurator in this node
BootstrapListbootstrapList
 pointer to the BootstrapList module
GlobalParametersglobalParameters
 pointer to the GlobalParameters module
uint32_t overlayId
 identifies the overlay this node belongs to (used for multiple overlays)
bool debugOutput
 debug output ?
RoutingType defaultRoutingType
bool useCommonAPIforward
 forward messages to applications?
bool collectPerHopDelay
 collect delay for single hops
bool routeMsgAcks
 send ACK when receiving route message
uint32_t recNumRedundantNodes
 numRedundantNodes for recursive routing
bool recordRoute
 record visited hops on route
bool drawOverlayTopology
bool rejoinOnFailure
bool sendRpcResponseToLastHop
 needed by KBR protocols for NAT support
bool dropFindNodeAttack
 if node is malicious, it tries a findNode attack
bool isSiblingAttack
 if node is malicious, it tries a isSibling attack
bool invalidNodesAttack
 if node is malicious, it tries a invalidNode attack
bool dropRouteMessageAttack
 if node is malicious, it drops all received BaseRouteMessages
int localPort
 used UDP-port
int hopCountMax
 maximum hop count
bool measureAuthBlock
 if true, measure the overhead of signatures in rpc messages
bool restoreContext
 if true, a node rejoins with its old nodeId and malicious state
int numDropped
 number of dropped packets
int bytesDropped
 number of dropped bytes
cOutVector delayVector
 statistical output vector for packet-delays
cOutVector hopCountVector
 statistical output vector for hop-counts
States state
IterativeLookupConfiguration iterativeLookupConfig
RecursiveLookupConfiguration recursiveLookupConfig
LookupSet lookups
bool kbr
 set this to true, if the overlay provides KBR services

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 72 of file Nice.cc.

: isRendevouzPoint(false),
isTempPeered(false),
{
/* do nothing at this point of time, OverSim calls initializeOverlay */
} // Nice
oversim::Nice::~Nice ( )
virtual

Definition at line 97 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;
}
} // ~NICE

Member Function Documentation

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

Definition at line 555 of file Nice.cc.

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

{
// Cancel timers involved in structure refinement
/*
if (layer == -1 || layer == 0) {
cancelEvent(maintenanceTimer);
cancelEvent(heartbeatTimer);
}
*/
if (layer > -1)
targetLayer = layer;
else
// Temporary peer with RP for faster data reception
NiceMessage* msg = new NiceMessage("NICE_PEER_TEMPORARY");
msg->setLayer(-1);
msg->setBitLength(NICEMESSAGE_L(msg));
isTempPeered = true;
} // BasicJoinLayer
void oversim::Nice::changeState ( int  toState)
protectedvirtual

changes node state

Parameters
toStatestate to change to

Definition at line 248 of file Nice.cc.

Referenced by handleNiceQueryResponse(), and joinOverlay().

{
switch (toState) {
case INIT:
getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 1, "red");
scheduleAt(simTime() + 1, visualizationTimer);
break;
case JOIN:
/* get rendevouz point */
/* join cluster layer 0 as first node */
return;
}
else {
pollRP(-1);
/* initiate NICE structure joining */
}
break;
case READY:
cancelEvent(heartbeatTimer);
scheduleAt(simTime() + heartbeatInterval, heartbeatTimer);
cancelEvent(maintenanceTimer);
scheduleAt(simTime() + maintenanceInterval, maintenanceTimer);
getParentModule()->getParentModule()->getDisplayString().setTagArg
/* allow only rendevouz point to be bootstrap node */
break;
}
} // changeState
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 2263 of file Nice.cc.

{
bool collisionDetected = false;
//Alternative Detection
leaderHeartbeats.push_back(std::make_pair(hbMsg->getSrcNode(), simTime()));
if (leaderHeartbeats.size() > 3) {
EV << simTime() << "leaderHeartbeats.size() > 3 : " << leaderHeartbeats.size() << endl;
simtime_t predecessor = leaderHeartbeats.at(leaderHeartbeats.size()-2).second;
EV << simTime() << "predecessor : " << predecessor << endl;
if (simTime() < (predecessor + heartbeatInterval)) {
EV << simTime() << "simTime() < (predecessor + heartbeatInterval)" << endl;
if (leaderHeartbeats.at(leaderHeartbeats.size()-2).first != hbMsg->getSrcNode()) {
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()) {
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) {
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;
}
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++) {
}
}
return collisionDetected;
}
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 2150 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)) {
deadTempPeers.push_back(itTempPeer->first);
}
}
std::vector<TransportAddress>::iterator itDead;
for (itDead = deadTempPeers.begin(); itDead != deadTempPeers.end(); ++itDead) {
tempPeers.erase(*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)) {
EV << simTime() << " : " << thisNode.getIp() << " : PEER TIMED OUT! : " << itPeer->first << endl;
EV << "Activity : " << itPeer->second->getActivity() << endl;
}
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);
}
}
} // cleanPeers
void oversim::Nice::ClusterMerge ( int  layer)
private

Definition at line 2868 of file Nice.cc.

Referenced by mergeNeeded().

{
ASSERT(layer < maxLayers - 1);
ASSERT(clusters[layer].getLeader() == thisNode);
simtime_t min_delay = 999;
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);
for (int j=0; j<clusters[layer+1].getSize(); 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";
}
} // ClusterMerge
void oversim::Nice::ClusterMergeRequest ( const TransportAddress node,
int  layer 
)
private

Definition at line 2936 of file Nice.cc.

Referenced by ClusterMerge(), and handleNiceForceMerge().

{
ASSERT(clusters[layer+1].contains(thisNode));
ASSERT(!clusters[layer+1].getLeader().isUnspecified());
NiceClusterMerge* msg = new NiceClusterMerge("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));
}
msg->setNewClusterLeader(clusters[layer+1].getLeader());
msg->setBitLength(NICECLUSTERMERGE_L(msg));
getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 0, "block/circle_vs");
sendMessageToUDP(node, msg);
} // ClusterMergeRequest
void oversim::Nice::ClusterSplit ( int  layer)
private

Definition at line 2621 of file Nice.cc.

Referenced by splitNeeded().

{
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;
simtime_t min_delay = 999;
for (int i=0; i<cluster.getSize(); i++) {
/* Delete all arrows in visualization */
/* 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;
}
// 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;
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) {
}
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].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);
}
//update arrows
if (pimp)
} // ClusterSplit
std::pair< TransportAddress, simtime_t > oversim::Nice::findCenter ( TaSet  cluster,
bool  allowRandom = false 
)
private

Definition at line 2971 of file Nice.cc.

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

{
return findCenter(cluster.begin(), cluster.end(), allowRandom);
}
std::pair< TransportAddress, simtime_t > oversim::Nice::findCenter ( std::vector< TransportAddress cluster,
bool  allowRandom = false 
)
private

Definition at line 2980 of file Nice.cc.

{
return findCenter(cluster.begin(), cluster.end(), allowRandom);
}
std::pair< TransportAddress, simtime_t > oversim::Nice::findCenter ( const NiceCluster cluster,
bool  allowRandom = false 
)
private

Definition at line 2989 of file Nice.cc.

{
return findCenter(cluster.begin(), cluster.end(), allowRandom);
}
template<class ConstIter >
std::pair< TransportAddress, simtime_t > oversim::Nice::findCenter ( ConstIter  begin,
ConstIter  end,
bool  allowRandom = false 
)
private

Definition at line 2998 of file Nice.cc.

{
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);
} // findCenter
void oversim::Nice::finishOverlay ( )
virtual

collects statistical data in derived class

Reimplemented from BaseOverlay.

Definition at line 521 of file Nice.cc.

{
}
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);
} // finishOverlay
int oversim::Nice::getHighestLayer ( )
private

Definition at line 1642 of file Nice.cc.

Referenced by changeState(), ClusterMerge(), ClusterSplit(), getHighestLeaderLayer(), gracefulLeave(), handleNiceLeaderHeartbeat(), handleNicePingProbeResponse(), 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;
}
} // getHighestLayer
int oversim::Nice::getHighestLeaderLayer ( )
private

Definition at line 1628 of file Nice.cc.

Referenced by gracefulLeave(), handleNiceClusterMergeRequest(), handleNicePollRp(), handleNiceQuery(), maintenance(), mergeNeeded(), and splitNeeded().

{
int layer = getHighestLayer();
if (!clusters[layer].getLeader().isUnspecified() && clusters[layer].getLeader() == thisNode) {
return layer;
}
else if (layer == -1) {
return -1;
}
else {
return layer - 1;
}
} // getHighestLeaderLayer
simtime_t oversim::Nice::getMaxDistance ( TransportAddress  member,
const std::set< TransportAddress > &  neighbors 
)
private

Definition at line 3075 of file Nice.cc.

Referenced by findCenter(), and maintenance().

{
return getMaxDistance(member, neighbors.begin(), neighbors.end());
} // getMaxDistance
template<class ConstIter >
simtime_t oversim::Nice::getMaxDistance ( TransportAddress  member,
ConstIter  neighborsBegin,
ConstIter  neighborsEnd 
)
private

Definition at line 3031 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;
} // getMaxDistance
simtime_t oversim::Nice::getMeanDistance ( std::set< TransportAddress neighbors)
private

Definition at line 3083 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;
}
} // getMeanDistance
void oversim::Nice::gracefulLeave ( short  bottomLayer)
private

Definition at line 3234 of file Nice.cc.

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

{
EV << simTime() << " : " << thisNode.getIp() << " : gracefulLeave()" << endl;
int layer = getHighestLayer();
ASSERT(layer >= bottomLayer);
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);
}
}
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;
}
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;
} // gracefulLeave
void oversim::Nice::handleAppMessage ( cMessage *  msg)
virtual

Processes "timer" self-messages.

Parameters
msgA self-message Processes non-commonAPI messages
msgnon-commonAPIMessage

Reimplemented from BaseOverlay.

Definition at line 3300 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->setLayer(-1);
niceMsg->setSrcNode(thisNode);
niceMsg->setLastHop(thisNode);
niceMsg->setHopCount(0);
niceMsg->setBitLength(NICEMULTICAST_L(niceMsg));
niceMsg->encapsulate(multicastMsg);
// 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;
}
} // handleAppMessage
void oversim::Nice::handleNiceClusterMergeRequest ( NiceClusterMerge mergeMsg)
private

Definition at line 755 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());
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) {
}
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)
delete mergeMsg;
EV << simTime() << " : " << thisNode.getIp() << " : NICE_CLUSTER_MERGE_REQUEST finished" << endl;
}
void oversim::Nice::handleNiceForceMerge ( NiceMessage msg)
private

Definition at line 862 of file Nice.cc.

Referenced by handleUDPMessage().

{
delete msg;
}
void oversim::Nice::handleNiceHeartbeat ( NiceHeartbeat msg)
private

Definition at line 869 of file Nice.cc.

Referenced by handleUDPMessage().

{
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;
EV << simTime() << " : " << thisNode.getIp() << " : handleHeartbeat() finished. " << endl;
}
void oversim::Nice::handleNiceJoinCluster ( NiceMessage joinMsg)
private

Definition at line 1282 of file Nice.cc.

Referenced by handleUDPMessage().

{
EV << simTime() << " : " << thisNode.getIp() << " : handleNiceJoinCluster()" << endl;
short layer = joinMsg->getLayer();
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 {
/* 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 */
if (pimp)
sendHeartbeatTo(joinMsg->getSrcNode(), layer);
}
}
else {
EV << "Leader unspecified. Ignoring request." << endl;
}
EV << simTime() << " : " << thisNode.getIp() << " : handleNiceJoinCluster() finished." << endl;
delete joinMsg;
} // handleNiceJoinCluster
void oversim::Nice::handleNiceJoineval ( NiceMessage msg)
private

Definition at line 1348 of file Nice.cc.

Referenced by handleUDPMessage().

{
NiceMessage* responseMsg = new NiceMessage("NICE_JOINEVAL_RESPONSE");
responseMsg->setSrcNode(thisNode);
responseMsg->setLayer(msg->getLayer());
responseMsg->setBitLength(NICEMESSAGE_L(responseMsg));
sendMessageToUDP(msg->getSrcNode(), responseMsg);
delete msg;
}
void oversim::Nice::handleNiceJoinevalResponse ( NiceMessage msg)
private

Definition at line 1362 of file Nice.cc.

Referenced by handleUDPMessage().

{
if (evalLayer > 0 && evalLayer == msg->getLayer()) {
Query(msg->getSrcNode(), msg->getLayer()-1);
}
else {
Query(tempResolver, msg->getLayer() - 1);
}
evalLayer = -1;
}
delete msg;
}
void oversim::Nice::handleNiceLeaderHeartbeat ( NiceLeaderHeartbeat lhbMsg)
private

Definition at line 928 of file Nice.cc.

Referenced by handleUDPMessage().

{
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());
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) {
EV << "Leader collision...";
if (lhbMsg->getSrcNode() < thisNode) {
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) {
}
clusters[lhbMsg->getLayer()].add(lhbMsg->getSrcNode());
clusters[lhbMsg->getLayer()].setLeader(lhbMsg->getSrcNode());
LeaderTransfer(lhbMsg->getLayer(), lhbMsg->getSrcNode());
}
else {
EV << "...remaining leader." << endl;
delete lhbMsg;
return;
}
}
else if (!clusters[lhbMsg->getLayer()].getLeader().isUnspecified() &&
clusters[lhbMsg->getLayer()].getLeader() != lhbMsg->getSrcNode()) {
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) {
}
}
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)
if (lhbMsg->getSupercluster_membersArraySize() > 0) {
for (TaSet::iterator itn = clusters[lhbMsg->getLayer() + 1].begin(); itn != clusters[lhbMsg->getLayer() + 1].end(); ++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));
}
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));
}
}
EV << simTime() << " : " << thisNode.getIp() << " : handleNiceLeaderHeartbeat() finished. " << endl;
delete lhbMsg;
}
void oversim::Nice::handleNiceLeaderHeartbeatOrTransfer ( NiceMessage msg)
private
void oversim::Nice::handleNiceLeaderTransfer ( NiceLeaderHeartbeat transferMsg)
private

Definition at line 1117 of file Nice.cc.

Referenced by handleUDPMessage().

{
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) {
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) {
}
clusters[transferMsg->getLayer()].clear();
clusters[transferMsg->getLayer()].add(thisNode);
clusters[transferMsg->getLayer()].setLeader(thisNode);
for (unsigned int i=0; i<transferMsg->getMembersArraySize(); i++) {
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) {
}
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++) {
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)
EV << simTime() << " : " << thisNode.getIp() << " : handleNiceLeaderTransfer() finished. " << endl;
delete transferMsg;
}
void oversim::Nice::handleNiceMulticast ( NiceMulticastMessage multicastMsg)
private

Definition at line 1385 of file Nice.cc.

Referenced by handleUDPMessage().

{
RECORD_STATS(++numReceived; totalReceivedBytes += multicastMsg->getByteLength());
/* If it is mine, count */
if (multicastMsg->getSrcNode() == thisNode) {
}
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");
}
}
delete multicastMsg;
}
void oversim::Nice::handleNicePeerTemporary ( NiceMessage msg)
private

Definition at line 1416 of file Nice.cc.

Referenced by handleUDPMessage().

{
// Add node to tempPeers
tempPeers.insert(std::make_pair(msg->getSrcNode(), simTime()));
delete msg;
}
void oversim::Nice::handleNicePeerTemporaryRelease ( NiceMessage msg)
private

Definition at line 1424 of file Nice.cc.

Referenced by handleUDPMessage().

{
// Remove node from tempPeers
tempPeers.erase(msg->getSrcNode());
delete msg;
}
void oversim::Nice::handleNicePingProbe ( NiceMessage msg)
private

Definition at line 1433 of file Nice.cc.

Referenced by handleUDPMessage().

{
// Only answer if I am part of requested layer
NiceMessage* probe = new NiceMessage("NICE_PING_PROBE");
probe->setLayer(msg->getLayer());
probe->setBitLength(NICEMESSAGE_L(probe));
sendMessageToUDP(msg->getSrcNode(), probe);
}
else {
//Do nothing
}
delete msg;
}
void oversim::Nice::handleNicePingProbeResponse ( NiceMessage msg)
private

Definition at line 1457 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();
}
}
delete msg;
}
void oversim::Nice::handleNicePollRp ( NiceMessage msg)
private

Definition at line 1478 of file Nice.cc.

Referenced by handleUDPMessage().

{
NiceMessage* response = new NiceMessage("NICE_POLL_RP_RESPONSE");
response->setSrcNode(thisNode);
response->setBitLength(NICEMESSAGE_L(response));
sendMessageToUDP(msg->getSrcNode(), response);
}
delete msg;
}
void oversim::Nice::handleNicePollRpResponse ( NiceMessage msg)
private
void oversim::Nice::handleNiceQuery ( NiceMessage queryMsg)
private

Definition at line 623 of file Nice.cc.

Referenced by handleUDPMessage().

{
EV << simTime() << " : " << thisNode.getIp() << " : handleNiceQuery()" << endl;
short layer = queryMsg->getLayer();
if (layer >= maxLayers) {
EV << "Layer " << layer << " >= max layer " << maxLayers << " ! Returning." << endl;
delete queryMsg;
return;
}
EV << " layer before: " << layer << endl;
if (layer > getHighestLeaderLayer()) {
EV << " getHighestLeaderLayer(): " << getHighestLeaderLayer() << " ! RP self-promoting." << endl;
for (int i = getHighestLeaderLayer() + 1; i <= layer; ++i) {
}
}
else {
EV << " getHighestLeaderLayer(): " << getHighestLeaderLayer() << " ! Returning." << endl;
delete queryMsg;
return;
}
}
if (layer < 0) {
/* If layer is < 0, response with highest layer I am leader of */
EV << " I am RP." << endl;
}
else {
EV << " I am not RP. Return." << endl;
if (pimp) {
/* forward to Rendevouz Point */
NiceMessage* dup = static_cast<NiceMessage*>(queryMsg->dup());
}
delete queryMsg;
return;
}
}
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);
}
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->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));
EV << " Response: " << i << " : " << clusters[layer].get(i) << endl;
j++;
}
}
response->setBitLength(NICEMEMBERMESSAGE_L(response));
sendMessageToUDP(queryMsg->getSrcNode(), response);
EV << " Sent response to: " << queryMsg->getSrcNode() << endl;
EV << simTime() << " : " << thisNode.getIp() << " : handleNiceQuery() finished." << endl;
delete queryMsg;
} // handleNiceQuery
void oversim::Nice::handleNiceQueryResponse ( NiceMemberMessage queryRspMsg)
private

Definition at line 1506 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);
}
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->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();
}
delete queryRspMsg;
} // handleNiceQueryResponse
void oversim::Nice::handleNiceRemove ( NiceMessage msg)
private

Definition at line 1572 of file Nice.cc.

Referenced by handleUDPMessage().

{
EV << simTime() << " : " << thisNode.getIp() << " : NICE_REMOVE" << endl;
if (msg->getSrcNode() == thisNode) {
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;
}
}
}
EV << simTime() << " : " << thisNode.getIp() << " : removing " << msg->getSrcNode() << " from layer " << layer << endl;
if (clusters[msg->getLayer()].getLeader() == thisNode) {
// check prevents visualization arrows to be deleted by error
if (clusters[msg->getLayer()].contains(msg->getSrcNode())) {
}
}
}
EV << simTime() << " : " << thisNode.getIp() << " : NICE_REMOVE finished." << endl;
delete msg;
}
void oversim::Nice::handleNodeLeaveNotification ( )
protectedvirtual

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

Reimplemented from BaseOverlay.

Definition at line 236 of file Nice.cc.

{
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

Reimplemented from BaseRpc.

Definition at line 320 of file Nice.cc.

{
if (msg->isName("visualizationTimer")) {
scheduleAt(simTime() + 1, visualizationTimer);
}
else if (msg->isName("heartbeatTimer")) {
scheduleAt(simTime() + heartbeatInterval, heartbeatTimer);
}
else if (msg->isName("maintenanceTimer")) {
cancelEvent(maintenanceTimer);
scheduleAt(simTime() + maintenanceInterval, maintenanceTimer);
}
else if (msg->isName("queryTimer")) {
}
else {
}
}
else if (msg->isName("rpPollTimer")) {
pollRP(-1);
}
} // handleTimerEvent
void oversim::Nice::handleUDPMessage ( BaseOverlayMessage msg)
virtual

Processes messages from underlay.

Parameters
msgMessage from UDP

Reimplemented from BaseOverlay.

Definition at line 368 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;
queryRspMsg = check_and_cast<NiceMemberMessage*>(niceMsg);
break;
break;
handleNicePollRp(niceMsg);
break;
break;
handleNiceHeartbeat(check_and_cast<NiceHeartbeat*>(niceMsg));
break;
handleNiceLeaderHeartbeat(check_and_cast<NiceLeaderHeartbeat*>(niceMsg));
break;
handleNiceLeaderTransfer(check_and_cast<NiceLeaderHeartbeat*>(niceMsg));
break;
break;
break;
handleNiceRemove(niceMsg);
break;
break;
break;
break;
break;
break;
mergeMsg = check_and_cast<NiceClusterMerge*>(niceMsg);
break;
multicastMsg = check_and_cast<NiceMulticastMessage*>(msg);
handleNiceMulticast(multicastMsg);
break;
default:
delete niceMsg;
}
}
else {
delete msg;
}
} // handleUDPMessage
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
stagethe init stage

Reimplemented from BaseOverlay.

Definition at line 122 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) {
}
}
/* 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");
/* 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;
// add some watches
WATCH(thisNode);
WATCH(evalLayer);
WATCH(query_start);
WATCH_MAP(tempPeers);
WATCH(numJoins);
WATCH(numReceived);
WATCH(numHeartbeat);
} // initializeOverlay
void oversim::Nice::JoinCluster ( const TransportAddress leader,
short  layer 
)
private

Definition at line 1670 of file Nice.cc.

Referenced by handleNiceLeaderTransfer(), handleNiceQueryResponse(), and maintenance().

{
EV << simTime() << " : " << thisNode.getIp() << " : JoinCluster()" << endl;
NiceMessage* msg = new NiceMessage("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 */
/* 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->setLayer(-1);
msg->setBitLength(NICEMESSAGE_L(msg));
isTempPeered = false;
}
EV << simTime() << " : " << thisNode.getIp() << " : JoinCluster() finished." << endl;
} // JoinCluster
void oversim::Nice::joinOverlay ( )
protectedvirtual

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 230 of file Nice.cc.

{
} // joinOverlay
void oversim::Nice::LeaderTransfer ( int  layer,
TransportAddress  leader,
TaSet  cluster,
TransportAddress  sc_leader,
TaSet  superCluster 
)
private

Definition at line 3135 of file Nice.cc.

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

{
NiceLeaderHeartbeat* msg = new NiceLeaderHeartbeat("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);
} // LeaderTransfer
void oversim::Nice::LeaderTransfer ( int  layer,
TransportAddress  leader 
)
private

Definition at line 3171 of file Nice.cc.

{
ASSERT(clusters[layer].contains(leader));
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)
else
LeaderTransfer(layer, leader, cluster, clusters[layer + 1].getLeader(), TaSet(clusters[layer + 1].begin(), clusters[layer+1].end()));
}
void oversim::Nice::maintenance ( )
private

Definition at line 2352 of file Nice.cc.

Referenced by handleTimerEvent().

{
// care for structure connection timer
EV << "No RendevouzPoint! " << endl;
}
int highestLayer = getHighestLayer();
bool leaderDied = false;
clusters[highestLayer].isLeaderConfirmed();
TransportAddress newLeader;
TransportAddress oldLeader = clusters[highestLayer].getLeader();
// 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;
newLeader = findCenter(clusters[highestLayer]).first;
}
if (leaderDied && RendevouzPoint != oldLeader) {
clusters[highestLayer].setLeader(newLeader);
if (newLeader == thisNode) {
clusters[highestLayer + 1].add(newLeader);
BasicJoinLayer(highestLayer + 1);
}
else {
LeaderTransfer(highestLayer, newLeader);
}
}
pollRP(-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) {
}
}
}
// 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) {
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;
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
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
}
}
// Try to find better leader.
for (int i = getHighestLeaderLayer(); i >= 0; i--) {
if (clusters[i].getSize() > 1 && clusters[i].isLeaderConfirmed()) {
bool allDistancesKnown = true;
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) {
EV << "Complete distance knowledge available." << endl;
// Perform check for better cluster leader
TransportAddress new_leader = findCenter(clusters[i]).first;
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())) {
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++) {
}
LeaderTransfer(i, new_leader);
getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 0, "block/circle_vs");
}
}
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
} // maintenance
bool oversim::Nice::mergeNeeded ( )
private

Merges clusters if needed.

mergeNeeded

Returns true if a merge was made, false otherwise.

Definition at line 2229 of file Nice.cc.

Referenced by maintenance().

{
// 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;
}
}
}
return false;
}
void oversim::Nice::pollRP ( int  layer)
private

Definition at line 3467 of file Nice.cc.

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

{
EV << simTime() << " : " << thisNode.getIp() << " : pollRP()" << endl;
NiceMessage* msg = new NiceMessage("NICE_POLL_RP");
msg->setLayer(layer);
msg->setBitLength(NICEMESSAGE_L(msg));
cancelEvent(rpPollTimer);
scheduleAt(simTime() + rpPollTimerInterval, rpPollTimer);
EV << simTime() << " : " << thisNode.getIp() << " : pollRP() finished." << endl;
} // pollRP
void oversim::Nice::Query ( const TransportAddress node,
short  layer 
)
private

Definition at line 594 of file Nice.cc.

Referenced by BasicJoinLayer(), handleNiceJoinevalResponse(), handleNiceQueryResponse(), and handleTimerEvent().

{
EV << simTime() << " : " << thisNode.getIp() << " : Query()" << endl;
NiceMessage* msg = new NiceMessage("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);
EV << simTime() << " : " << thisNode.getIp() << " : Query() finished." << endl;
} // Query
void oversim::Nice::Remove ( int  layer)
private

Definition at line 3190 of file Nice.cc.

Referenced by gracefulLeave(), and maintenance().

{
EV << simTime() << " : " << thisNode.getIp() << " : Remove()" << endl;
int highestLayer = getHighestLayer();
ASSERT(layer <= highestLayer);
NiceMessage* msg = new NiceMessage("NICE_REMOVE");
msg->setLayer(layer);
msg->setBitLength(NICEMESSAGE_L(msg));
sendMessageToUDP(clusters[layer].getLeader(), msg);
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]);
}
}
}
EV << simTime() << " : " << thisNode.getIp() << " : Remove() finished." << endl;
} // Remove
void oversim::Nice::sendDataToOverlay ( NiceMulticastMessage appMsg)
private

Definition at line 3365 of file Nice.cc.

Referenced by handleAppMessage(), and handleNiceMulticast().

{
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 );
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());
sendMessageToUDP(it->first, dup);
it++;
}
delete appMsg;
} // sendDataToOverlay
void oversim::Nice::sendHeartbeats ( )
private

Definition at line 1757 of file Nice.cc.

Referenced by ClusterSplit(), handleNiceClusterMergeRequest(), handleNiceLeaderTransfer(), 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) {
/* Build heartbeat message with info on all current members */
NiceLeaderHeartbeat* msg = new NiceLeaderHeartbeat("NICE_LEADERHEARTBEAT");
msg->setLayer(i);
msg->setOne_hop_distance(simTime().dbl());
msg->setK(k);
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());
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->setLayer(i);
msg->setOne_hop_distance(simTime().dbl());
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->setBitLength(NICEMESSAGE_L(msg));
for (int i=0; i<clusters[getHighestLayer()+1].getSize(); i++) {
NiceMessage* dup = static_cast<NiceMessage*>(msg->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;
}
} // sendHeartbeats
void oversim::Nice::sendHeartbeatTo ( const TransportAddress node,
int  layer 
)
private

Definition at line 1999 of file Nice.cc.

Referenced by handleNiceJoinCluster().

{
if (clusters[layer].getLeader() == thisNode) {
/* Build heartbeat message with info on all current members */
NiceLeaderHeartbeat* msg = new NiceLeaderHeartbeat("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->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);
}
} // sendHeartbeatTo
void oversim::Nice::sendRemoveTo ( const TransportAddress node,
int  layer 
)
private

sendRemoveTo

Definition at line 2135 of file Nice.cc.

Referenced by handleNiceLeaderHeartbeat().

{
NiceMessage* msg = new NiceMessage("NICE_REMOVE");
msg->setLayer(layer);
msg->setBitLength(NICEMESSAGE_L(msg));
sendMessageToUDP(node, msg);
} // sendRemoveTo
bool oversim::Nice::splitNeeded ( )
private

Splits clusters if needed.

splitNeeded

Returns true if a split was made, false otherwise.

Definition at line 2208 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 &&
(i == maxLayers - 1 || clusters[i + 1].getSize() == 0 || clusters[i + 1].isLeaderConfirmed())) {
splitMade = true;
}
}
return splitMade;
} // splitNeeded
void oversim::Nice::updateVisualization ( )
private

Definition at line 3420 of file Nice.cc.

Referenced by ClusterSplit(), handleNiceRemove(), and handleTimerEvent().

{
EV << simTime() << " : " << thisNode.getIp() << " : updateVisualization" << endl;
/* Update node symbol */
getParentModule()->getParentModule()
->getDisplayString().setTagArg("i2", 0, "block/circle_vs");
getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 0, "block/star_vs");
}
/* Update node color */
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++) {
EV << "draw to: " << clusters[i].get(j) << endl;
}
}
}
}
} // updateVisualization

Friends And Related Function Documentation

Member Data Documentation

double oversim::Nice::CLUSTERLEADERBOUND
private

Definition at line 186 of file Nice.h.

Referenced by initializeOverlay(), and maintenance().

double oversim::Nice::CLUSTERLEADERCOMPAREDIST
private

Definition at line 187 of file Nice.h.

Referenced by initializeOverlay(), and maintenance().

int oversim::Nice::clusterrefinement
private

Definition at line 146 of file Nice.h.

Referenced by initializeOverlay(), and maintenance().

int oversim::Nice::debug_heartbeats
private
int oversim::Nice::debug_join
private

Definition at line 149 of file Nice.h.

Referenced by finishOverlay(), handleNiceJoinCluster(), initializeOverlay(), and JoinCluster().

int oversim::Nice::debug_peertimeouts
private

Definition at line 150 of file Nice.h.

Referenced by cleanPeers(), and initializeOverlay().

int oversim::Nice::debug_queries
private

Definition at line 152 of file Nice.h.

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

int oversim::Nice::debug_removes
private

Definition at line 151 of file Nice.h.

Referenced by handleNiceRemove(), initializeOverlay(), and Remove().

int oversim::Nice::debug_visualization
private

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 handleNiceJoinevalResponse(), handleNiceQueryResponse(), and initializeOverlay().

simtime_t oversim::Nice::first_HB
private

Definition at line 138 of file Nice.h.

TransportAddress oversim::Nice::first_leader
private

Definition at line 139 of file Nice.h.

Referenced by initializeOverlay().

simtime_t oversim::Nice::heartbeatInterval
private
cMessage* oversim::Nice::heartbeatTimer
private

Definition at line 115 of file Nice.h.

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

bool oversim::Nice::isTempPeered
private

Definition at line 184 of file Nice.h.

Referenced by BasicJoinLayer(), and JoinCluster().

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
std::vector<std::pair<TransportAddress, simtime_t> > oversim::Nice::leaderHeartbeats
private

Definition at line 143 of file Nice.h.

Referenced by checkLeaderHeartbeatsForCollisions().

simtime_t oversim::Nice::maintenanceInterval
private

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(), JoinCluster(), and ~Nice().

int oversim::Nice::numForward
private

Definition at line 208 of file Nice.h.

Referenced by finishOverlay(), and handleNiceMulticast().

int oversim::Nice::numHeartbeat
private

Definition at line 216 of file Nice.h.

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

int oversim::Nice::numInconsistencies
private

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(), handleNiceJoinCluster(), and initializeOverlay().

int oversim::Nice::numOwnMessagesReceived
private

Definition at line 202 of file Nice.h.

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

int oversim::Nice::numPeerTimeouts
private

Definition at line 196 of file Nice.h.

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

int oversim::Nice::numQueryTimeouts
private

Definition at line 194 of file Nice.h.

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

int oversim::Nice::numReceived
private

Definition at line 212 of file Nice.h.

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

int oversim::Nice::numStructurePartitions
private

Definition at line 200 of file Nice.h.

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

int oversim::Nice::numTempPeerTimeouts
private

Definition at line 198 of file Nice.h.

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

double oversim::Nice::peerTimeoutHeartbeats
private

Definition at line 130 of file Nice.h.

Referenced by cleanPeers(), and initializeOverlay().

TransportAddress oversim::Nice::polledRendevouzPoint
private

Definition at line 165 of file Nice.h.

Referenced by handleNicePollRpResponse(), handleTimerEvent(), initializeOverlay(), and pollRP().

simtime_t oversim::Nice::query_compare
private

Definition at line 174 of file Nice.h.

Referenced by handleNiceJoinevalResponse(), and handleNiceQueryResponse().

simtime_t oversim::Nice::query_start
private
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 handleNiceQueryResponse(), initializeOverlay(), Query(), and ~Nice().

cMessage* oversim::Nice::rpPollTimer
private

Definition at line 127 of file Nice.h.

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

simtime_t oversim::Nice::rpPollTimerInterval
private

Definition at line 128 of file Nice.h.

Referenced by initializeOverlay(), and pollRP().

double oversim::Nice::SC_MIN_OFFSET
private

Definition at line 189 of file Nice.h.

Referenced by initializeOverlay(), and maintenance().

double oversim::Nice::SC_PROC_DISTANCE
private

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.

TransportAddress oversim::Nice::second_leader
private

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(), and handleNiceQueryResponse().

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

Definition at line 171 of file Nice.h.

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

int oversim::Nice::totalForwardBytes
private

Definition at line 210 of file Nice.h.

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

int oversim::Nice::totalHeartbeatBytes
private

Definition at line 218 of file Nice.h.

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

int oversim::Nice::totalReceivedBytes
private

Definition at line 214 of file Nice.h.

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

double oversim::Nice::totalSCMinCompare
private

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: