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)
 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
00265 {
00266     return new BasePathLookup(this);
00267 }

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
00270 {
00271     FindNodeCall* call = new FindNodeCall("FindNodeCall");
00272     if (firstCallExt)
00273         call->addObject(static_cast<cObject*>(firstCallExt->dup()));
00274     return call;
00275 }

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 >.

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

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
00292 {
00293     bool result = false;
00294 
00295     if (numSiblings == 0) {
00296         if (handle.key == key) {
00297             siblings.clear();
00298             siblings.push_back( handle );
00299             result = true;
00300         }
00301     } else {
00302         if (config.parallelPaths==1) {
00303             result = true;
00304             if (!siblings.isFull())
00305                 siblings.push_back(handle);
00306         } else {
00307             result = this->siblings.add(handle);
00308         }
00309     }
00310 
00311     return result;
00312 }

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
00315 {
00316     if (visited)
00317         this->visited.insert( addr );
00318     else
00319         this->visited.erase( addr );
00320 }

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
00323 {
00324     return this->visited.count(addr) != 0;
00325 }

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.

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

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

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

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

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

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) &&
00110         overlay->isSiblingFor(overlay->thisNode, key, numSiblings, &err)) {
00111         
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 ==
00237           (uint)config.parallelPaths && numSiblings > 0) ) {
00238 
00239         for (uint i=0; i<paths.size(); i++)
00240             success |= paths[i]->success;
00241         finishLookup = true;
00242     } else if (rpcs.size() == 0) {
00243         finishLookup = true;
00244     }
00245 
00246     if (finishLookup == true) {
00247         if (success == false && retries > 0) {
00248 //          std::cout << "BaseLookup::checkStop(): Retry..." << endl;
00249             retries--;
00250             LookupListener* oldListener = listener;
00251             listener = NULL;
00252             stop();
00253             listener = oldListener;
00254             start();
00255         } else {
00256             delete this;
00257         }
00258     }
00259 }

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.

00514 {
00515     // check flags
00516     if (finished || running)
00517         return;
00518 
00519     // set params
00520     this->key = key;
00521     this->numSiblings = numSiblings;
00522     this->hopCountMax = hopCountMax;
00523     this->listener = listener;
00524     this->retries = retries;
00525 
00526     // start lookup
00527     start();
00528 }

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

Returns the result of the lookup.

Returns:
The result node vector.

Implements AbstractLookup.

00531 {
00532     // return sibling vector
00533     return siblings;
00534 }

bool BaseLookup::isValid (  )  const [virtual]

Returns true, if the lookup was successful.

Returns:
true, if the lookup was successful.

Implements AbstractLookup.

00537 {
00538     return success && finished;
00539 }

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.

00542 {
00543     return accumulatedHops;
00544 }


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 Wed Sep 26 12:13:00 2007 for ITM OverSim by  doxygen 1.5.1