BootstrapList Class Reference

#include <BootstrapList.h>

Inheritance diagram for BootstrapList:

BaseApp BaseRpc RpcListener

List of all members.


Detailed Description

The BootstrapList module maintains a list of bootstrap node candidates.

The BootstrapList module maintains a list of bootstrap node candidates received from various sources (BootstrapOracle for simulations and Zeroconf for SingleHostUnderlay). This list is also used to detect overlay partitions and triggers the merging process.

Author:
Bin Zheng, Ingmar Baumgart
See also:
BootstrapList

Public Member Functions

 BootstrapList ()
 ~BootstrapList ()
const NodeHandlegetBootstrapNode (const NodeHandle &node)
 Get a bootstrap node from the bootstrap list.
void locateBootstrapNode (const NodeHandle &node)
 Determine locality of a bootstapnode.
bool insertBootstrapCandidate (const NodeHandle &node, BootstrapNodePrioType prio=DNSSD)
 Inserts a new bootstrap candidate into the bootstrap list.
bool insertBootstrapCandidate (BootstrapNodeHandle &node)
void removeBootstrapCandidate (const TransportAddress &addr)
 Remove an unavailable bootstrap candidate from the bootstraplist.
void removeBootstrapNode (const NodeHandle &node)
const NodeHandlegetBootstrapNode ()
void registerBootstrapNode (const NodeHandle &node)

Protected Member Functions

virtual void pingResponse (PingResponse *pingResponse, cPolymorphic *context, int rpcId, simtime_t rtt)
virtual void pingTimeout (PingCall *pingCall, const TransportAddress &dest, cPolymorphic *context, int rpcId)
virtual CompType getThisCompType ()
 Return the component type of this module.

Private Member Functions

virtual void initializeApp (int stage)
 initializes derived class-attributes
virtual void finishApp ()
 collects statistical data of derived app
void handleTimerEvent (cMessage *msg)
 processes self-messages
void handleBootstrapListTimerExpired ()
 Periodic maintenance method for the bootstrap list.
void handleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt)
 This method is called if an RPC response has been received.
void handleLookupResponse (LookupResponse *msg)
 Handle the response for a lookup rpc.

Private Attributes

BootstrapNodeSet bootstrapList
cMessage * timerMsg
 self-message for periodic maintenance
ZeroConfiguratorzeroConfigurator
 pointer to the ZeroConfigurator module
bool mergeOverlayPartitions
 if true, detect and merge overlay partitions
bool maintainList
 maintain a list of bootstrap candidates and check them periodically

Static Private Attributes

static const int timerInterval = 10
 the interval of the maintenance timer in seconds

Constructor & Destructor Documentation

BootstrapList::BootstrapList (  ) 

00060 {
00061     zeroConfigurator = NULL;
00062     timerMsg = NULL;
00063 }

BootstrapList::~BootstrapList (  ) 

00067 {
00068     cancelAndDelete(timerMsg);
00069 }


Member Function Documentation

const NodeHandle& BootstrapList::getBootstrapNode ( const NodeHandle node  ) 

Get a bootstrap node from the bootstrap list.

If not using SingleHostConfigurator and the list is empty, return a node by asking the BootstrapOracle.

Parameters:
node the node that needs a bootstrap node

Referenced by BasePastry::baseChangeState(), Gia::changeState(), Chord::changeState(), Broose::changeState(), Vast::handleJoin(), Gia::handleTimerEvent(), and Kademlia::joinOverlay().

void BootstrapList::locateBootstrapNode ( const NodeHandle node  ) 

Determine locality of a bootstapnode.

Parameters:
node the newly discovered bootstrap node

Referenced by insertBootstrapCandidate().

00260 {
00261     Enter_Method_Silent();
00262 
00263     if ((overlay->getState() == BaseOverlay::READY) && (!node.isUnspecified())
00264             && mergeOverlayPartitions) {
00265        LookupCall* call = new LookupCall();
00266        call->setLength(0);
00267        call->setKey(node.key);
00268        call->setNumSiblings(overlay->getMaxNumSiblings());
00269        sendInternalRpcCall(OVERLAY_COMP, call);
00270     }
00271 
00272     return;
00273 }

bool BootstrapList::insertBootstrapCandidate ( const NodeHandle node,
BootstrapNodePrioType  prio = DNSSD 
)

Inserts a new bootstrap candidate into the bootstrap list.

Parameters:
node the bootstrap candidate
prio priority of the bootstrap node
Returns:
true, if bootstrap node is already in the list

Referenced by initializeApp(), and BootstrapOracle::mergeBootstrapNodes().

00278 {
00279     Enter_Method_Silent();
00280 
00281     BootstrapNodeSet::iterator iter;
00282     BootstrapNodeHandle *bootstrapNode;
00283 
00284     // if node already in the list, update its lastPing and nodePrio fields
00285     if ((iter = bootstrapList.find(node)) != bootstrapList.end()) {
00286         iter->second->setLastPing(simTime());
00287         iter->second->setNodePrio(prio);
00288 
00289         return true;
00290     }
00291 
00292     if ((bootstrapNode = new BootstrapNodeHandle(node, prio))) {
00293         bootstrapNode->setLastPing(simTime());
00294         bootstrapList.insert(NodePair(*bootstrapNode, bootstrapNode));
00295     }
00296 
00297     locateBootstrapNode(node);
00298 
00299     return false;
00300 }

bool BootstrapList::insertBootstrapCandidate ( BootstrapNodeHandle node  ) 

00304 {
00305     Enter_Method_Silent();
00306 
00307     BootstrapNodeSet::iterator iter;
00308 
00309     node.setLastPing(simTime());
00310 
00311     // if node already in the list, update its lastPing and nodePrio fields
00312     if ((iter = bootstrapList.find(node)) != bootstrapList.end()) {
00313         iter->second->setLastPing(node.getLastPing());
00314         iter->second->setNodePrio(node.getNodePrio());
00315 
00316         return true;
00317     }
00318 
00319     bootstrapList.insert(NodePair(node, &node));
00320     locateBootstrapNode(node);
00321 
00322     return false;
00323 }

void BootstrapList::removeBootstrapCandidate ( const TransportAddress addr  ) 

Remove an unavailable bootstrap candidate from the bootstraplist.

Parameters:
addr the address of the bootstrap candidate

Referenced by pingTimeout().

00327 {
00328     BootstrapNodeSet::iterator iter;
00329     BootstrapNodeHandle* bootstrapNode;
00330 
00331     if (!addr.isUnspecified()) {
00332         if ((iter = bootstrapList.find(addr)) != bootstrapList.end()) {
00333             bootstrapNode = iter->second;
00334             bootstrapList.erase(iter);
00335             delete bootstrapNode;
00336         }
00337     }
00338 
00339     return;
00340 }

void BootstrapList::removeBootstrapNode ( const NodeHandle node  ) 

Referenced by BasePastry::baseChangeState(), Broose::changeState(), Gia::finishOverlay(), Chord::finishOverlay(), Broose::finishOverlay(), BasePastry::finishOverlay(), Kademlia::joinOverlay(), and BaseOverlay::setOverlayReady().

00344 {
00345     overlay->bootstrapOracle->removePeer(node);
00346     // at this point, we consider this node not being able to provide the
00347     // boot service anymore, therefore we have to revoke
00348     // the service via zeroConfigurator
00349     if (zeroConfigurator) {
00350         zeroConfigurator->revokeService();
00351     }
00352 }

const NodeHandle & BootstrapList::getBootstrapNode (  ) 

00230 {
00231     if (!maintainList) {
00232         return overlay->bootstrapOracle->getBootstrapNode();
00233     } else {
00234         const NodeHandle *bootstrapNode = &NodeHandle::UNSPECIFIED_NODE;
00235         int i, j = 0;
00236 
00237         // pick a random node from the list
00238         if (!bootstrapList.empty()) {
00239             i = intrand(bootstrapList.size());
00240             BootstrapNodeSet::iterator iter = bootstrapList.begin();
00241 
00242             while (j < i) {
00243                 iter++;
00244                 j++;
00245             }
00246 
00247             bootstrapNode = (NodeHandle *)iter->second;
00248         } else {
00249             // if the list empty, get a bootstrap node from BootstrapOracle
00250             if (!zeroConfigurator)
00251                 bootstrapNode = &overlay->bootstrapOracle->
00252                         getBootstrapNode(overlay->getThisNode());
00253         }
00254         return *bootstrapNode;
00255     }
00256 }

void BootstrapList::registerBootstrapNode ( const NodeHandle node  ) 

Referenced by BaseOverlay::setOverlayReady().

00356 {
00357     bootstrapOracle->registerPeer(node);
00358 
00359     // at this point, we consider this node as booted and therefore have to
00360     // announce the boot service for it via zeroConfigurator
00361     if (zeroConfigurator) {
00362         zeroConfigurator->announceService(node);
00363     }
00364 }

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

Reimplemented from BaseRpc.

00198 {
00199     NodeHandle &srcNode = pingResponse->getSrcNode();
00200     BootstrapNodeSet::iterator iter;
00201 
00202     EV << "[BootstrapList::pingResponse() @ " << overlay->getThisNode().ip
00203            << " (" << overlay->getThisNode().key << ")]\n"
00204            << "    Ping response from node " << srcNode
00205            << " with rtt " << rtt << endl;
00206 
00207     // update the lastPing field of the source node
00208     if (!srcNode.isUnspecified())
00209         if ((iter = bootstrapList.find(srcNode)) != bootstrapList.end())
00210             iter->second->setLastPing(simTime());
00211 
00212     return;
00213 }

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

Reimplemented from BaseRpc.

00220 {
00221     EV << "[BootstrapList::pingTimeout() @ " << overlay->getThisNode().ip
00222        << " (" << overlay->getThisNode().key << ")]\n"
00223        << "    Ping timeout for node " << dest << endl;
00224     // destination does not answer, remove it from the list
00225     removeBootstrapCandidate(dest);
00226 }

virtual CompType BootstrapList::getThisCompType (  )  [inline, protected, virtual]

Return the component type of this module.

This method is overloaded by BaseOverlay/BaseApp and returns the appropriate component type of this module.

Returns:
the component type of this module

Reimplemented from BaseApp.

00110 { return BOOTSTRAPLIST_COMP; };

void BootstrapList::initializeApp ( int  stage  )  [private, virtual]

initializes derived class-attributes

Parameters:
stage the init stage

Reimplemented from BaseApp.

00073 {
00074     if (stage != MIN_STAGE_APP) {
00075         return;
00076     }
00077 
00078     mergeOverlayPartitions = par("mergeOverlayPartitions");
00079     maintainList = par("maintainList");
00080 
00081     if (parentModule()->parentModule()->submodule("zeroConfigurator", 0)) {
00082         zeroConfigurator = check_and_cast<ZeroConfigurator *>(parentModule()->
00083                 parentModule()->submodule("zeroConfigurator", 0));
00084         if (!zeroConfigurator->isEnabled()) {
00085             zeroConfigurator = NULL;
00086         }
00087     }
00088 
00089     // load local cache list only when using SingleHostConfigurator
00090     if (zeroConfigurator) {
00091         ifstream nodeListFile("nodelist.dat", ios::in);
00092         if (!nodeListFile) {
00093             EV << "BootstrapList::initializeApp(): nodelist.dat not found"
00094                << endl;
00095         } else {
00096             char address[16];
00097             int port;
00098             string key;
00099             BootstrapNodeHandle *node;
00100 
00101             while (nodeListFile >> address >> port >> key) {
00102                 node = new BootstrapNodeHandle(OverlayKey(key, 16),
00103                                                IPvXAddress(address), port,
00104                                                CACHE);
00105                 if (node)
00106                     insertBootstrapCandidate(*node);
00107             }
00108             nodeListFile.close();
00109         }
00110     }
00111 
00112     WATCH_UNORDERED_MAP(bootstrapList);
00113 
00114     if (maintainList) {
00115         timerMsg = new cMessage("BootstrapListTimer");
00116         scheduleAt(simTime() + timerInterval, timerMsg);
00117     }
00118 }

void BootstrapList::finishApp (  )  [private, virtual]

collects statistical data of derived app

Reimplemented from BaseApp.

00368 {
00369     // dump the list of bootstrap nodes into the local cache only when
00370     // using SingleHostConfigurator
00371     if (zeroConfigurator) {
00372         ofstream nodeListFile("nodelist.dat", ios::out|ios::trunc);
00373         if (!nodeListFile) {
00374             std::cerr << "nodelist.dat could not be opened" << endl;
00375         } else {
00376             for (BootstrapNodeSet::iterator iter = bootstrapList.begin();
00377                  iter != bootstrapList.end(); iter++) {
00378                 nodeListFile << iter->second->ip.str() << ' '
00379                              << iter->second->port << ' '
00380                              << iter->second->key.toString(16) << '\n';
00381             }
00382             nodeListFile.close();
00383         }
00384     }
00385 
00386     // delete all bootstrap nodes and clear the list
00387     for (BootstrapNodeSet::iterator iter = bootstrapList.begin();
00388          iter != bootstrapList.end(); iter++) {
00389         delete iter->second;
00390     }
00391 
00392     bootstrapList.clear();
00393 }

void BootstrapList::handleTimerEvent ( cMessage *  msg  )  [private, virtual]

processes self-messages

method to handle self-messages should be overwritten in derived application if needed

Parameters:
msg self-message

Reimplemented from BaseApp.

00122 {
00123     if (msg == timerMsg) {
00124         handleBootstrapListTimerExpired();
00125         scheduleAt(simTime() + timerInterval, msg);
00126     } else {
00127         throw new cException("BootstrapList::handleTimerEvent(): "
00128                              "Received unknown self-message!");
00129     }
00130 }

void BootstrapList::handleBootstrapListTimerExpired (  )  [private]

Periodic maintenance method for the bootstrap list.

Referenced by handleTimerEvent().

00133 {
00134     simtime_t current = simTime();
00135     BootstrapNodeHandle *node;
00136     BootstrapNodeSet::iterator iter;
00137 
00138     for (iter = bootstrapList.begin(); iter != bootstrapList.end(); iter++) {
00139         node = iter->second;
00140         if (timerInterval <= (current - node->getLastPing())) {
00141             pingNode(*node);
00142         }
00143     }
00144 }

void BootstrapList::handleRpcResponse ( BaseResponseMessage *  msg,
cPolymorphic *  context,
int  rpcId,
simtime_t  rtt 
) [private, virtual]

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

Parameters:
msg The response message.
context Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code
rpcId The RPC id.
rtt The Round-Trip-Time of this RPC

Reimplemented from RpcListener.

00150 {
00151     RPC_SWITCH_START(msg)
00152     RPC_ON_RESPONSE(Lookup) {
00153         handleLookupResponse(_LookupResponse);
00154         EV << "[BootstrapList::handleRpcResponse() @ "
00155            << overlay->getThisNode().ip
00156            << " (" << overlay->getThisNode().key.toString(16) << ")]\n"
00157            << "    Lookup RPC Response received: id=" << rpcId << "\n"
00158            << "    msg=" << *_LookupResponse << " rtt=" << rtt
00159            << endl;
00160     }
00161     RPC_SWITCH_END( )
00162 }

void BootstrapList::handleLookupResponse ( LookupResponse *  msg  )  [private]

Handle the response for a lookup rpc.

This is used to detected foreign overlay partitions

Parameters:
msg The lookup response message

Referenced by handleRpcResponse().

00165 {
00166     EV << "[BootstrapList::handleLookupResponse() @ "
00167        << overlay->getThisNode().ip
00168        << " (" << overlay->getThisNode().key.toString(16) << ")]\n"
00169        << "    Lookup response for key " << msg->getKey()<< " : ";
00170 
00171     if (msg->getIsValid()) {
00172         for (uint i=0; i<msg->getSiblingsArraySize(); i++) {
00173             if (msg->getSiblings(i).key == msg->getKey()) {
00174                 EV << "Key " << msg->getSiblings(i)
00175                    << "belongs to a local node." << endl;
00176                 return;
00177             }
00178         }
00179 
00180         EV << "New partition discovered, going to join." << endl;
00181         BootstrapNodeSet::iterator iter;
00182         for (iter = bootstrapList.begin(); iter != bootstrapList.end(); iter++) {
00183             if (iter->second->key == msg->getKey())
00184                 overlay->joinForeignPartition(*iter->second);
00185         }
00186 
00187     } else {
00188         EV << "failed" << endl;
00189     }
00190 
00191     return;
00192 }


Member Data Documentation

const int BootstrapList::timerInterval = 10 [static, private]

the interval of the maintenance timer in seconds

Referenced by handleBootstrapListTimerExpired(), handleTimerEvent(), and initializeApp().

cMessage* BootstrapList::timerMsg [private]

self-message for periodic maintenance

Referenced by BootstrapList(), handleTimerEvent(), initializeApp(), and ~BootstrapList().

if true, detect and merge overlay partitions

Referenced by initializeApp(), and locateBootstrapNode().

maintain a list of bootstrap candidates and check them periodically

Referenced by getBootstrapNode(), and initializeApp().


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

Generated on Fri Sep 19 13:05:06 2008 for ITM OverSim by  doxygen 1.5.5