BaseLookup Class Reference

#include <BaseLookup.h>

Inheritance diagram for BaseLookup:

RpcListener AbstractLookup Comparator< OverlayKey >

List of all members.


Detailed Description

This class implements a basic greedy lookup strategy.

It uses the standard metric for greedy behaviour. If another metric is needed, the distance function can be replaced by overriding the distance method.

Author:
Sebastian Mies

Public Member Functions

 BaseLookup (BaseOverlay *overlay, const BaseLookupConfiguration &config, const cObject *findNodeExt=NULL)
virtual ~BaseLookup ()
void lookup (const OverlayKey &key, int numSiblings=1, int hopCountMax=0, int retries=0, LookupListener *listener=NULL)
 Lookup siblings for a key.
const NodeVectorgetResult () const
 Returns the result of the lookup.
bool isValid () const
 Returns true, if the lookup was successful.
void abortLookup ()
 Aborts a running lookup.
uint getAccumulatedHops () const
 Returns the total number of hops for all lookup paths.

Protected Types

typedef hash_map
< TransportAddress,
RpcInfoVector,
TransportAddress::hashFcn
RpcInfoMap

Protected Member Functions

virtual BasePathLookupcreatePathLookup ()
 This method creates a new path lookup.
virtual FindNodeCall * createInitialRpcCall ()
 This method creates the initial FindNode RPC call message used to query the local findNode() method.
int compare (const OverlayKey &lhs, const OverlayKey &rhs) const
 compares two OverlayKeys and indicates which one is closer to the key to look up
bool addSibling (const NodeHandle &handle)
 adds a node to the siblings NodeVector
void setVisited (const TransportAddress &addr, bool visited=true)
 adds/deletes visited nodes to/from the visited TransportAddress::Set
bool getVisited (const TransportAddress &addr)
 indicates if the specified node has been visited before
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=OverlayKey::UNSPECIFIED_KEY)
 This method is called if an RPC timeout has been reached.
void sendRpc (const NodeHandle &handle, FindNodeCall *call, BasePathLookup *listener, int rpcId)
void start ()
void stop ()
void checkStop ()

Protected Attributes

OverlayKey key
 key to lookup
BaseOverlayoverlay
 ptr to overlay
BaseLookupConfiguration config
 lookup configuration
cObject * firstCallExt
 additional info for first findNode()
LookupListenerlistener
 lookup listener
vector
< BasePathLookup * > 
paths
 parallel paths
bool finished
 true, if lookup is finished
bool success
 true, if lookup was successful
bool running
 true, if lookup is running
int retries
 number of retries, if lookup fails
uint finishedPaths
 number of finished paths
uint successfulPaths
 number of successful paths
uint accumulatedHops
 total number of hops (for all paths)
NodeVector siblings
 closest nodes
TransportAddress::Set visited
 nodes already visited
int numSiblings
 number of siblings
int hopCountMax
 maximum hop count
RpcInfoMap rpcs

Friends

class BasePathLookup
class BaseOverlay

Classes

class  RpcInfo
class  RpcInfoVector

Member Typedef Documentation

typedef hash_map<TransportAddress, RpcInfoVector, TransportAddress::hashFcn> BaseLookup::RpcInfoMap [protected]


Constructor & Destructor Documentation

BaseLookup::BaseLookup ( BaseOverlay overlay,
const BaseLookupConfiguration config,
const cObject *  findNodeExt = NULL 
)

00046                                                     :
00047 overlay(overlay),
00048 config(config),
00049 firstCallExt(NULL),
00050 finished(false),
00051 success(false),
00052 running(false)
00053 {
00054     if (findNodeExt) firstCallExt = static_cast<cObject*>(findNodeExt->dup());
00055     if (config.secure)
00056         cout << "WARNING: Secure BaseLookup is still under development!!"
00057         << endl;
00058 }

BaseLookup::~BaseLookup (  )  [virtual]

00061 {
00062     stop();
00063     delete firstCallExt;
00064     overlay->removeLookup(this);
00065 
00066 //    std::cout << "time: " << simulation.simTime() << "deleting " << this << endl;
00067 }


Member Function Documentation

BasePathLookup * BaseLookup::createPathLookup (  )  [protected, virtual]

This method creates a new path lookup.

It may be overloaded to enhance BasePathLookup with some new information/features.

Returns:
The new path lookup
00263 {
00264     return new BasePathLookup(this);
00265 }

FindNodeCall * BaseLookup::createInitialRpcCall (  )  [protected, virtual]

This method creates the initial FindNode RPC call message used to query the local findNode() method.

It may be overridden to allow additional information being attached before the lookup procedure actually starts

Returns:
newly allocated FindNodeCall message
00268 {
00269     FindNodeCall* call = new FindNodeCall("FindNodeCall");
00270     if (firstCallExt)
00271         call->addObject(static_cast<cObject*>(firstCallExt->dup()));
00272     return call;
00273 }

int BaseLookup::compare ( const OverlayKey lhs,
const OverlayKey rhs 
) const [protected, virtual]

compares two OverlayKeys and indicates which one is closer to the key to look up

Parameters:
lhs the first OverlayKey
rhs the second OverlayKey
Returns:
-1 if rhs is closer, 0 if lhs and rhs are equal and 1 if rhs is farther away to the key to lookup

Reimplemented from Comparator< OverlayKey >.

00280 { 
00281     return overlay->distance( key, lhs ).compareTo( overlay->distance(key,
00282                                                                       rhs));
00283 }

bool BaseLookup::addSibling ( const NodeHandle handle  )  [protected]

adds a node to the siblings NodeVector

Parameters:
handle NodeHandle of the node to add
Returns:
true if operation was succesfull, false otherwise
00290 {
00291     bool result = false;
00292 
00293     if (numSiblings == 0) {
00294         if (handle.key == key) {
00295             siblings.clear();
00296             siblings.push_back( handle );
00297             result = true;
00298         }
00299     } else {
00300         if (config.parallelPaths==1) {
00301             result = true;
00302             if (!siblings.isFull()) {
00303                 siblings.push_back(handle);
00304             }
00305         } else {
00306             result = this->siblings.add(handle);
00307         }
00308     }
00309 
00310     return result;
00311 }

void BaseLookup::setVisited ( const TransportAddress addr,
bool  visited = true 
) [protected]

adds/deletes visited nodes to/from the visited TransportAddress::Set

Parameters:
addr TransportAddress of the node to add
visited if true node is addes, else node is erased
00314 {
00315     if (visited)
00316         this->visited.insert( addr );
00317     else
00318         this->visited.erase( addr );
00319 }

bool BaseLookup::getVisited ( const TransportAddress addr  )  [protected]

indicates if the specified node has been visited before

Parameters:
addr TransportAddress of the node
Returns:
false if addr is not in visited, true otherwise
00322 {
00323     return this->visited.count(addr) != 0;
00324 }

void BaseLookup::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.

00332 {
00333     // check flags
00334     if (finished || !running)
00335         return;
00336 
00337     // get source, cast messages and mark node as visited
00338     const TransportAddress& src = *(static_cast<const TransportAddress*>(
00339                                                                         &(msg->getSrcNode())));
00340     FindNodeResponse* findNodeResponse = dynamic_cast<FindNodeResponse*>(msg);
00341     PingResponse* pingResponse = dynamic_cast<PingResponse*>(msg);
00342     FailedNodeResponse* failedNodeResponse =
00343     dynamic_cast<FailedNodeResponse*>(msg);
00344 
00345     setVisited( src );
00346 
00347     if ( findNodeResponse != NULL || pingResponse != NULL) {
00348         // add authentificated sibling
00349         // addSibling( src );
00350     }
00351 
00352     // handle find node response
00353     if ( findNodeResponse != NULL ) {
00354 //      std::cout << "time: " << simulation.simTime() << " node: " << overlay->thisNode << " this: " << this << " received rpc with nonce: " << findNodeResponse->getNonce() << " from: " << findNodeResponse->getSrcNode() << endl;
00355 
00356         // check if rpc info is available, no -> exit
00357         if (rpcs.count(src)==0)
00358             return;
00359 
00360         // get info
00361         RpcInfoVector infos = rpcs[src];
00362         rpcs.erase(src);
00363 
00364         // add to siblinglist if not secure
00365         //      if (!config.secure)
00366         //          for (uint i=0; i<findNodeResponse->getClosestNodesArraySize(); i++)
00367         //              addSibling( findNodeResponse->getClosestNodes(i) );
00368 
00369         // iterate
00370         bool rpcHandled = false;
00371         for (uint i=0; i<infos.size(); i++) {
00372 
00373             // get info
00374             const RpcInfo& info = infos[i];
00375 
00376             // do not handle finished paths
00377             if (info.path->finished)
00378                 continue;
00379 
00380             // check if path accepts the message
00381             if ( !rpcHandled && info.path->accepts( info.vrpcId ) ) {
00382                 info.path->handleResponse( findNodeResponse );
00383                 rpcHandled = true;
00384             } else {
00385                 info.path->handleTimeout( NULL,
00386                                           findNodeResponse->getSrcNode(), info.vrpcId );
00387             }
00388 
00389             // count finished and successful paths
00390             if (info.path->finished) {
00391                 finishedPaths++;
00392 
00393                 // count total number of hops
00394                 accumulatedHops += info.path->hops;
00395 
00396                 if (info.path->success)
00397                     successfulPaths++;
00398             }
00399 
00400         }
00401     }
00402 
00403 
00404     // handle failed node response
00405     if ( failedNodeResponse != NULL ) {
00406         cMessage* findNodeExt = NULL;
00407         if (failedNodeResponse->hasObject("findNodeExt")) {
00408             findNodeExt =
00409             (cMessage*)failedNodeResponse->removeObject("findNodeExt");
00410         }
00411         for (std::vector<BasePathLookup*>::iterator i = paths.begin();
00412             i != paths.end(); i++)
00413             (*i)->handleFailedNodeResponse( 
00414                 failedNodeResponse->getSrcNode(),
00415                 findNodeExt, failedNodeResponse->getTryAgain() 
00416             );
00417     }
00418 
00419     checkStop();
00420 }

void BaseLookup::handleRpcTimeout ( BaseCallMessage *  msg,
const TransportAddress dest,
int  rpcId,
const OverlayKey destKey = OverlayKey::UNSPECIFIED_KEY 
) [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.

00426 {
00427     // check flags
00428     if (finished || !running)
00429         return;
00430 
00431     // check if rpc info is available
00432     const TransportAddress& src = dest;
00433     if (rpcs.count(src)==0) {
00434         cout << "BaseLookup::handleRpcTimeout(): RPC Timeout, but node"
00435              << " is not in rpcs structure!" << endl;
00436         return;
00437     }
00438 
00439     RpcInfoVector infos = rpcs[src];
00440     rpcs.erase(src);  // ib
00441 
00442     // iterate
00443     for (uint i=0; i < infos.size(); i++) {
00444 
00445         const RpcInfo& info = infos[i];
00446 
00447         // do not handle finished paths
00448         if (info.path->finished)
00449             continue;
00450 
00451         // delegate timeout
00452         info.path->handleTimeout( msg, dest, info.vrpcId );
00453 
00454         // count total number of hops
00455         accumulatedHops += info.path->hops;
00456 
00457         // count finished and successful paths
00458         if (info.path->finished) {
00459             finishedPaths++;
00460             if (info.path->success)
00461                 successfulPaths++;
00462         }
00463     }
00464     checkStop();
00465 }

void BaseLookup::sendRpc ( const NodeHandle handle,
FindNodeCall *  call,
BasePathLookup listener,
int  rpcId 
) [protected]

00469 {
00470     // check flags
00471     if (finished || !running) {
00472         delete call;
00473         return;
00474     }
00475 
00476     // create rpc info
00477     RpcInfo info;
00478     info.path = listener;
00479     info.vrpcId = rpcId;
00480 
00481     // send new message
00482     if ( rpcs.count(handle) == 0 ) {
00483         RpcInfoVector newVector;
00484 
00485         if (overlay->measureNetwInitPhase ||
00486             !overlay->underlayConfigurator->isInit()) {
00487 
00488             overlay->numFindNodeSent++;
00489             overlay->bytesFindNodeSent += call->byteLength();
00490         }
00491 
00492         newVector.nonce = overlay->sendUdpRpcCall(handle, call, -1, 0, -1,
00493                                                   this);
00494 
00495 //      std::cout << "time: " << simulation.simTime() << " node: " << overlay->thisNode << " new rpc with nonce: " << newVector.nonce << " to: " << handle << endl;
00496         rpcs[handle] = newVector;
00497 //      setVisited(handle); // TODO ib
00498     } else {
00499         opp_error("BaseLookup::sendRpc(): RPC already sent...");
00500         delete call;
00501     }
00502 
00503     // register info
00504     rpcs[handle].push_back(info);
00505 }

void BaseLookup::start (  )  [protected]

00079 {
00080 //    std::cout << "time: " << simulation.simTime() << " start(): node: " << overlay->thisNode << " this: " << this  << " key: " << key << endl;
00081 
00082     // init params
00083     this->successfulPaths = 0;
00084     this->finishedPaths   = 0;
00085     this->accumulatedHops = 0;
00086 
00087     // init flags
00088     this->finished = false;
00089     this->success  = false;
00090     this->running  = true;
00091 
00092     // init siblings vector
00093     siblings = NodeVector( numSiblings == 0 ? 1 : numSiblings, this );
00094     visited.clear();
00095 
00096     // get local closest nodes
00097     FindNodeCall* call = createInitialRpcCall();
00098     NodeVector* nextHops = overlay->findNode(key, config.redundantNodes,
00099                                              numSiblings, call);
00100     bool err;
00101 
00102     setVisited(overlay->getThisNode());
00103 
00104     // if this node is new and no nodes are known -> stop lookup
00105     if (nextHops->size() == 0) {
00106         //std::cout << "BaseLookup: No next hops known" << endl;
00107         finished = true;
00108         success = false;
00109     } else if ((numSiblings == 0) && overlay->isSiblingFor(overlay->thisNode,
00110                                                            key, numSiblings,
00111                                                            &err)) {
00112         if (overlay->getThisNode().key == key) {
00113             addSibling(overlay->getThisNode() );
00114             success = true;
00115         } else {
00116             std::cout << "BaseLookup: numSiblings==0 and no node with this id"
00117                     << endl;
00118             success = false;
00119         }
00120         finished = true;
00121     }
00122     // finish lookup if the key is local and siblings are needed
00123     else if ( numSiblings != 0 && 
00124               overlay->isSiblingFor(overlay->thisNode, key, numSiblings, &err)
00125               && !config.secure) {
00126         
00127         for (uint i=0; i<nextHops->size(); i++) {
00128             addSibling( nextHops->at(i) );
00129         }
00130 
00131         // TODO: definition of hop count for iterative lookups is unclear
00132         // add one hop if destination node is our sibling
00133         if ( key != overlay->getThisNode().key ) {
00134             accumulatedHops++;
00135         }
00136 
00137         success = finished = true;
00138 
00139     }
00140 /* 
00141         // check if the node is found locally
00142         else if ( nextHops->contains(key) && !config.secure ) {
00143 
00144         // node is one of our siblings
00145         addSibling( nextHops->find( key ) );
00146 
00147         // TODO: definition of hop count for iterative lookups is unclear
00148         // add one hop if destination node is our sibling
00149         if ( key != overlay->getThisNode().key )
00150             accumulatedHops++;
00151 
00152         success = true;
00153         finished = true;
00154     }
00155 */
00156 
00157     // if the key was local or belongs to one of our siblings we are finished
00158     if (finished) {
00159         // UGLY - calls stop and finishs the lookup
00160         delete nextHops;
00161         delete call;
00162         delete this;
00163         return;
00164     }
00165 
00166 
00167     // remove find node extensions
00168     cMessage* findNodeExt = NULL;
00169     if (call->hasObject("findNodeExt"))
00170         findNodeExt = (cMessage*)call->removeObject("findNodeExt");
00171     delete call;
00172 
00173     // distribution of nodes to paths
00174     uint n = nextHops->size() / config.parallelPaths;
00175 
00176     // not enough nodes for all paths? -> reduce number of parallel paths
00177     if ( n == 0 ) {
00178         config.parallelPaths = nextHops->size();
00179         n = 1;
00180     }
00181 
00182     // create parallel paths
00183     int j=0;
00184     for (int i=0; i<config.parallelPaths; i++) {
00185 
00186         // create state
00187         BasePathLookup* pathLookup = new BasePathLookup( this );
00188         paths.push_back( pathLookup );
00189 
00190         // populate next hops
00191         for ( uint k=0; k<n; k++, j++ )
00192             pathLookup->add( nextHops->at(j) );
00193 
00194         // send initial rpcs
00195         pathLookup->sendRpc( config.parallelRpcs, findNodeExt );
00196     }
00197     delete nextHops;
00198     delete findNodeExt;
00199 }

void BaseLookup::stop (  )  [protected]

00202 {
00203     // only stop if running
00204     if (!running)
00205         return;
00206 
00207     // cancel pending rpcs
00208     for (RpcInfoMap::iterator i = rpcs.begin(); i != rpcs.end(); i++) {
00209 //      std::cout << "time: " << simulation.simTime()     << " node: " << overlay->thisNode       << " this: " << this << " first: " << i->first  << " nonce: " << i->second.nonce << endl;
00210         overlay->cancelRpcMessage( i->second.nonce );
00211     }
00212     rpcs.clear();
00213 
00214     // delete path lookups
00215     for (uint i=0; i<paths.size(); i++)
00216         delete paths[i];
00217     paths.clear();
00218 
00219     // reset running flag
00220     running  = false;
00221     finished = true;
00222 
00223     // inform listener
00224     if ( listener != NULL ) {
00225         listener->lookupFinished(this);
00226         listener = NULL;
00227     }
00228 }

void BaseLookup::checkStop (  )  [inline, protected]

00231 {
00232     bool finishLookup = false;
00233 
00234     // check if there are rpcs pending or lookup finished
00235     if ((successfulPaths >=1 && numSiblings == 0) ||
00236         (finishedPaths == (uint)config.parallelPaths && numSiblings > 0)) {
00237         for (uint i=0; i<paths.size(); i++)
00238             success |= paths[i]->success;
00239         finishLookup = true;
00240     } else if (rpcs.size() == 0) {
00241         finishLookup = true;
00242     }
00243 
00244     if (finishLookup == true) {
00245         if (success == false && retries > 0) {
00246             //      std::cout << "BaseLookup::checkStop(): Retry..." << endl;
00247             retries--;
00248             LookupListener* oldListener = listener;
00249             listener = NULL;
00250             stop();
00251             listener = oldListener;
00252             start();
00253         } else {
00254             delete this;
00255         }
00256     }
00257 }

void BaseLookup::lookup ( const OverlayKey key,
int  numSiblings = 1,
int  hopCountMax = 0,
int  retries = 0,
LookupListener listener = NULL 
) [virtual]

Lookup siblings for a key.

Parameters:
key The key to lookup
numSiblings Number of siblings to lookup
hopCountMax Maximum hop count
retries Number of retries if lookup fails
listener Listener to inform, when the lookup is done

Implements AbstractLookup.

00513 {   
00514     EV << "[BaseLookup::lookup() @ " << overlay->thisNode.ip
00515        << " (" << overlay->thisNode.key.toString(16) << ")]\n"
00516        << "    Lookup of key " << key
00517        << endl;
00518 
00519     // check flags
00520     if (finished || running)
00521         return;
00522 
00523     // set params
00524     this->key = key;
00525     this->numSiblings = numSiblings;
00526     this->hopCountMax = hopCountMax;
00527     this->listener = listener;
00528     this->retries = retries;
00529 
00530     // start lookup
00531     start();
00532 }

const NodeVector & BaseLookup::getResult (  )  const [virtual]

Returns the result of the lookup.

Returns:
The result node vector.

Implements AbstractLookup.

00535 {
00536     // return sibling vector
00537     return siblings;
00538 }

bool BaseLookup::isValid (  )  const [virtual]

Returns true, if the lookup was successful.

Returns:
true, if the lookup was successful.

Implements AbstractLookup.

00541 {
00542     return success && finished;
00543 }

void BaseLookup::abortLookup (  )  [virtual]

Aborts a running lookup.

This method aborts a running lookup without calling the listener and delete the lookup object.

Implements AbstractLookup.

00070 {
00071     if (listener != NULL) {
00072         delete listener;
00073         listener = NULL;
00074     }
00075     delete this;
00076 }

uint BaseLookup::getAccumulatedHops (  )  const [virtual]

Returns the total number of hops for all lookup paths.

Returns:
The accumulated number of hops.

Implements AbstractLookup.

00546 {
00547     return accumulatedHops;
00548 }


Friends And Related Function Documentation

friend class BasePathLookup [friend]

friend class BaseOverlay [friend]


Member Data Documentation

OverlayKey BaseLookup::key [protected]

key to lookup

BaseOverlay* BaseLookup::overlay [protected]

ptr to overlay

BaseLookupConfiguration BaseLookup::config [protected]

lookup configuration

cObject* BaseLookup::firstCallExt [protected]

additional info for first findNode()

LookupListener* BaseLookup::listener [protected]

lookup listener

vector<BasePathLookup*> BaseLookup::paths [protected]

parallel paths

bool BaseLookup::finished [protected]

true, if lookup is finished

bool BaseLookup::success [protected]

true, if lookup was successful

bool BaseLookup::running [protected]

true, if lookup is running

int BaseLookup::retries [protected]

number of retries, if lookup fails

uint BaseLookup::finishedPaths [protected]

number of finished paths

uint BaseLookup::successfulPaths [protected]

number of successful paths

uint BaseLookup::accumulatedHops [protected]

total number of hops (for all paths)

NodeVector BaseLookup::siblings [protected]

closest nodes

TransportAddress::Set BaseLookup::visited [protected]

nodes already visited

int BaseLookup::numSiblings [protected]

number of siblings

int BaseLookup::hopCountMax [protected]

maximum hop count

RpcInfoMap BaseLookup::rpcs [protected]


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