#include <Kademlia.h>
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 | |
NodeVector * | findNode (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. | |
KademliaBucket * | routingBucket (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 |
KademliaBucket * | siblingTable |
std::vector < KademliaBucket * > | routingTable |
int | numBuckets |
Friends | |
class | KademliaLookupListener |
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.
key | The key of the node |
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.
key | The key of the node | |
ensure | If true, the bucket allocation is ensured |
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.
handle | handle to add | |
isAlive | true, if it is known that the node is alive |
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.
key | Key of the Node |
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).
key | Node's key to remove | |
immediately | If true, the node is removed immediately |
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.
dest | destination node | |
msg | message to send |
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.
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.
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 |
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.
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().
Reimplemented from BaseOverlay.
00187 { 00188 return k; 00189 }
void Kademlia::handleTimerEvent | ( | cMessage * | msg | ) | [virtual] |
Processes "timer" self-messages.
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.
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.
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.
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. |
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.
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.
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
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).
x | Left-hand-side Key | |
y | Right-hand-side key |
Reimplemented from BaseOverlay.
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 }
friend class KademliaLookupListener [friend] |
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] |