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

oversim::Chord Class Reference

Chord overlay module. More...

#include <Chord.h>

Inheritance diagram for oversim::Chord:
BaseOverlay ProxListener BaseRpc BaseTcpSupport TopologyVis RpcListener oversim::Koorde

List of all members.

Public Member Functions

 Chord ()
virtual ~Chord ()
virtual void initializeOverlay (int stage)
virtual void handleTimerEvent (cMessage *msg)
virtual void handleUDPMessage (BaseOverlayMessage *msg)
virtual void recordOverlaySentStats (BaseOverlayMessage *msg)
virtual void finishOverlay ()
OverlayKey distance (const OverlayKey &x, const OverlayKey &y, bool useAlternative=false) const
virtual void updateTooltip ()
 updates information shown in tk-environment
void proxCallback (const TransportAddress &node, int rpcId, cPolymorphic *contextPointer, Prox prox)

Protected Member Functions

virtual void changeState (int toState)
 changes node state
virtual void handleJoinTimerExpired (cMessage *msg)
 handle a expired join timer
virtual void handleStabilizeTimerExpired (cMessage *msg)
 handle a expired stabilize timer
virtual void handleFixFingersTimerExpired (cMessage *msg)
 handle a expired fix_fingers timer
virtual void handleNewSuccessorHint (ChordMessage *chordMsg)
 handle a received NEWSUCCESSORHINT message
virtual NodeVectorclosestPreceedingNode (const OverlayKey &key)
 looks up the finger table and returns the closest preceeding node.
virtual void findFriendModules ()
 Assigns the finger table and successor list module to our reference.
virtual void initializeFriendModules ()
 initializes finger table and successor list
virtual bool handleRpcCall (BaseCallMessage *msg)
NodeVectorfindNode (const OverlayKey &key, int numRedundantNodes, int numSiblings, BaseOverlayMessage *msg)
virtual void joinOverlay ()
virtual void joinForeignPartition (const NodeHandle &node)
virtual bool isSiblingFor (const NodeHandle &node, const OverlayKey &key, int numSiblings, bool *err)
int getMaxNumSiblings ()
int getMaxNumRedundantNodes ()
void rpcFixfingers (FixfingersCall *call)
 Fixfingers Remote-Procedure-Call.
virtual void rpcJoin (JoinCall *call)
 Join Remote-Procedure-Call.
virtual void rpcNotify (NotifyCall *call)
 NOTIFY Remote-Procedure-Call.
void rpcStabilize (StabilizeCall *call)
 STABILIZE Remote-Procedure-Call.
virtual void handleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt)
virtual void handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, cPolymorphic *context, int rpcId, const OverlayKey &destKey)
virtual void pingResponse (PingResponse *pingResponse, cPolymorphic *context, int rpcId, simtime_t rtt)
virtual void pingTimeout (PingCall *pingCall, const TransportAddress &dest, cPolymorphic *context, int rpcId)
virtual void handleRpcJoinResponse (JoinResponse *joinResponse)
virtual void handleRpcNotifyResponse (NotifyResponse *notifyResponse)
virtual void handleRpcStabilizeResponse (StabilizeResponse *stabilizeResponse)
virtual void handleRpcFixfingersResponse (FixfingersResponse *fixfingersResponse, double rtt=-1)
virtual bool handleFailedNode (const TransportAddress &failed)

Protected Attributes

int joinRetry
int stabilizeRetry
 // retries before neighbor considered failed
double joinDelay
double stabilizeDelay
 stabilize interval (secs)
double fixfingersDelay
double checkPredecessorDelay
int successorListSize
bool aggressiveJoinMode
 use modified (faster) JOIN protocol
bool extendedFingerTable
unsigned int numFingerCandidates
bool proximityRouting
bool memorizeFailedSuccessor
bool newChordFingerTable
bool mergeOptimizationL1
bool mergeOptimizationL2
bool mergeOptimizationL3
bool mergeOptimizationL4
cMessage * join_timer
cMessage * stabilize_timer
cMessage * fixfingers_timer
cMessage * checkPredecessor_timer
int joinCount
int stabilizeCount
int fixfingersCount
int notifyCount
int newsuccessorhintCount
int joinBytesSent
int stabilizeBytesSent
int notifyBytesSent
int fixfingersBytesSent
int newsuccessorhintBytesSent
int keyLength
 length of an overlay key in bits
int missingPredecessorStabRequests
 missing StabilizeCall msgs
NodeHandle predecessorNode
 predecessor of this node
TransportAddress bootstrapNode
 node used to bootstrap
ChordFingerTablefingerTable
 pointer to this node's finger table
ChordSuccessorListsuccessorList
 pointer to this node's successor list

Private Attributes

TransportAddress failedSuccessor

Friends

class ChordSuccessorList
class ChordFingerTable

Detailed Description

Chord overlay module.

Implementation of the Chord KBR overlay as described in "Chord: A Scalable Peer-to-Peer Lookup Protocol for Inetnet Applications" by I. Stoica et al. published in Transactions on Networking.

Author:
Markus Mauch, Ingmar Baumgart
See also:
BaseOverlay, ChordFingerTable, ChordSuccessorList

Definition at line 47 of file Chord.h.


Constructor & Destructor Documentation

oversim::Chord::Chord (  ) 

Definition at line 38 of file Chord.cc.

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

Definition at line 116 of file Chord.cc.

{
    // destroy self timer messages
    cancelAndDelete(join_timer);
    cancelAndDelete(stabilize_timer);
    cancelAndDelete(fixfingers_timer);
    cancelAndDelete(checkPredecessor_timer);


Member Function Documentation

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

changes node state

Parameters:
toState state to change to

Reimplemented in oversim::Koorde.

Definition at line 151 of file Chord.cc.

Referenced by handleJoinTimerExpired(), handleRpcJoinResponse(), and joinOverlay().

{
    //
    // Defines tasks to be executed when a state change occurs.
    //

    switch (toState) {
    case INIT:
        state = INIT;

        setOverlayReady(false);

        // initialize predecessor pointer
        predecessorNode = NodeHandle::UNSPECIFIED_NODE;

        // initialize finger table and successor list
        initializeFriendModules();

        updateTooltip();

        // debug message
        if (debugOutput) {
            EV << "[Chord::changeState() @ " << thisNode.getIp()
            << " (" << thisNode.getKey().toString(16) << ")]\n"
            << "    Entered INIT stage"
            << endl;
        }

        getParentModule()->getParentModule()->bubble("Enter INIT state.");
        break;

    case BOOTSTRAP:
        state = BOOTSTRAP;

        // initiate bootstrap process
        cancelEvent(join_timer);
        // workaround: prevent notificationBoard from taking
        // ownership of join_timer message
        take(join_timer);
        scheduleAt(simTime(), join_timer);

        // debug message
        if (debugOutput) {
            EV << "[Chord::changeState() @ " << thisNode.getIp()
            << " (" << thisNode.getKey().toString(16) << ")]\n"
            << "    Entered BOOTSTRAP stage"
            << endl;
        }
        getParentModule()->getParentModule()->bubble("Enter BOOTSTRAP state.");

        // find a new bootstrap node and enroll to the bootstrap list
        bootstrapNode = bootstrapList->getBootstrapNode();

        // is this the first node?
        if (bootstrapNode.isUnspecified()) {
            // create new cord ring
            assert(predecessorNode.isUnspecified());
            bootstrapNode = thisNode;
            changeState(READY);
            updateTooltip();
        }
        break;

    case READY:
        state = READY;

        setOverlayReady(true);

        // initiate stabilization protocol
        cancelEvent(stabilize_timer);
        scheduleAt(simTime() + stabilizeDelay, stabilize_timer);

        // initiate finger repair protocol
        cancelEvent(fixfingers_timer);
        scheduleAt(simTime() + fixfingersDelay,
                   fixfingers_timer);

        // initiate predecessor check
        cancelEvent(checkPredecessor_timer);
        if (checkPredecessorDelay > 0) {
            scheduleAt(simTime() + checkPredecessorDelay,
                       checkPredecessor_timer);
        }

        // debug message
        if (debugOutput) {
            EV << "[Chord::changeState() @ " << thisNode.getIp()
            << " (" << thisNode.getKey().toString(16) << ")]\n"
            << "    Entered READY stage"
            << endl;
        }
        getParentModule()->getParentModule()->bubble("Enter READY state.");
        break;
    }

NodeVector * oversim::Chord::closestPreceedingNode ( const OverlayKey key  )  [protected, virtual]

looks up the finger table and returns the closest preceeding node.

Parameters:
key key to find the closest preceeding node for
Returns:
node vector of the closest preceeding nodes to key

Definition at line 601 of file Chord.cc.

Referenced by findNode().

{
    NodeHandle tempHandle = NodeHandle::UNSPECIFIED_NODE;

    // find the closest preceding node in the successor list
    for (int j = successorList->getSize() - 1; j >= 0; j--) {
        // return a predecessor of the key, unless we know a node with an Id = destKey
        if (successorList->getSuccessor(j).getKey().isBetweenR(thisNode.getKey(), key)) {
            tempHandle = successorList->getSuccessor(j);
            break;
        }
    }

    if(tempHandle.isUnspecified()) {
        std::stringstream temp;
        temp << "Chord::closestPreceedingNode(): Successor list broken "
             << thisNode.getKey() << " " << key;
        throw cRuntimeError(temp.str().c_str());
    }

    NodeVector* nextHop = NULL;

    for (int i = fingerTable->getSize() - 1; i >= 0; i--) {
        // return a predecessor of the key, unless we know a node with an Id = destKey
        if (fingerTable->getFinger(i).getKey().isBetweenLR(tempHandle.getKey(), key)) {
            if(!extendedFingerTable) {
                nextHop = new NodeVector();
                nextHop->push_back(fingerTable->getFinger(i));

                EV << "[Chord::closestPreceedingNode() @ " << thisNode.getIp()
                   << " (" << thisNode.getKey().toString(16) << ")]\n"
                   << "    ClosestPreceedingNode: node " << thisNode
                   << " for key " << key << "\n"
                   << "    finger " << fingerTable->getFinger(i).getKey()
                   << " better than \n"
                   << "    " << tempHandle.getKey()
                   << endl;
                return nextHop;
            } else {
                return fingerTable->getFinger(i, key);
            }
        }
    }

    nextHop = new NodeVector();
    EV << "[Chord::closestPreceedingNode() @ " << thisNode.getIp()
       << " (" << thisNode.getKey().toString(16) << ")]\n"
       << "    No finger found"
       << endl;

    // if no finger is found lookup the rest of the successor list
    for (int i = successorList->getSize() - 1; i >= 0
        && nextHop->size() <= numFingerCandidates ; i--) {
        if (successorList->getSuccessor(i).getKey().isBetween(thisNode.getKey(), key)) {
            nextHop->push_back(successorList->getSuccessor(i));
        }
    }

    if (nextHop->size() != 0) {
        return nextHop;
    }

    // if this is the first and only node on the ring, it is responsible
    if ((predecessorNode.isUnspecified()) &&
        (successorList->getSuccessor() == thisNode)) {
        nextHop->push_back(thisNode);
        return nextHop;
    }

    // if there is still no node found throw an exception
    throw cRuntimeError("Error in Chord::closestPreceedingNode()!");
    return nextHop;

OverlayKey oversim::Chord::distance ( const OverlayKey x,
const OverlayKey y,
bool  useAlternative = false 
) const

Definition at line 1402 of file Chord.cc.

       : The following should be removed, since Chord doesn't have a simple metric
OverlayKey Chord::distance(const OverlayKey& x,
                           const OverlayKey& y,
                           bool useAlternative) const
{
    return KeyUniRingMetric().distance(x, y);

void oversim::Chord::findFriendModules (  )  [protected, virtual]

Assigns the finger table and successor list module to our reference.

Reimplemented in oversim::Koorde.

Definition at line 1358 of file Chord.cc.

Referenced by initializeOverlay().

{
    fingerTable = check_and_cast<ChordFingerTable*>
                  (getParentModule()->getSubmodule("fingerTable"));

    successorList = check_and_cast<ChordSuccessorList*>
                    (getParentModule()->getSubmodule("successorList"));

NodeVector * oversim::Chord::findNode ( const OverlayKey key,
int  numRedundantNodes,
int  numSiblings,
BaseOverlayMessage msg 
) [protected]

Reimplemented in oversim::Koorde.

Definition at line 547 of file Chord.cc.

{
    bool err;
    NodeVector* nextHop;

    if (state != READY)
        return new NodeVector();

    if (successorList->isEmpty() && !predecessorNode.isUnspecified()) {
        throw new cRuntimeError("Chord: Node is READY, has a "
                                "predecessor but no successor!");
        join();
        return new NodeVector();
    }

    // if key is unspecified, the message is for this node
    if (key.isUnspecified()) {
        nextHop = new NodeVector();
        nextHop->push_back(thisNode);
    }

    // the message is destined for this node
    else if (isSiblingFor(thisNode, key, 1, &err)) {
        nextHop = new NodeVector();
        nextHop->push_back(thisNode);
        for (uint32_t i = 0; i < successorList->getSize(); i++) {
            nextHop->push_back(successorList->getSuccessor(i));
        }
        nextHop->downsizeTo(numSiblings);
    }

    // the message destined for our successor
    else if (key.isBetweenR(thisNode.getKey(),
                            successorList->getSuccessor().getKey())) {
        nextHop = new NodeVector();
        for (uint32_t i = 0; i < successorList->getSize(); i++) {
            nextHop->push_back(successorList->getSuccessor(i));
        }
        nextHop->downsizeTo(numRedundantNodes);
    }

    // find next hop with finger table and/or successor list
    else {
        nextHop = closestPreceedingNode(key);
        nextHop->downsizeTo(numRedundantNodes);
    }

    return nextHop;

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

Reimplemented in oversim::Koorde.

Definition at line 725 of file Chord.cc.

{
    // remove this node from the bootstrap list
    bootstrapList->removeBootstrapNode(thisNode);

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

    globalStatistics->addStdDev("Chord: Sent JOIN Messages/s",
                                joinCount / time);
    globalStatistics->addStdDev("Chord: Sent NEWSUCCESSORHINT Messages/s",
                                newsuccessorhintCount / time);
    globalStatistics->addStdDev("Chord: Sent STABILIZE Messages/s",
                                stabilizeCount / time);
    globalStatistics->addStdDev("Chord: Sent NOTIFY Messages/s",
                                notifyCount / time);
    globalStatistics->addStdDev("Chord: Sent FIX_FINGERS Messages/s",
                                fixfingersCount / time);
    globalStatistics->addStdDev("Chord: Sent JOIN Bytes/s",
                                joinBytesSent / time);
    globalStatistics->addStdDev("Chord: Sent NEWSUCCESSORHINT Bytes/s",
                                newsuccessorhintBytesSent / time);
    globalStatistics->addStdDev("Chord: Sent STABILIZE Bytes/s",
                                stabilizeBytesSent / time);
    globalStatistics->addStdDev("Chord: Sent NOTIFY Bytes/s",
                                notifyBytesSent / time);
    globalStatistics->addStdDev("Chord: Sent FIX_FINGERS Bytes/s",
                                fixfingersBytesSent / time);

int oversim::Chord::getMaxNumRedundantNodes (  )  [protected]

Definition at line 415 of file Chord.cc.

int oversim::Chord::getMaxNumSiblings (  )  [protected]

Definition at line 410 of file Chord.cc.

Referenced by isSiblingFor().

bool oversim::Chord::handleFailedNode ( const TransportAddress failed  )  [protected, virtual]

Reimplemented in oversim::Koorde.

Definition at line 501 of file Chord.cc.

Referenced by handleRpcTimeout(), pingTimeout(), and proxCallback().

{
    Enter_Method_Silent();

    if (!predecessorNode.isUnspecified() && failed == predecessorNode)
        predecessorNode = NodeHandle::UNSPECIFIED_NODE;

    //TODO const reference -> trying to compare unspec NH
    TransportAddress oldSuccessor = successorList->getSuccessor();

    if (successorList->handleFailedNode(failed))
        updateTooltip();
    // check pointer for koorde
    if (fingerTable != NULL)
        fingerTable->handleFailedNode(failed);

    // if we had a ring consisting of 2 nodes and our successor seems
    // to be dead. Remove also predecessor because the successor
    // and predecessor are the same node
    if ((!predecessorNode.isUnspecified()) &&
        oldSuccessor == predecessorNode) {
        predecessorNode = NodeHandle::UNSPECIFIED_NODE;
        callUpdate(predecessorNode, false);
    }

    if (failed == oldSuccessor) {
        // schedule next stabilization process
        if (memorizeFailedSuccessor) {
            failedSuccessor = oldSuccessor;
        }
        cancelEvent(stabilize_timer);
        scheduleAt(simTime(), stabilize_timer);
    }

    if (state != READY) return true;

    if (successorList->isEmpty()) {
        // lost our last successor - cancel periodic stabilize tasks
        // and wait for rejoin
        cancelEvent(stabilize_timer);
        cancelEvent(fixfingers_timer);
    }

    return !(successorList->isEmpty());

void oversim::Chord::handleFixFingersTimerExpired ( cMessage *  msg  )  [protected, virtual]

handle a expired fix_fingers timer

Parameters:
msg the timer self-message

Definition at line 844 of file Chord.cc.

Referenced by oversim::Koorde::handleTimerEvent(), and handleTimerEvent().

{
    if ((state != READY) || successorList->isEmpty())
        return;

    OverlayKey offset, lookupKey;
    for (uint32_t nextFinger = 0; nextFinger < thisNode.getKey().getLength();
         nextFinger++) {
        // calculate "n + 2^(i - 1)"
        offset = OverlayKey::pow2(nextFinger);
        lookupKey = thisNode.getKey() + offset;

        // send message only for non-trivial fingers
        if (offset > successorList->getSuccessor().getKey() - thisNode.getKey()) {
            // call FIXFINGER RPC
            FixfingersCall* call = new FixfingersCall("FixfingersCall");
            call->setFinger(nextFinger);
            call->setBitLength(FIXFINGERSCALL_L(call));

            sendRouteRpcCall(OVERLAY_COMP, lookupKey, call, NULL,
                             DEFAULT_ROUTING, fixfingersDelay);
        } else {
            // delete trivial fingers (points to the successor node)
            fingerTable->removeFinger(nextFinger);
        }
    }

    // schedule next finger repair process
    cancelEvent(fixfingers_timer);
    scheduleAt(simTime() + fixfingersDelay, msg);

void oversim::Chord::handleJoinTimerExpired ( cMessage *  msg  )  [protected, virtual]

handle a expired join timer

Parameters:
msg the timer self-message

Definition at line 757 of file Chord.cc.

Referenced by handleTimerEvent().

{
    // only process timer, if node is not bootstrapped yet
    if (state == READY)
        return;

    // enter state BOOTSTRAP
    if (state != BOOTSTRAP)
        changeState(BOOTSTRAP);

    // change bootstrap node from time to time
    joinRetry--;
    if (joinRetry == 0) {
        joinRetry = par("joinRetry");
        changeState(BOOTSTRAP);
        return;
    }

    // call JOIN RPC
    JoinCall* call = new JoinCall("JoinCall");
    call->setBitLength(JOINCALL_L(call));

    RoutingType routingType = (defaultRoutingType == FULL_RECURSIVE_ROUTING ||
                               defaultRoutingType == RECURSIVE_SOURCE_ROUTING) ?
                              SEMI_RECURSIVE_ROUTING : defaultRoutingType;

    sendRouteRpcCall(OVERLAY_COMP, bootstrapNode, thisNode.getKey(),
                     call, NULL, routingType, joinDelay);

    // schedule next bootstrap process in the case this one fails
    cancelEvent(join_timer);
    scheduleAt(simTime() + joinDelay, msg);

void oversim::Chord::handleNewSuccessorHint ( ChordMessage chordMsg  )  [protected, virtual]

handle a received NEWSUCCESSORHINT message

Parameters:
chordMsg the message to process

Definition at line 877 of file Chord.cc.

Referenced by handleUDPMessage().

{
    NewSuccessorHintMessage* newSuccessorHintMsg =
        check_and_cast<NewSuccessorHintMessage*>(chordMsg);

    // fetch the successor's predecessor
    NodeHandle predecessor = newSuccessorHintMsg->getPreNode();

    // is the successor's predecessor a new successor for this node?
    if (predecessor.getKey().isBetween(thisNode.getKey(),
                                  successorList->getSuccessor().getKey())
        || (thisNode.getKey() == successorList->getSuccessor().getKey())) {
        // add the successor's predecessor to the successor list
        successorList->addSuccessor(predecessor);
        updateTooltip();
    }

    // if the successor node reports a new successor, put it into the
    // successor list and start stabilizing
    if (mergeOptimizationL3) {
        if (successorList->getSuccessor() == predecessor) {
            StabilizeCall *call = new StabilizeCall("StabilizeCall");
            call->setBitLength(STABILIZECALL_L(call));

            sendUdpRpcCall(predecessor, call);
        } else {
            if (successorList->getSuccessor() == newSuccessorHintMsg->
                                                               getSrcNode()) {

                StabilizeCall *call = new StabilizeCall("StabilizeCall");
                call->setBitLength(STABILIZECALL_L(call));

                sendUdpRpcCall(predecessor, call);
            }
        }
    }

bool oversim::Chord::handleRpcCall ( BaseCallMessage msg  )  [protected, virtual]

Reimplemented in oversim::Koorde.

Definition at line 293 of file Chord.cc.

{
    if (state != READY) {
        EV << "[Chord::handleRpcCall() @ " << thisNode.getIp()
           << " (" << thisNode.getKey().toString(16) << ")]\n"
           << "    Received RPC call and state != READY"
           << endl;
        return false;
    }

    // delegate messages
    RPC_SWITCH_START( msg )
    // RPC_DELEGATE( <messageName>[Call|Response], <methodToCall> )
    RPC_DELEGATE( Join, rpcJoin );
    RPC_DELEGATE( Notify, rpcNotify );
    RPC_DELEGATE( Stabilize, rpcStabilize );
    RPC_DELEGATE( Fixfingers, rpcFixfingers );
    RPC_SWITCH_END( )

    return RPC_HANDLED;

void oversim::Chord::handleRpcFixfingersResponse ( FixfingersResponse fixfingersResponse,
double  rtt = -1 
) [protected, virtual]

Definition at line 1256 of file Chord.cc.

Referenced by handleRpcResponse().

{
    /*
    OverlayCtrlInfo* ctrlInfo =
        check_and_cast<OverlayCtrlInfo*>(fixfingersResponse->getControlInfo());

    RECORD_STATS(globalStatistics->recordOutVector("Chord: FIX_FINGERS response Hop Count", ctrlInfo->getHopCount()));
     */

    // set new finger pointer#
    if (!extendedFingerTable) {
        fingerTable->setFinger(fixfingersResponse->getFinger(),
                               fixfingersResponse->getSucNode(0));
    } else {
        Successors successors;
        for (unsigned int i = 0; i < fixfingersResponse->getSucNodeArraySize();
             i++) {
            if (fixfingersResponse->getSucNode(i).isUnspecified())
                continue;
            if (fixfingersResponse->getSucNode(i) == thisNode)
                break;
            successors.insert(std::make_pair(MAXTIME,
                                             fixfingersResponse->getSucNode(i)));
        }

        if (successors.size() == 0) {
            return;
        }

        fingerTable->setFinger(fixfingersResponse->getFinger(), successors);

#if 0
        if (proximityRouting || globalParameters->getTopologyAdaptation()) {
#else
        if (proximityRouting) {
#endif
            for (unsigned int i = 0;
                 i < fixfingersResponse->getSucNodeArraySize();
                 i++) {
                if (fixfingersResponse->getSucNode(i).isUnspecified())
                    continue;
                if (fixfingersResponse->getSucNode(i) == thisNode)
                    break;
                //pingNode(fixfingersResponse->getSucNode(i), -1, 0, NULL,
                //         NULL, NULL, fixfingersResponse->getFinger(),
                //         INVALID_TRANSPORT);
                Prox prox =
                    neighborCache->getProx(fixfingersResponse->getSucNode(i),
                                           NEIGHBORCACHE_DEFAULT,
                                           fixfingersResponse->getFinger(),
                                           this, NULL);
                if (prox == Prox::PROX_TIMEOUT) {
                    fingerTable->removeFinger(fixfingersResponse->getFinger());
                } else if (prox != Prox::PROX_UNKNOWN &&
                           prox != Prox::PROX_SELF) {
                    fingerTable->updateFinger(fixfingersResponse->getFinger(),
                                              fixfingersResponse->getSucNode(i),
                                              prox.proximity);
                }
            }
        }
    }

void oversim::Chord::handleRpcJoinResponse ( JoinResponse joinResponse  )  [protected, virtual]

Reimplemented in oversim::Koorde.

Definition at line 987 of file Chord.cc.

Referenced by handleRpcResponse().

{
    // determine the numer of successor nodes to add
    int sucNum = successorListSize - 1;

    if (joinResponse->getSucNum() < successorListSize - 1) {
        sucNum = joinResponse->getSucNum();
    }

    // add successor getNode(s)
    for (int k = 0; k < sucNum; k++) {
        NodeHandle successor = joinResponse->getSucNode(k);
        successorList->addSuccessor(successor);
    }

    // the sender of this message is our new successor
    successorList->addSuccessor(joinResponse->getSrcNode());

    // in aggressiveJoinMode: use hint in JoinResponse
    // to set our new predecessor
    if (aggressiveJoinMode) {
        // it is possible that the joinResponse doesn't contain a valid
        // predecessor especially when merging two partitions
        if (!joinResponse->getPreNode().isUnspecified()) {
            if (!predecessorNode.isUnspecified()) {


                // inform the original predecessor about the new predecessor
                if (mergeOptimizationL2) {
                    NewSuccessorHintMessage* newSuccessorHintMsg =
                        new NewSuccessorHintMessage("NEWSUCCESSORHINT");
                    newSuccessorHintMsg->setCommand(NEWSUCCESSORHINT);
                    newSuccessorHintMsg->setSrcNode(thisNode);
                    newSuccessorHintMsg->setPreNode(joinResponse->getPreNode());
                    newSuccessorHintMsg->
                        setBitLength(NEWSUCCESSORHINT_L(newSuccessorHintMsg));

                    sendMessageToUDP(predecessorNode, newSuccessorHintMsg);
                }
            }

            NodeHandle oldPredecessor = predecessorNode;
            predecessorNode = joinResponse->getPreNode();

            if (!oldPredecessor.isUnspecified()
                && !joinResponse->getPreNode().isUnspecified()
                && oldPredecessor != joinResponse->getPreNode()) {
                callUpdate(oldPredecessor, false);
            }
            callUpdate(predecessorNode, true);
        }
    }

    updateTooltip();

    changeState(READY);

    // immediate stabilization protocol
    cancelEvent(stabilize_timer);
    scheduleAt(simTime(), stabilize_timer);

    // immediate finger repair protocol
    cancelEvent(fixfingers_timer);
    scheduleAt(simTime(), fixfingers_timer);

void oversim::Chord::handleRpcNotifyResponse ( NotifyResponse notifyResponse  )  [protected, virtual]

Definition at line 1191 of file Chord.cc.

Referenced by handleRpcResponse().

{
    if (state != READY) {
        return;
    }

    if (successorList->getSuccessor() != notifyResponse->getSrcNode()) {
        EV << "[Chord::handleRpcNotifyResponse() @ " << thisNode.getIp()
           << " (" << thisNode.getKey().toString(16) << ")]\n"
           << "    The srcNode of the received NotifyResponse is not our "
           << " current successor"
           << endl;
        return;
    }

    // if the NotifyResponse sender couldn't accept me as predecessor,
    // put its predecessor into the successor list and starts stabilizing
    if (mergeOptimizationL3) {
        if (!notifyResponse->getPreNodeSet()) {
            StabilizeCall *call = new StabilizeCall("StabilizeCall");
            call->setBitLength(STABILIZECALL_L(call));

            successorList->addSuccessor(notifyResponse->getPreNode());
            if (successorList->getSuccessor() == notifyResponse->getPreNode())
                sendUdpRpcCall(notifyResponse->getPreNode(), call);
            return;
        }
    }

    // replace our successor list by our successor's successor list
    successorList->updateList(notifyResponse);

    updateTooltip();

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

Reimplemented in oversim::Koorde.

Definition at line 315 of file Chord.cc.

{
    RPC_SWITCH_START(msg)
    RPC_ON_RESPONSE( Join ) {
        handleRpcJoinResponse(_JoinResponse);
        EV << "[Chord::handleRpcResponse() @ " << thisNode.getIp()
        << " (" << thisNode.getKey().toString(16) << ")]\n"
        << "    Received a Join RPC Response: id=" << rpcId << "\n"
        << "    msg=" << *_JoinResponse << " rtt=" << rtt
        << endl;
        break;
    }
    RPC_ON_RESPONSE( Notify ) {
        handleRpcNotifyResponse(_NotifyResponse);
        EV << "[Chord::handleRpcResponse() @ " << thisNode.getIp()
        << " (" << thisNode.getKey().toString(16) << ")]\n"
        << "    Received a Notify RPC Response: id=" << rpcId << "\n"
        << "    msg=" << *_NotifyResponse << " rtt=" << rtt
        << endl;
        break;
    }
    RPC_ON_RESPONSE( Stabilize ) {
        handleRpcStabilizeResponse(_StabilizeResponse);
        EV << "[Chord::handleRpcResponse() @ " << thisNode.getIp()
        << " (" << thisNode.getKey().toString(16) << ")]\n"
        << "    Received a Stabilize RPC Response: id=" << rpcId << "\n"
        << "    msg=" << *_StabilizeResponse << " rtt=" << rtt
        << endl;
        break;
    }
    RPC_ON_RESPONSE( Fixfingers ) {
        handleRpcFixfingersResponse(_FixfingersResponse, SIMTIME_DBL(rtt));
        EV << "[Chord::handleRpcResponse() @ " << thisNode.getIp()
        << " (" << thisNode.getKey().toString(16) << ")]\n"
        << "    Received a Fixfingers RPC Response: id=" << rpcId << "\n"
        << "    msg=" << *_FixfingersResponse << " rtt=" << rtt
        << endl;
        break;
    }
    RPC_SWITCH_END( )

void oversim::Chord::handleRpcStabilizeResponse ( StabilizeResponse stabilizeResponse  )  [protected, virtual]

Definition at line 1071 of file Chord.cc.

Referenced by handleRpcResponse().

{
    if (state != READY) {
        return;
    }

    // fetch the successor's predecessor
    const NodeHandle& predecessor = stabilizeResponse->getPreNode();

    // is the successor's predecessor a new successor for this node?
    if ((successorList->isEmpty() ||
         predecessor.getKey().isBetween(thisNode.getKey(),
                                  successorList->getSuccessor().getKey())) &&
        (failedSuccessor.isUnspecified() || failedSuccessor != predecessor)) {
        if (successorList->isEmpty() && predecessor.isUnspecified()) {
            // successor is emptry and the sender of the response has
            // no predecessor => take the sender as new successor
            successorList->addSuccessor(stabilizeResponse->getSrcNode());
        } else {
            // add the successor's predecessor to the successor list
            successorList->addSuccessor(predecessor);
        }
        updateTooltip();
    }

    // compile NOTIFY RPC
    NotifyCall* notifyCall = new NotifyCall("NotifyCall");
    notifyCall->setBitLength(NOTIFYCALL_L(notifyCall));
    notifyCall->setFailed(failedSuccessor);
    failedSuccessor = TransportAddress::UNSPECIFIED_NODE;

    sendUdpRpcCall(successorList->getSuccessor(), notifyCall);

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

Reimplemented in oversim::Koorde.

Definition at line 359 of file Chord.cc.

{
    RPC_SWITCH_START(msg)
    RPC_ON_CALL( FindNode ) {
        EV << "[Chord::handleRpcTimeout() @ " << thisNode.getIp()
        << " (" << thisNode.getKey().toString(16) << ")]\n"
        << "    FindNode RPC Call timed out: id=" << rpcId << "\n"
        << "    msg=" << *_FindNodeCall
        << endl;
        break;
    }
    RPC_ON_CALL( Join ) {
        EV << "[Chord::handleRpcTimeout() @ " << thisNode.getIp()
        << " (" << thisNode.getKey().toString(16) << ")]\n"
        << "    Join RPC Call timed out: id=" << rpcId << "\n"
        << "    msg=" << *_JoinCall
        << endl;
        break;
    }
    RPC_ON_CALL( Notify ) {
        EV << "[Chord::handleRpcTimeout() @ " << thisNode.getIp()
        << " (" << thisNode.getKey().toString(16) << ")]\n"
        << "    Notify RPC Call timed out: id=" << rpcId << "\n"
        << "    msg=" << *_NotifyCall
        << endl;
        if (!handleFailedNode(dest)) join();
        break;
    }
    RPC_ON_CALL( Stabilize ) {
        EV << "[Chord::handleRpcTimeout() @ " << thisNode.getIp()
        << " (" << thisNode.getKey().toString(16) << ")]\n"
        << "    Stabilize RPC Call timed out: id=" << rpcId << "\n"
        << "    msg=" << *_StabilizeCall
        << endl;
        if (!handleFailedNode(dest)) join();
        break;
    }
    RPC_ON_CALL( Fixfingers ) {
        EV << "[Chord::handleRpcTimeout() @ " << thisNode.getIp()
        << " (" << thisNode.getKey().toString(16) << ")]\n"
        << "    Fixfingers RPC Call timed out: id=" << rpcId << "\n"
        << "    msg=" << *_FixfingersCall
        << endl;
        break;
    }
    RPC_SWITCH_END( )

void oversim::Chord::handleStabilizeTimerExpired ( cMessage *  msg  )  [protected, virtual]

handle a expired stabilize timer

Parameters:
msg the timer self-message

Definition at line 792 of file Chord.cc.

Referenced by handleTimerEvent().

{
    if (state != READY)
        return;

    // alternative predecessor check
    if ((checkPredecessorDelay == 0) &&
        (missingPredecessorStabRequests >= stabilizeRetry)) {
        // predecessor node seems to be dead
        // remove it from the predecessor / successor lists
        //successorList->removeSuccessor(predecessorNode);
        predecessorNode = NodeHandle::UNSPECIFIED_NODE;
        missingPredecessorStabRequests = 0;
        updateTooltip();
        callUpdate(predecessorNode, false);
    }

    if (!successorList->isEmpty()) {
        // call STABILIZE RPC
        StabilizeCall* call = new StabilizeCall("StabilizeCall");
        call->setBitLength(STABILIZECALL_L(call));

        sendUdpRpcCall(successorList->getSuccessor(), call);

        missingPredecessorStabRequests++;
    }

    // check if fingers are still alive and remove unreachable finger nodes
    if (mergeOptimizationL4) {
        OverlayKey offset;
        for (uint32_t nextFinger = 0; nextFinger < thisNode.getKey().getLength();
             nextFinger++) {
            offset = OverlayKey::pow2(nextFinger);

            // send message only for non-trivial fingers
            if (offset > successorList->getSuccessor().getKey() - thisNode.getKey()) {
                if ((fingerTable->getFinger(nextFinger)).isUnspecified()) {
                    continue;
                } else {
                    pingNode(fingerTable->getFinger(nextFinger), -1, 0, NULL,
                             NULL, NULL, nextFinger);
                }
            }
        }
    }

    // schedule next stabilization process
    cancelEvent(stabilize_timer);
    scheduleAt(simTime() + stabilizeDelay, msg);

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

Reimplemented in oversim::Koorde.

Definition at line 248 of file Chord.cc.

{
    // catch JOIN timer
    if (msg == join_timer) {
        handleJoinTimerExpired(msg);
    }
    // catch STABILIZE timer
    else if (msg == stabilize_timer) {
        handleStabilizeTimerExpired(msg);
    }
    // catch FIX_FINGERS timer
    else if (msg == fixfingers_timer) {
        handleFixFingersTimerExpired(msg);
    }
    // catch CHECK_PREDECESSOR timer
    else if (msg == checkPredecessor_timer) {
        cancelEvent(checkPredecessor_timer);
        scheduleAt(simTime() + checkPredecessorDelay,
                   checkPredecessor_timer);
        if (!predecessorNode.isUnspecified()) pingNode(predecessorNode);
    }
    // unknown self message
    else {
        error("Chord::handleTimerEvent(): received self message of "
              "unknown type!");
    }

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

Reimplemented in oversim::Koorde.

Definition at line 277 of file Chord.cc.

{
    ChordMessage* chordMsg = check_and_cast<ChordMessage*>(msg);
    switch(chordMsg->getCommand()) {
    case NEWSUCCESSORHINT:
        handleNewSuccessorHint(chordMsg);
        break;
    default:
        error("handleUDPMessage(): Unknown message type!");
        break;
    }

    delete chordMsg;

void oversim::Chord::initializeFriendModules (  )  [protected, virtual]

initializes finger table and successor list

Reimplemented in oversim::Koorde.

Definition at line 1368 of file Chord.cc.

Referenced by changeState().

{
    // initialize finger table
    fingerTable->initializeTable(thisNode.getKey().getLength(), thisNode, this);

    // initialize successor list
    successorList->initializeList(par("successorListSize"), thisNode, this);

void oversim::Chord::initializeOverlay ( int  stage  )  [virtual]

Reimplemented in oversim::Koorde.

Definition at line 45 of file Chord.cc.

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

    if (iterativeLookupConfig.merge == true) {
        throw cRuntimeError("Chord::initializeOverlay(): "
              "Chord doesn't work with iterativeLookupConfig.merge = true!");
    }

    // Chord provides KBR services
    kbr = true;

    // fetch some parameters
    useCommonAPIforward = par("useCommonAPIforward");
    successorListSize = par("successorListSize");
    joinRetry = par("joinRetry");
    stabilizeRetry = par("stabilizeRetry");
    joinDelay = par("joinDelay");
    stabilizeDelay = par("stabilizeDelay");
    fixfingersDelay = par("fixfingersDelay");
    checkPredecessorDelay = par("checkPredecessorDelay");
    aggressiveJoinMode = par("aggressiveJoinMode");
    extendedFingerTable = par("extendedFingerTable");
    numFingerCandidates = par("numFingerCandidates");
    proximityRouting = par("proximityRouting");
    memorizeFailedSuccessor = par("memorizeFailedSuccessor");

    // merging optimizations
    mergeOptimizationL1 = par("mergeOptimizationL1");
    mergeOptimizationL2 = par("mergeOptimizationL2");
    mergeOptimizationL3 = par("mergeOptimizationL3");
    mergeOptimizationL4 = par("mergeOptimizationL4");

    keyLength = OverlayKey::getLength();
    missingPredecessorStabRequests = 0;

    // statistics
    joinCount = 0;
    stabilizeCount = 0;
    fixfingersCount = 0;
    notifyCount = 0;
    newsuccessorhintCount = 0;
    joinBytesSent = 0;
    stabilizeBytesSent = 0;
    notifyBytesSent = 0;
    fixfingersBytesSent = 0;
    newsuccessorhintBytesSent = 0;

    failedSuccessor = TransportAddress::UNSPECIFIED_NODE;

    // find friend modules
    findFriendModules();

    // add some watches
    WATCH(predecessorNode);
    WATCH(thisNode);
    WATCH(bootstrapNode);
    WATCH(joinRetry);
    WATCH(missingPredecessorStabRequests);

    // self-messages
    join_timer = new cMessage("join_timer");
    stabilize_timer = new cMessage("stabilize_timer");
    fixfingers_timer = new cMessage("fixfingers_timer");
    checkPredecessor_timer = new cMessage("checkPredecessor_timer");

bool oversim::Chord::isSiblingFor ( const NodeHandle node,
const OverlayKey key,
int  numSiblings,
bool *  err 
) [protected, virtual]

Definition at line 421 of file Chord.cc.

Referenced by findNode().

{
    if (key.isUnspecified())
        error("Chord::isSiblingFor(): key is unspecified!");

    if (state != READY) {
        *err = true;
        return false;
    }

    if (numSiblings > getMaxNumSiblings()) {
        opp_error("Chord::isSiblingFor(): numSiblings too big!");
    }
    // set default number of siblings to consider
    if (numSiblings == -1) numSiblings = getMaxNumSiblings();

    // if this is the first and only node on the ring, it is responsible
    if ((predecessorNode.isUnspecified()) && (node == thisNode)) {
        if (successorList->isEmpty() || (node.getKey() == key)) {
            *err = false;
            return true;
        } else {
            *err = true;
            return false;
        }
    }

    if ((node == thisNode)
         && (key.isBetweenR(predecessorNode.getKey(), thisNode.getKey()))) {

        *err = false;
        return true;
    }

    NodeHandle prevNode = predecessorNode;
    NodeHandle curNode;

    for (int i = -1; i < (int)successorList->getSize();
         i++, prevNode = curNode) {

        if (i < 0) {
            curNode = thisNode;
        } else {
            curNode = successorList->getSuccessor(i);
        }

        if (node == curNode) {
            // is the message destined for curNode?
            if (key.isBetweenR(prevNode.getKey(), curNode.getKey())) {
                if (numSiblings <= ((int)successorList->getSize() - i)) {
                    *err = false;
                    return true;
                } else {
                    *err = true;
                    return false;
                }
            } else {
                // the key doesn't directly belong to this node, but
                // the node could be a sibling for this key
                if (numSiblings <= 1) {
                    *err = false;
                    return false;
                } else {
                    // In Chord we don't know if we belong to the
                    // replicaSet of one of our predecessors
                    *err = true;
                    return false;
                }
            }
        }
    }

    // node is not in our neighborSet
    *err = true;
    return false;

void oversim::Chord::joinForeignPartition ( const NodeHandle node  )  [protected, virtual]

Definition at line 134 of file Chord.cc.

{
    Enter_Method_Silent();

    // create a join call and sent to the bootstrap node.
    JoinCall *call = new JoinCall("JoinCall");
    call->setBitLength(JOINCALL_L(call));

    RoutingType routingType = (defaultRoutingType == FULL_RECURSIVE_ROUTING ||
                               defaultRoutingType == RECURSIVE_SOURCE_ROUTING) ?
                              SEMI_RECURSIVE_ROUTING : defaultRoutingType;

    sendRouteRpcCall(OVERLAY_COMP, node, thisNode.getKey(),
                     call, NULL, routingType, joinDelay);

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

Definition at line 127 of file Chord.cc.

void oversim::Chord::pingResponse ( PingResponse pingResponse,
cPolymorphic *  context,
int  rpcId,
simtime_t  rtt 
) [protected, virtual]

Definition at line 1333 of file Chord.cc.

{
    EV << "[Chord::pingResponse() @ " << thisNode.getIp()
       << " (" << thisNode.getKey().toString(16) << ")]\n"
       << "    Received a Ping RPC Response: id=" << rpcId << "\n"
       << "    msg=" << *pingResponse << " rtt=" << rtt
       << endl;

    if (rpcId != -1)
        fingerTable->updateFinger(rpcId, pingResponse->getSrcNode(), rtt);

void oversim::Chord::pingTimeout ( PingCall pingCall,
const TransportAddress dest,
cPolymorphic *  context,
int  rpcId 
) [protected, virtual]

Definition at line 1346 of file Chord.cc.

{
    EV << "[Chord::pingTimeout() @ " << thisNode.getIp()
       << " (" << thisNode.getKey().toString(16) << ")]\n"
       << "    Ping RPC timeout: id=" << rpcId << endl;

    // call join dependant on return value?
    handleFailedNode(dest);

void oversim::Chord::proxCallback ( const TransportAddress node,
int  rpcId,
cPolymorphic *  contextPointer,
Prox  prox 
) [virtual]

Implements ProxListener.

Definition at line 1321 of file Chord.cc.

{
    if (prox == Prox::PROX_TIMEOUT) {
        // call join dependant on return value?
        handleFailedNode(node);
        return;
    }

    fingerTable->updateFinger(rpcId, (NodeHandle&)node, prox.proximity);

void oversim::Chord::recordOverlaySentStats ( BaseOverlayMessage msg  )  [virtual]

Reimplemented in oversim::Koorde.

Definition at line 675 of file Chord.cc.

{
    BaseOverlayMessage* innerMsg = msg;
    while (innerMsg->getType() != APPDATA &&
           innerMsg->getEncapsulatedPacket() != NULL) {
        innerMsg =
            static_cast<BaseOverlayMessage*>(innerMsg->getEncapsulatedPacket());
    }

    switch (innerMsg->getType()) {
        case OVERLAYSIGNALING: {
            ChordMessage* chordMsg = dynamic_cast<ChordMessage*>(innerMsg);
            switch(chordMsg->getCommand()) {
            case NEWSUCCESSORHINT:
                RECORD_STATS(newsuccessorhintCount++;
                             newsuccessorhintBytesSent += msg->getByteLength());
                break;
            }
            break;
        }

        case RPC: {
            if ((dynamic_cast<StabilizeCall*>(innerMsg) != NULL) ||
                    (dynamic_cast<StabilizeResponse*>(innerMsg) != NULL)) {
                RECORD_STATS(stabilizeCount++; stabilizeBytesSent +=
                             msg->getByteLength());
            } else if ((dynamic_cast<NotifyCall*>(innerMsg) != NULL) ||
                    (dynamic_cast<NotifyResponse*>(innerMsg) != NULL)) {
                RECORD_STATS(notifyCount++; notifyBytesSent +=
                             msg->getByteLength());
            } else if ((dynamic_cast<FixfingersCall*>(innerMsg) != NULL) ||
                    (dynamic_cast<FixfingersResponse*>(innerMsg) != NULL)) {
                RECORD_STATS(fixfingersCount++; fixfingersBytesSent +=
                             msg->getByteLength());
            } else if ((dynamic_cast<JoinCall*>(innerMsg) != NULL) ||
                    (dynamic_cast<JoinResponse*>(innerMsg) != NULL)) {
                RECORD_STATS(joinCount++; joinBytesSent += msg->getByteLength());
            }
            break;
        }

        case APPDATA:
            break;

        default:
            throw cRuntimeError("Unknown message type!");
    }

void oversim::Chord::rpcFixfingers ( FixfingersCall call  )  [protected]

Fixfingers Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Definition at line 1227 of file Chord.cc.

Referenced by handleRpcCall().

{
    FixfingersResponse* fixfingersResponse =
        new FixfingersResponse("FixfingersResponse");

    fixfingersResponse->setSucNodeArraySize(1);
    fixfingersResponse->setSucNode(0, thisNode);

    if (extendedFingerTable) {
        fixfingersResponse->setSucNodeArraySize(((successorList->getSize() + 1
                                                < numFingerCandidates + 1)
                                                ? successorList->getSize() + 1
                                                : numFingerCandidates + 1));
        for (unsigned int i = 0;
            i < (((successorList->getSize()) < numFingerCandidates)
                 ? (successorList->getSize()) : numFingerCandidates); i++) {

            assert(!successorList->getSuccessor(i).isUnspecified());
            fixfingersResponse->setSucNode(i + 1,
                                           successorList->getSuccessor(i));
        }
    }
    fixfingersResponse->setFinger(call->getFinger());
    fixfingersResponse->setBitLength(FIXFINGERSRESPONSE_L(fixfingersResponse));

    sendRpcResponse(call, fixfingersResponse);

void oversim::Chord::rpcJoin ( JoinCall call  )  [protected, virtual]

Join Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Reimplemented in oversim::Koorde.

Definition at line 916 of file Chord.cc.

Referenced by handleRpcCall().

{
    NodeHandle requestor = joinCall->getSrcNode();

    // compile successor list
    JoinResponse* joinResponse =
        new JoinResponse("JoinResponse");

    int sucNum = successorList->getSize();
    joinResponse->setSucNum(sucNum);
    joinResponse->setSucNodeArraySize(sucNum);

    for (int k = 0; k < sucNum; k++) {
        joinResponse->setSucNode(k, successorList->getSuccessor(k));
    }

    // sent our predecessor as hint to the joining node
    if (predecessorNode.isUnspecified() && successorList->isEmpty()) {
        // we are the only node in the ring
        joinResponse->setPreNode(thisNode);
    } else {
        joinResponse->setPreNode(predecessorNode);
    }

    joinResponse->setBitLength(JOINRESPONSE_L(joinResponse));

    sendRpcResponse(joinCall, joinResponse);

    if (aggressiveJoinMode) {
        // aggressiveJoinMode differs from standard join operations:
        // 1. set our predecessor pointer to the joining node
        // 2. send our old predecessor as hint in JoinResponse msgs
        // 3. send a NEWSUCCESSORHINT to our old predecessor to update
        //    its successor pointer

        // send NEWSUCCESSORHINT to our old predecessor

        if (!predecessorNode.isUnspecified()) {
            NewSuccessorHintMessage* newSuccessorHintMsg =
                new NewSuccessorHintMessage("NEWSUCCESSORHINT");
            newSuccessorHintMsg->setCommand(NEWSUCCESSORHINT);

            newSuccessorHintMsg->setSrcNode(thisNode);
            newSuccessorHintMsg->setPreNode(requestor);
            newSuccessorHintMsg->
            setBitLength(NEWSUCCESSORHINT_L(newSuccessorHintMsg));

            sendMessageToUDP(predecessorNode, newSuccessorHintMsg);
        }

        if (predecessorNode.isUnspecified() || (predecessorNode != requestor)) {
            // the requestor is our new predecessor
            NodeHandle oldPredecessor = predecessorNode;
            predecessorNode = requestor;

            // send update to application if we've got a new predecessor
            if (!oldPredecessor.isUnspecified()) {
                callUpdate(oldPredecessor, false);
            }
            callUpdate(predecessorNode, true);

        }
    }

    // if we don't have a successor, the requestor is also our new successor
    if (successorList->isEmpty())
        successorList->addSuccessor(requestor);

    updateTooltip();

void oversim::Chord::rpcNotify ( NotifyCall call  )  [protected, virtual]

NOTIFY Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Definition at line 1105 of file Chord.cc.

Referenced by handleRpcCall().

{
    // our predecessor seems to be alive
    if (!predecessorNode.isUnspecified() &&
        call->getSrcNode() == predecessorNode) {
        missingPredecessorStabRequests = 0;
    }

    bool newPredecessorSet = false;

    NodeHandle newPredecessor = call->getSrcNode();

    // is the new predecessor closer than the current one?
    if (predecessorNode.isUnspecified() ||
        newPredecessor.getKey().isBetween(predecessorNode.getKey(), thisNode.getKey()) ||
        (!call->getFailed().isUnspecified() &&
         call->getFailed() == predecessorNode)) {

        if ((predecessorNode.isUnspecified()) ||
            (newPredecessor != predecessorNode)) {

            // set up new predecessor
            NodeHandle oldPredecessor = predecessorNode;
            predecessorNode = newPredecessor;

            if (successorList->isEmpty()) {
                successorList->addSuccessor(newPredecessor);
            }

            newPredecessorSet = true;
            updateTooltip();

            // send update to application if we've got a new predecessor
            if (!oldPredecessor.isUnspecified()) {
                callUpdate(oldPredecessor, false);
            }
            callUpdate(predecessorNode, true);

            // inform the original predecessor about the new predecessor
            if (mergeOptimizationL1) {
                if (!oldPredecessor.isUnspecified()) {
                    NewSuccessorHintMessage *newSuccessorHintMsg =
                        new NewSuccessorHintMessage("NEWSUCCESSORHINT");
                    newSuccessorHintMsg->setCommand(NEWSUCCESSORHINT);

                    newSuccessorHintMsg->setSrcNode(thisNode);
                    newSuccessorHintMsg->setPreNode(predecessorNode);
                    newSuccessorHintMsg->
                        setBitLength(NEWSUCCESSORHINT_L(newSuccessorHintMsg));
                    sendMessageToUDP(oldPredecessor, newSuccessorHintMsg);
                }
            }


        }
    }

    // compile NOTIFY response
    NotifyResponse* notifyResponse = new NotifyResponse("NotifyResponse");

    int sucNum = successorList->getSize();
    notifyResponse->setSucNum(sucNum);
    notifyResponse->setSucNodeArraySize(sucNum);

    // can't accept the notify sender as predecessor,
    // tell it about my correct predecessor
    if (mergeOptimizationL3) {
        if (!newPredecessorSet && (predecessorNode != newPredecessor)) {

            notifyResponse->setPreNode(predecessorNode);
            notifyResponse->setPreNodeSet(false);
        } else {
            notifyResponse->setPreNodeSet(true);
        }
    }

    for (int k = 0; k < sucNum; k++) {
        notifyResponse->setSucNode(k, successorList->getSuccessor(k));
    }

    notifyResponse->setBitLength(NOTIFYRESPONSE_L(notifyResponse));

    sendRpcResponse(call, notifyResponse);

void oversim::Chord::rpcStabilize ( StabilizeCall call  )  [protected]

STABILIZE Remote-Procedure-Call.

Parameters:
call RPC Parameter Message

Definition at line 1054 of file Chord.cc.

Referenced by handleRpcCall().

{
    // our predecessor seems to be alive
    if (!predecessorNode.isUnspecified() &&
        call->getSrcNode() == predecessorNode) {
        missingPredecessorStabRequests = 0;
    }

    // reply with StabilizeResponse message
    StabilizeResponse* stabilizeResponse =
        new StabilizeResponse("StabilizeResponse");
    stabilizeResponse->setPreNode(predecessorNode);
    stabilizeResponse->setBitLength(STABILIZERESPONSE_L(stabilizeResponse));

    sendRpcResponse(call, stabilizeResponse);

void oversim::Chord::updateTooltip (  )  [virtual]

updates information shown in tk-environment

Reimplemented in oversim::Koorde.

Definition at line 1378 of file Chord.cc.

Referenced by changeState(), handleFailedNode(), handleNewSuccessorHint(), handleRpcJoinResponse(), handleRpcNotifyResponse(), handleRpcStabilizeResponse(), handleStabilizeTimerExpired(), rpcJoin(), and rpcNotify().

{
    if (ev.isGUI()) {
        std::stringstream ttString;

        // show our predecessor and successor in tooltip
        ttString << predecessorNode << endl << thisNode << endl
                 << successorList->getSuccessor();

        getParentModule()->getParentModule()->getDisplayString().
        setTagArg("tt", 0, ttString.str().c_str());
        getParentModule()->getDisplayString().
        setTagArg("tt", 0, ttString.str().c_str());
        getDisplayString().setTagArg("tt", 0, ttString.str().c_str());

        // draw an arrow to our current successor
        showOverlayNeighborArrow(successorList->getSuccessor(), true,
                                 "m=m,50,0,50,0;ls=red,1");
        showOverlayNeighborArrow(predecessorNode, false,
                                 "m=m,50,100,50,100;ls=green,1");
    }


Friends And Related Function Documentation

friend class ChordFingerTable [friend]

Definition at line 271 of file Chord.h.

friend class ChordSuccessorList [friend]

Definition at line 270 of file Chord.h.


Member Data Documentation

use modified (faster) JOIN protocol

Definition at line 89 of file Chord.h.

Referenced by handleRpcJoinResponse(), initializeOverlay(), and rpcJoin().

Definition at line 105 of file Chord.h.

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

Definition at line 116 of file Chord.h.

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

Definition at line 110 of file Chord.h.

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

double oversim::Chord::fixfingersDelay [protected]

Definition at line 86 of file Chord.h.

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

Definition at line 113 of file Chord.h.

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

int oversim::Chord::joinCount [protected]

Definition at line 108 of file Chord.h.

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

double oversim::Chord::joinDelay [protected]

Definition at line 84 of file Chord.h.

Referenced by handleJoinTimerExpired(), initializeOverlay(), and joinForeignPartition().

int oversim::Chord::joinRetry [protected]

Definition at line 82 of file Chord.h.

Referenced by handleJoinTimerExpired(), and initializeOverlay().

int oversim::Chord::keyLength [protected]

length of an overlay key in bits

Definition at line 119 of file Chord.h.

Referenced by initializeOverlay().

Definition at line 93 of file Chord.h.

Referenced by handleFailedNode(), and initializeOverlay().

Definition at line 95 of file Chord.h.

Referenced by initializeOverlay(), and rpcNotify().

Definition at line 96 of file Chord.h.

Referenced by handleRpcJoinResponse(), and initializeOverlay().

Definition at line 98 of file Chord.h.

Referenced by handleStabilizeTimerExpired(), and initializeOverlay().

Definition at line 94 of file Chord.h.

Definition at line 112 of file Chord.h.

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

Definition at line 115 of file Chord.h.

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

int oversim::Chord::notifyCount [protected]

Definition at line 111 of file Chord.h.

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

Definition at line 92 of file Chord.h.

Referenced by handleRpcFixfingersResponse(), and initializeOverlay().

Definition at line 114 of file Chord.h.

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

Definition at line 109 of file Chord.h.

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

double oversim::Chord::stabilizeDelay [protected]

stabilize interval (secs)

Definition at line 85 of file Chord.h.

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

// retries before neighbor considered failed

Definition at line 83 of file Chord.h.

Referenced by handleStabilizeTimerExpired(), and initializeOverlay().

Definition at line 88 of file Chord.h.

Referenced by getMaxNumSiblings(), handleRpcJoinResponse(), and initializeOverlay().


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