Kademlia Class Reference

#include <Kademlia.h>

Inheritance diagram for Kademlia:

BaseOverlay BaseRpc TopologyVis RpcListener

List of all members.


Detailed Description

Kademlia overlay module.

Author:
Sebastian Mies

Public Member Functions

 ~Kademlia ()
void initializeOverlay (int stage)
 Initializes derived-class-attributes.
void finishOverlay ()
 collects statistical data in derived class
void joinOverlay ()
 Join the overlay with a given nodeID in thisNode.key.
bool isSiblingFor (const NodeHandle &node, const OverlayKey &key, int numSiblings, bool *err)
 Query if a node is among the siblings for a given key.
int getMaxNumSiblings ()
 Query the maximum number of siblings (nodes close to a key) that are maintained by this overlay protocol.
int getMaxNumRedundantNodes ()
 Query the maximum number of redundant next hop nodes that are returned by findNode().
void handleTimerEvent (cMessage *msg)
 Processes "timer" self-messages.
void handleUDPMessage (BaseOverlayMessage *msg)
 Processes messages from underlay.
bool handleRpc (BaseCallMessage *msg)
 Processes Remote-Procedure-Call invokation messages.

Protected Member Functions

NodeVectorfindNode (const OverlayKey &key, int numRedundantNodes, int numSiblings, BaseOverlayMessage *msg)
 Implements the find node call.
void handleRpcResponse (BaseResponseMessage *msg, int rpcId, simtime_t rtt)
 This method is called if an RPC response has been received.
void handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, int rpcId, const OverlayKey &destKey)
 This method is called if an RPC timeout has been reached.
void handleStabilizeTimerExpired (cMessage *msg)
 handle a expired stabilize timer
OverlayKey distance (const OverlayKey &x, const OverlayKey &y) const
 This method should implement the distance between two keys.
void updateTooltip ()
 updates information shown in GUI
virtual void lookupFinished ()

Protected Attributes

int k
int b
int s
int r
int removalDelay
int keyLength
double stabilizeDelay
cMessage * stabilizeTimer

Private Member Functions

void routingInit ()
void routingDeinit ()
int routingBucketIndex (const OverlayKey &key)
 Returns the index of the bucket the key would reside with respect to kademlia parameters.
KademliaBucketroutingBucket (const OverlayKey &key, bool ensure)
 Returns a Bucket or NULL if the bucket has not yet allocated.
bool routingAdd (const NodeHandle &handle, bool isAlive)
 Adds a node to the routing table.
bool routingRemove (const OverlayKey &key)
 Removes a node from the routing table.
bool routingTimeout (const OverlayKey &key, bool immediately=false)
 Removes a node after a number of timeouts or immediatly if immediately is true (behaves like routingRemove).
bool forwardMessageRecursive (const TransportAddress &dest, BaseRouteMessage *msg)
 Hook for forwarded message in recursive lookup mode.

Private Attributes

KeyDistanceComparator
< KeyXorMetric > * 
comparator
KademliaBucketsiblingTable
std::vector
< KademliaBucket * > 
routingTable
int numBuckets

Friends

class KademliaLookupListener

Constructor & Destructor Documentation

Kademlia::~Kademlia (  ) 

00082 {
00083 }


Member Function Documentation

void Kademlia::routingInit (  )  [private]

00123 {
00124     // set join state
00125     state = JOIN;
00126 
00127     // setup comparator
00128     comparator = new KeyDistanceComparator<KeyXorMetric>( thisNode.getKey() );
00129 
00130     // set key length
00131     this->keyLength = OverlayKey::getLength();
00132 
00133     // calculate number of buckets: ( (2^b)-1 ) * ( keylength / b )
00134     this->numBuckets = ( (1L << b) - 1L ) * (keyLength / b );
00135 
00136     // init routing and sibling table
00137     this->siblingTable = new KademliaBucket ( s * 5, comparator );
00138 
00139     // initialize pointers
00140     this->routingTable.assign(this->numBuckets, (KademliaBucket*)NULL);
00141 
00142     WATCH_VECTOR(*siblingTable);
00143     WATCH_VECTOR(routingTable);
00144 
00145     updateTooltip();
00146 }

void Kademlia::routingDeinit (  )  [private]

00149 {
00150     // set refresh state (to prevent registering this node
00151     // at the BootstrapOracle in lookupFinished(), if routingDeinit()
00152     // was called, because this node gets deleted
00153     state = REFRESH;
00154 
00155     // remove current node handle from the bootstrap list
00156     if (!thisNode.key.isUnspecified()) {
00157         removeBootstrapNode(thisNode);
00158     }
00159 
00160     // delete buckets
00161     for (uint i=0; i<this->routingTable.size(); i++) {
00162         if (this->routingTable[i] != NULL) {
00163             delete this->routingTable[i];
00164             this->routingTable[i] = NULL;
00165         }
00166     }
00167     this->routingTable.clear();
00168 
00169     // clear sibling table
00170     if (this->siblingTable != NULL) {
00171         delete this->siblingTable;
00172         this->siblingTable = NULL;
00173     }
00174 
00175     if (comparator != NULL) {
00176         delete comparator;
00177         comparator = NULL;
00178     }
00179 }

int Kademlia::routingBucketIndex ( const OverlayKey key  )  [private]

Returns the index of the bucket the key would reside with respect to kademlia parameters.

Parameters:
key The key of the node
Returns:
int The index of the bucket
00192 {
00193     // calculate XOR distance
00194     OverlayKey delta = key ^ getThisNode().getKey();
00195 
00196     // find first subinteger that is not zero...
00197     int i;
00198     for (i = key.getLength()-b; i>=0 && delta.get(i, b) == 0; i-=b)
00199         ;
00200     if (i<0)
00201         return -1;
00202     return (i / b) * ( (1 << b) - 1 ) + (delta.get(i, b) - 1 );
00203 }

KademliaBucket * Kademlia::routingBucket ( const OverlayKey key,
bool  ensure 
) [private]

Returns a Bucket or NULL if the bucket has not yet allocated.

If ensure is true, the bucket allocation is ensured.

Parameters:
key The key of the node
ensure If true, the bucket allocation is ensured
Returns:
Bucket* The Bucket
00206 {
00207     // get bucket index
00208     int num = routingBucketIndex(key);
00209     if (num < 0)
00210         return NULL;
00211 
00212     // get bucket and allocate if neccessary
00213     KademliaBucket* bucket = routingTable[ num ];
00214     if (bucket == NULL && ensure)
00215         bucket = routingTable[ num ] = new KademliaBucket( k, comparator );
00216 
00217     // return bucket
00218     return bucket;
00219 }

bool Kademlia::routingAdd ( const NodeHandle handle,
bool  isAlive 
) [private]

Adds a node to the routing table.

Parameters:
handle handle to add
isAlive true, if it is known that the node is alive
Returns:
true, if the node was known or has been added
00222 {
00223     // never add unspecified node handles
00224     if (handle.isUnspecified() || handle.key == getThisNode().getKey() )
00225         return false;
00226 
00227     // bucket index
00228     KademliaBucket::iterator i;
00229     bool result = false;
00230 
00231     // convert node handle
00232     KademliaNodeHandle kadHandle = handle;
00233     kadHandle.setLastSeen(simulation.simTime() );
00234 
00235     /* check if node is already a sibling -----------------------------------*/
00236     if ( (i = siblingTable->findIterator(handle.getKey() ) )
00237             != siblingTable->end() ) {
00238 
00239         // not alive? -> do not change routing information
00240         if (!isAlive)
00241             return true;
00242 
00243         // refresh sibling
00244         (*i) = kadHandle;
00245         return true;
00246     }
00247 
00248     /* check if node is already in a bucket ---------------------------------*/
00249     KademliaBucket* bucket = routingBucket(handle.getKey(), false);
00250     if (bucket != NULL && (i = bucket->findIterator(handle.getKey() ) )
00251             != bucket->end() ) {
00252 
00253         // not alive? -> do not change routing information
00254         if (!isAlive)
00255             return true;
00256 
00257         // remove old handle
00258         bucket->erase(i);
00259 
00260         // re-add to tail 
00261         bucket->push_back(kadHandle);
00262 
00263         return true;
00264     }
00265 
00266     /* check if node can be added to the sibling list -----------------------*/
00267     if (siblingTable->isAddable(handle) ) {
00268 
00269         // check if sibling list is full so a handle is preemted from the list
00270         if (siblingTable->isFull()) {
00271 
00272             // get handle thats about to be preempted
00273             KademliaNodeHandle& oldHandle = siblingTable->back();
00274 
00275             // add handle to the sibling list
00276             siblingTable->add(kadHandle);
00277 
00278             // TODO: only call update() for real siblings
00279             callUpdate(oldHandle, false);
00280             callUpdate(kadHandle, true);
00281 
00282             // change, so that the preemted handle is added to a bucket
00283             kadHandle = oldHandle;
00284 
00285             // return always true, since the handle has been added
00286             result |= true;
00287         } else {
00288 
00289             // simply add the handle and stop
00290             siblingTable->add(kadHandle);
00291             callUpdate(kadHandle, true);
00292             updateTooltip();
00293             return true;
00294         }
00295         updateTooltip();
00296     }
00297 
00298     /* add node to the appropritate bucket, if not full ---------------------*/
00299     bucket = routingBucket(kadHandle.getKey(), true);
00300     if (!bucket->isFull()) {
00301         EV << "Kademlia::routingAdd(): Adding new node " << kadHandle
00302         << " to bucket " << routingBucketIndex(kadHandle.getKey()) << endl;
00303         bucket->push_back(kadHandle);
00304         result |= true;
00305     }
00306     return result;
00307 }

bool Kademlia::routingRemove ( const OverlayKey key  )  [private]

Removes a node from the routing table.

Parameters:
key Key of the Node
Returns:
true, if the node has been removed
00310 {
00311     return routingTimeout(key, true);
00312 }

bool Kademlia::routingTimeout ( const OverlayKey key,
bool  immediately = false 
) [private]

Removes a node after a number of timeouts or immediatly if immediately is true (behaves like routingRemove).

Parameters:
key Node's key to remove
immediately If true, the node is removed immediately
Returns:
true, if the node has been removed
00315 {
00316     // key unspecified? yes -> ignore
00317     if (key.isUnspecified())
00318         return false;
00319 
00320     // bucket index
00321     KademliaBucket::iterator i;
00322 
00323     /* check if the node is one of the siblings -----------------------------*/
00324     if ( (i = siblingTable->findIterator(key) ) != siblingTable->end() ) {
00325 
00326         i->incStaleCount();
00327         if (i->getStaleCount() > removalDelay || immediately) {
00328             // remove from sibling table
00329             callUpdate(*i, false);
00330             updateTooltip();
00331             siblingTable->erase(i);
00332 
00333             // try to refill with new closest contact
00334             // TODO!
00335             return true;
00336         }
00337     }
00338 
00339     /* check if node is already in a bucket ---------------------------------*/
00340     KademliaBucket* bucket = routingBucket(key, false);
00341     if (bucket != NULL && (i = bucket->findIterator(key) ) != bucket->end() ) {
00342 
00343         i->incStaleCount();
00344         if (i->getStaleCount() > removalDelay || immediately) {
00345             // remove from routing table
00346             bucket->erase(i);
00347             return true;
00348         }
00349     }
00350     return false;
00351 }

bool Kademlia::forwardMessageRecursive ( const TransportAddress dest,
BaseRouteMessage *  msg 
) [private, virtual]

Hook for forwarded message in recursive lookup mode.

This hook is called just before a message is forwarded to a next hop or if the message is at its destination just before it is sent to the app. Default implementation just returns true. This hook can for example be used to detect failed nodes and call handleFailedNode() before the actual forwarding takes place.

Parameters:
dest destination node
msg message to send
Returns:
true, if message should be forwarded; false, if message will be forwarded later by an other function or message has been discarded

Reimplemented from BaseOverlay.

00450 {
00451     if (msg->getSrcNode() != thisNode) {
00452         routingAdd(msg->getSrcNode(), true);
00453 
00454         NodeVector* nextHops = findNode(msg->getDestKey(), k, s, msg);
00455         KademliaRoutingInfoMessage* kadRoutingInfoMsg =
00456                 new KademliaRoutingInfoMessage();
00457 
00458         kadRoutingInfoMsg->setSrcNode(thisNode);
00459         kadRoutingInfoMsg->setNextHopsArraySize(nextHops->size());
00460         for (uint i = 0; i < nextHops->size(); i++) {
00461             kadRoutingInfoMsg->setNextHops(i, (*nextHops)[i]);
00462         }
00463 
00464         sendMessageToUDP(msg->getSrcNode(), kadRoutingInfoMsg);
00465     }
00466     return true;
00467 }

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

Initializes derived-class-attributes.


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

Parameters:
stage the init stage

Reimplemented from BaseOverlay.

00063 {
00064     if (stage != MIN_STAGE_OVERLAY)
00065         return;
00066 
00067     // setup kademlia parameters
00068     this->stabilizeDelay = par("stabilizeDelay");
00069     this->removalDelay = par("removalDelay");
00070     this->k = par("k");
00071     this->b = par("b");
00072     this->s = par("s");
00073 
00074     // self-messages
00075     stabilizeTimer = new cMessage("stabilizeTimer");
00076 
00077     comparator = NULL;
00078     siblingTable = NULL;
00079 }

void Kademlia::finishOverlay (  )  [virtual]

collects statistical data in derived class

Reimplemented from BaseOverlay.

00086 {
00087     // deinitialize routing
00088     routingDeinit();
00089 
00090     // remove comparator and timer
00091     cancelEvent(stabilizeTimer);
00092     delete comparator;
00093     delete stabilizeTimer;
00094 }

void Kademlia::joinOverlay (  )  [virtual]

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

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

Reimplemented from BaseOverlay.

00097 {
00098     // initialize routing
00099     routingDeinit();
00100     routingInit();
00101 
00102     // add bootstrap nodes
00103     //for (int i=0; i < k; i++) {
00104 
00105     NodeHandle handle = getBootstrapNode();
00106     if (!handle.isUnspecified()) {
00107         routingAdd(handle, true);
00108     } else {
00109         // as the first packet leaves the node, this node is accessible
00110         registerBootstrapNode(thisNode);
00111         state = READY;
00112     }
00113     //    }
00114 
00115     // schedule refresh timer
00116     cancelEvent(stabilizeTimer);
00117     scheduleAt(simulation.simTime(), stabilizeTimer);
00118 }

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

Query if a node is among the siblings for a given key.

Query if a node is among the siblings for a given key. This means, that the nodeId of this node is among the closest numSiblings nodes to the key and that by a local findNode() call all other siblings to this key can be retrieved.

Parameters:
node the NodeHandle
key destination key
numSiblings The nodes knows all numSiblings nodes close to this key
err return false if the range could not be determined
Returns:
bool true, if the node is responsible for the key.

Reimplemented from BaseOverlay.

00355 {
00356     if (key.isUnspecified())
00357         error("Kademlia::isSiblingFor(): key is unspecified!");
00358 
00359     if (state != READY) {
00360         *err = true;
00361         return false;
00362     }
00363 
00364     if (numSiblings > getMaxNumSiblings()) {
00365         opp_error("Kademlia::isSiblingFor(): numSiblings too big!");
00366     }
00367     // set default number of siblings to consider
00368     if (numSiblings == -1)
00369         numSiblings = getMaxNumSiblings();
00370 
00371     if (numSiblings == 0) {
00372         *err = false;
00373         return (node.getKey() == key);
00374     }
00375 
00376     // return false, if sibling table is not full
00377     if (siblingTable->size() <= (uint)numSiblings ) {
00378         //       *err = true;
00379         //        return false;
00380         //cout << "sibling table not full" << endl;
00381     }
00382 
00383     KeyDistanceComparator<KeyXorMetric>* comp =
00384             new KeyDistanceComparator<KeyXorMetric>( key );
00385 
00386     // create result vector
00387     NodeVector* result = new NodeVector( numSiblings, comp );
00388 
00389     //TODO now:searching all buckets
00390     // add items from buckets
00391     int mainIndex = routingBucketIndex(key);
00392 
00393     for (int i=1; !result->isFull() && i<numBuckets*3; i++) {
00394         int index = mainIndex + ( ((i&1)==1) ? -1 : 1 ) * (i / 2 );
00395         if (index<0 || index>=numBuckets)
00396             continue;
00397 
00398         // add bucket to result vector
00399         KademliaBucket* bucket = routingTable[index];
00400         if (bucket!=NULL) {
00401             for (KademliaBucket::iterator i=bucket->begin(); i!=bucket->end(); i++) {
00402                 result->add( *i);
00403                 EV << "Kademlia::routingGetClosestNodes(): Adding "
00404                 << *i << " from bucket " << index << endl;
00405             }
00406         }
00407     }
00408 
00409     for (KademliaBucket::iterator i=siblingTable->begin(); i
00410             != siblingTable->end(); i++)
00411         result->add( *i);
00412 
00413     // add local node
00414     result->add(thisNode);
00415 
00416     *err = false;
00417     delete comp;
00418 
00419     if (result->contains(node.key)) {
00420         /*
00421          if (numSiblings == 1) {
00422          std::cout << siblingTable->size() << " " << result->size() << std::endl;
00423          for (NodeVector::iterator i = result->begin();
00424          i != result->end(); i++)
00425          std::cout << *i << std::endl;
00426          std::cout << std::endl;
00427          }
00428          */
00429         delete result;
00430         return true;
00431     } else {
00432         delete result;
00433         return false;
00434     }
00435 
00436     // the following doesn't work!!!
00437 
00438     // get distance from this node
00439     //    OverlayKey d1 = getThisNode().getKey()^key;
00440 
00441     // get siblings range
00442     //    OverlayKey d2 = getThisNode().getKey()^
00443     //                    (siblingTable->at(numSiblings).getKey());
00444 
00445     //    return d1 < d2;
00446 }

int Kademlia::getMaxNumSiblings (  )  [virtual]

Query the maximum number of siblings (nodes close to a key) that are maintained by this overlay protocol.

Returns:
int number of siblings.

Reimplemented from BaseOverlay.

00182 {
00183     return s;
00184 }

int Kademlia::getMaxNumRedundantNodes (  )  [virtual]

Query the maximum number of redundant next hop nodes that are returned by findNode().

Returns:
int number of redundant nodes returned by findNode().

Reimplemented from BaseOverlay.

00187 {
00188     return k;
00189 }

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

Processes "timer" self-messages.

Parameters:
msg A self-message

Reimplemented from BaseOverlay.

00540 {
00541     if (msg->isName("stabilizeTimer")) {
00542         handleStabilizeTimerExpired(msg);
00543     }
00544 }

void Kademlia::handleUDPMessage ( BaseOverlayMessage *  msg  )  [virtual]

Processes messages from underlay.

Parameters:
msg Message from UDP

Reimplemented from BaseOverlay.

00547 {
00548     OverlayCtrlInfo* ctrlInfo =
00549             check_and_cast<OverlayCtrlInfo*>(msg->removeControlInfo());
00550     KademliaRoutingInfoMessage* kadRoutingInfoMsg = check_and_cast<
00551             KademliaRoutingInfoMessage*>(msg);
00552 
00553     routingAdd(kadRoutingInfoMsg->getSrcNode(), true);
00554 
00555     for (uint i = 0; i < kadRoutingInfoMsg->getNextHopsArraySize(); i++) {
00556         routingAdd(kadRoutingInfoMsg->getNextHops(i), true);
00557     }
00558 
00559     delete ctrlInfo;
00560     delete msg;
00561 }

bool Kademlia::handleRpc ( BaseCallMessage *  msg  )  [virtual]

Processes Remote-Procedure-Call invokation messages.


This method should be overloaded when the overlay provides RPC functionality.

Returns:
true, if rpc has been handled

Reimplemented from BaseRpc.

00565 {
00566     RPC_SWITCH_START( msg )
00567     RPC_ON_CALL( Ping ) {
00568         // add active node
00569         routingAdd( _PingCall->getSrcNode(), true );
00570         break;
00571     }
00572     RPC_ON_CALL(FindNode)
00573     {
00574         // add active node
00575         routingAdd(_FindNodeCall->getSrcNode(), true);
00576         break;
00577     }
00578     RPC_SWITCH_END( )
00579     return false;
00580 }

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

Implements the find node call.

This method simply returns the closest nodes known in the corresponding routing topology. If the node is a sibling for this key (isSiblingFor(key) = true), this method returns all numSiblings siblings, with the closest neighbor to the key first.

Parameters:
key The lookup key.
numRedundantNodes Maximum number of next hop nodes to return.
numSiblings number of siblings to return
msg A pointer to the BaseRouteMessage or FindNodeCall message of this lookup.
Returns:
NodeVector with closest nodes.

Reimplemented from BaseOverlay.

00471 {
00472     if ((numRedundantNodes > getMaxNumRedundantNodes()) || (numSiblings
00473             > getMaxNumSiblings())) {
00474 
00475         opp_error("(Kademlia::findNode()) numRedundantNodes or numSiblings "
00476             "too big!");
00477     }
00478 
00479     // create temporary comparator
00480     KeyDistanceComparator<KeyXorMetric>* comp =
00481             new KeyDistanceComparator<KeyXorMetric>( key );
00482 
00483     // select result set size
00484     bool err;
00485 
00486     int resultSize = isSiblingFor(thisNode, key, numSiblings, &err) ?
00487                 (numSiblings ? numSiblings : 1) : numRedundantNodes;
00488 
00489     // create result vector
00490     NodeVector* result = new NodeVector( resultSize, comp );
00491 
00492     // add items from buckets
00493     int mainIndex = routingBucketIndex(key);
00494 
00495     for (int i=1; !result->isFull() && i<numBuckets*3; i++) {
00496         int index = mainIndex + ( ((i&1)==1) ? -1 : 1 ) * (i / 2 );
00497         if (index<0 || index>=numBuckets)
00498             continue;
00499 
00500         // add bucket to result vector
00501         KademliaBucket* bucket = routingTable[index];
00502         if (bucket!=NULL) {
00503             for (KademliaBucket::iterator i=bucket->begin(); i!=bucket->end(); i++) {
00504                 result->add( *i);
00505                 EV << "Kademlia::routingGetClosestNodes(): Adding "
00506                 << *i << " from bucket " << index << endl;
00507             }
00508         }
00509     }
00510 
00511     // add nodes from sibling table 
00512     for (KademliaBucket::iterator i=siblingTable->begin(); i
00513             != siblingTable->end(); i++)
00514         result->add( *i);
00515     //TODO: Only add if needed!!
00516 
00517     // add local node
00518     result->add(thisNode);
00519 
00520     if (isSiblingFor(thisNode, key, numSiblings, &err)) {
00521         if ((*result)[0].key != key) {
00522             EV << "!!!!! Node " << (*result)[0] << " should be close to "
00523             << key;
00524             if (siblingTable->contains(key)) {
00525                 EV << " +++" << endl;
00526             } else {
00527                 EV << " ---" << endl;
00528             }
00529         }
00530     }
00531 
00532     delete comp;
00533     return result;
00534 }

void Kademlia::handleRpcResponse ( BaseResponseMessage *  msg,
int  rpcId,
simtime_t  rtt 
) [protected, virtual]

This method is called if an RPC response has been received.

Parameters:
msg The response message.
rpcId The RPC id.
rtt The Round-Trip-Time of this RPC

Reimplemented from RpcListener.

00585 {
00586     // add node that reponded
00587     routingAdd(msg->getSrcNode(), true);
00588 
00589     RPC_SWITCH_START( msg )
00590     RPC_ON_RESPONSE( Ping ) {
00591         // add active node
00592         routingAdd( _PingResponse->getSrcNode(), true );
00593         break;
00594     }
00595     RPC_ON_RESPONSE(FindNode)
00596     {
00597         // add active node
00598         routingAdd(_FindNodeResponse->getSrcNode(), true);
00599         // add inactive nodes
00600         for (uint i=0; i<_FindNodeResponse->getClosestNodesArraySize(); i++)
00601             routingAdd(_FindNodeResponse->getClosestNodes(i), false);
00602         break;
00603     }
00604     RPC_SWITCH_END( )
00605 }

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

This method is called if an RPC timeout has been reached.

Parameters:
msg The original RPC message.
dest The destination node
rpcId The RPC id.
destKey the destination OverlayKey

Reimplemented from RpcListener.

00610 {
00611     RPC_SWITCH_START( msg )
00612     RPC_ON_CALL( Ping ) {
00613         routingTimeout( destKey );
00614         break;
00615     }
00616     RPC_ON_CALL(FindNode)
00617     {
00618         routingTimeout(destKey);
00619         break;
00620     }
00621     RPC_SWITCH_END( )
00622 }

void Kademlia::handleStabilizeTimerExpired ( cMessage *  msg  )  [protected]

handle a expired stabilize timer

Parameters:
msg the timer self-message
00637 {
00638     if (state == READY)
00639         state = REFRESH;
00640 
00641     // refresh buckets
00642     createLookup()->lookup(~getThisNode().getKey(), getMaxNumSiblings(), 0, 0,
00643                 new KademliaLookupListener(this));
00644     createLookup()->lookup(getThisNode().getKey(), getMaxNumSiblings(), 0, 0,
00645                 new KademliaLookupListener(this));
00646     createLookup()->lookup(getThisNode().getKey() + OverlayKey::ONE, 0, 0, 0,
00647                 new KademliaLookupListener(this));
00648 
00649     for (int i=0; i<20; i++) {
00650         createLookup()->lookup(getThisNode().getKey() ^ 
00651                 (OverlayKey::ONE<<(keyLength-i-1)), 0, 0, 0,
00652                 new KademliaLookupListener(this));
00653     }
00654 
00655     // refresh sibling table
00656     for (int i = 0; i < s && i < (int)siblingTable->size(); i++) {
00657         NodeHandle& handle = siblingTable->at(i);
00658         FindNodeCall* findNodeCall = new FindNodeCall();
00659         findNodeCall->setLookupKey(handle.getKey() );
00660         findNodeCall->setSrcNode(getThisNode() );
00661         findNodeCall->setNumRedundantNodes(getMaxNumRedundantNodes() );
00662         findNodeCall->setNumSiblings(getMaxNumSiblings() );
00663         findNodeCall->setLength(FINDNODECALL_L(call) );
00664 
00665         RECORD_STATS(numFindNodeSent++;
00666                      bytesFindNodeSent += findNodeCall->byteLength());
00667 
00668         sendUdpRpcCall(handle, findNodeCall);
00669     }
00670 
00671     if (state == REFRESH)
00672         state = READY;
00673 
00674     // schedule next stabilization process
00675     cancelEvent(stabilizeTimer);
00676     scheduleAt(simulation.simTime() + stabilizeDelay, stabilizeTimer);
00677 }

OverlayKey Kademlia::distance ( const OverlayKey x,
const OverlayKey y 
) const [protected, virtual]

This method should implement the distance between two keys.

It may be overloaded to implement a new metric. The default implementation uses the standard-metric d = abs(x-y).

Parameters:
x Left-hand-side Key
y Right-hand-side key
Returns:
OverlayKey Distance between x and y

Reimplemented from BaseOverlay.

00681 {
00682     return x^y;
00683 }

void Kademlia::updateTooltip (  )  [protected]

updates information shown in GUI

00686 {
00687     if (ev.isGUI()) {
00688         std::stringstream ttString;
00689 
00690         // show our nodeId in a tooltip
00691         ttString << "This: " << thisNode << endl << "Siblings: "
00692                 << siblingTable->size();
00693 
00694         parentModule()->parentModule()->displayString().
00695         setTagArg("tt", 0, ttString.str().c_str());
00696         parentModule()->displayString().
00697         setTagArg("tt", 0, ttString.str().c_str());
00698         displayString().setTagArg("tt", 0, ttString.str().c_str());
00699     }
00700 }

void Kademlia::lookupFinished (  )  [protected, virtual]

00625 {
00626 
00627     if (state == JOIN) {
00628         // registerBootstrapNode( thisNode );
00629         setOverlayReady(true);
00630     }
00631 
00632     state = READY;
00633 }


Friends And Related Function Documentation

friend class KademliaLookupListener [friend]


Member Data Documentation

KeyDistanceComparator<KeyXorMetric>* Kademlia::comparator [private]

KademliaBucket* Kademlia::siblingTable [private]

std::vector<KademliaBucket*> Kademlia::routingTable [private]

int Kademlia::numBuckets [private]

int Kademlia::k [protected]

int Kademlia::b [protected]

int Kademlia::s [protected]

int Kademlia::r [protected]

int Kademlia::removalDelay [protected]

int Kademlia::keyLength [protected]

double Kademlia::stabilizeDelay [protected]

cMessage* Kademlia::stabilizeTimer [protected]


The documentation for this class was generated from the following files:
Generated on Thu Apr 17 13:19:29 2008 for ITM OverSim by  doxygen 1.5.3