SimpleNetConfigurator Class Reference

#include <SimpleNetConfigurator.h>

Inheritance diagram for SimpleNetConfigurator:

UnderlayConfigurator

List of all members.


Detailed Description

Sets up a SimpleNetwork.

Sets up a SimpleNetwork. Adds overlay nodes to the network in init phase and adds/removes/migrates overlay nodes after init phase.

Public Member Functions

virtual
TransportAddress
createNode (NodeType type, bool initialize=false)
 Creates an overlay node.
virtual void preKillNode (NodeType type, TransportAddress *addr=NULL)
 Notifies and schedules overlay nodes for removal.
virtual void migrateNode (NodeType type, TransportAddress *addr=NULL)
 Migrates overlay nodes from one access net to another.
uint getFieldSize ()
uint getFieldDimension ()
uint getSendQueueLenghth ()

Protected Member Functions

void initializeUnderlay (int stage)
 Enables access to the globalHashMap, sets some parameters and adds the initial number of nodes to the network.
void handleTimerEvent (cMessage *msg)
void finishUnderlay ()
 Saves statistics, prints simulation time.
void setDisplayString ()
 Prints statistics.
uint parseCoordFile (const char *nodeCoordinateSource)

Protected Attributes

uint32 nextFreeAddress
 adress of the node that will be created next
cModuleType * moduleType
 type of overlay terminals
std::deque< IPvXAddress > killList
 stores nodes scheduled to be killed
std::set< int > scheduledID
 stores nodeIds to prevent migration of prekilled nodes
uint sendQueueLength
 send queue length of overlay terminals
uint fieldSize
int dimensions
bool fixedNodePositions
bool useXmlCoords
const char * nodeCoordinateSource
vector< NodeRecordunusedNodeRecords
map< IPvXAddress,
NodeRecord
assignedNodeRecords
int numCreated
 number of overall created overlay terminals
int numKilled
 number of overall killed overlay terminals


Member Function Documentation

TransportAddress * SimpleNetConfigurator::createNode ( NodeType  type,
bool  initialize = false 
) [virtual]

Creates an overlay node.

Parameters:
type NodeType of the node to create
initialize are we in init phase?

Implements UnderlayConfigurator.

00108 {
00109     Enter_Method_Silent();
00110     // derive overlay node from ned
00111     cModuleType* moduleType = findModuleType(type.terminalType.c_str());
00112 
00113     cModule* node = moduleType->create("overlayTerminal", parentModule());
00114 
00115     node->par("overlayType").setStringValue(type.overlayType.c_str());
00116     node->par("tier1Type").setStringValue(type.tier1Type.c_str());
00117     node->par("tier2Type").setStringValue(type.tier2Type.c_str());
00118     node->par("tier3Type").setStringValue(type.tier3Type.c_str());
00119 
00120     node->setDisplayString("i=device/wifilaptop_l;i2=block/circle_s");
00121     node->buildInside();
00122     node->scheduleStart(simulation.simTime());
00123 
00124     for (int i = 0; i < MAX_STAGE_UNDERLAY + 1; i++) {
00125         node->callInitialize(i);
00126     }
00127 
00128     // FIXME use only IPv4?
00129     IPvXAddress addr = IPAddress(nextFreeAddress++);
00130 
00131     cChannelType* chan = findChannelType(type.channelTypes[intuniform(0,
00132             type.channelTypes.size()
00133             - 1)].c_str());
00134     if (!chan)
00135         opp_error("Could not find Channel Type. Most likely parameter "
00136                   "channelTypes does not match the channels defined in "
00137                   "channels.ned");
00138     SimpleNodeEntry* entry;
00139 
00140     if (!useXmlCoords) {
00141         entry = new SimpleNodeEntry(node, chan, fieldSize, sendQueueLength);
00142     } else {
00143         // stop with errormessage if no more unused nodes available
00144         if (unusedNodeRecords.size() < 1) {
00145             opp_error("Cannot create any more Nodes. "
00146                       "Provide %s-file with more Nodes!\n",
00147                       nodeCoordinateSource);
00148         }
00149 
00150         //get random node from set of unused        
00151         int volunteer = intuniform(0, unusedNodeRecords.size()-1);
00152         entry = new SimpleNodeEntry(node, chan, dimensions,
00153                 unusedNodeRecords[volunteer].coords);
00154 
00155         //insert IP-address into noderecord used
00156         unusedNodeRecords[volunteer].ip = addr;
00157 
00158         // add noderecord to assigned...
00159         assignedNodeRecords.insert(make_pair(addr, unusedNodeRecords[volunteer]));
00160         // ... and erase from unused
00161         unusedNodeRecords.erase(unusedNodeRecords.begin()+volunteer);
00162 
00163     }
00164 
00165     node->gate("out",0)->setChannel(chan->create("outChan"));
00166 
00167     SimpleUDP* simple = check_and_cast<SimpleUDP*>(node->submodule("udp"));
00168     simple->setNodeEntry(*entry);
00169 
00170     // Add pseudo-Interface to node's interfaceTable
00171     IPv4InterfaceData* ifdata = new IPv4InterfaceData;
00172     ifdata->setInetAddress(addr.get4());
00173     ifdata->setNetmask(IPAddress("255.255.255.255"));
00174     InterfaceEntry* e = new InterfaceEntry;
00175     e->setName("dummy interface");
00176     e->setIPv4Data(ifdata);
00177 
00178     IPAddressResolver().interfaceTableOf(node)->addInterface(e, NULL);
00179 
00180     // create meta information
00181     SimpleInfo* info = new SimpleInfo(type.typeID, node->id());
00182     info->setEntry(entry);
00183 
00184     // append index to module name
00185     char buf[80];
00186     sprintf(buf, "overlayTerminal[%i]", numCreated);
00187     node->setName(buf);
00188 
00189     //add node to bootstrap oracle
00190     bootstrapOracle->addPeer(addr, info);
00191 
00192     // if the node was not created during startup we have to
00193     // finish the initialization process manually
00194     if ( !initialize) {
00195         for (int i = MAX_STAGE_UNDERLAY + 1; i < NUM_STAGES_ALL; i++) {
00196             node->callInitialize(i);
00197         }
00198     }
00199 
00200     //show ip... todo: migrate   
00201     if (fixedNodePositions && ev.isGUI()) {
00202         node->displayString().insertTag("p");
00203         node->displayString().setTagArg("p", 0, (long int)entry->getX());
00204         node->displayString().setTagArg("p", 1, (long int)entry->getY());
00205         node->displayString().insertTag("t", 0);
00206         node->displayString().setTagArg("t", 0, addr.str().c_str());
00207         node->displayString().setTagArg("t", 1, "l");
00208     }
00209 
00210     overlayTerminalCount++;
00211     numCreated++;
00212 
00213     churnGenerator[type.typeID - 1]->terminalCount++;
00214 
00215     TransportAddress *address = new TransportAddress(addr);
00216 
00217     // update display
00218     setDisplayString();
00219 
00220     return address;
00221 }

void SimpleNetConfigurator::preKillNode ( NodeType  type,
TransportAddress addr = NULL 
) [virtual]

Notifies and schedules overlay nodes for removal.

Parameters:
type NodeType of the node to remove
addr NULL for random node

Implements UnderlayConfigurator.

00269 {
00270     Enter_Method_Silent();
00271 
00272     SimpleNodeEntry* entry= NULL;
00273     SimpleInfo* info;
00274 
00275     if (addr != NULL) {
00276         info = dynamic_cast<SimpleInfo*>(bootstrapOracle->getPeerInfo(*addr));
00277         if (info != NULL) {
00278             entry = info->getEntry();
00279         } else
00280             opp_error("SimpleNetConfigurator: Trying to pre kill node "
00281                 "with nonexistant TransportAddress!");
00282     } else {
00283         info = dynamic_cast<SimpleInfo*>(bootstrapOracle
00284             ->getRandomPeerInfo(type.typeID));
00285         entry = info->getEntry();
00286     }
00287 
00288     uint32_t effectiveType = info->getTypeID();
00289     cGate* gate = entry->getGate();
00290 
00291     cModule* node = gate->ownerModule()->parentModule();
00292 
00293     if (scheduledID.count(node->id()))
00294         return;
00295 
00296     //remove node from bootstrap oracle
00297     bootstrapOracle->removePeer(IPAddressResolver().addressOf(node));
00298 
00299     // put node into the kill list and schedule a message for final removal
00300     // of the node
00301     killList.push_front(IPAddressResolver().addressOf(node));
00302     scheduledID.insert(node->id());
00303 
00304     overlayTerminalCount--;
00305     numKilled++;
00306 
00307     churnGenerator[effectiveType - 1]->terminalCount--;
00308 
00309     // update display
00310     setDisplayString();
00311 
00312     // inform the notification board about the removal
00313     NotificationBoard* nb = check_and_cast<NotificationBoard*>(node->
00314     submodule("notificationBoard"));
00315     nb->fireChangeNotification(NF_OVERLAY_NODE_LEAVE);
00316 
00317     double random = uniform(0, 1);
00318     if (random < gracefulLeavePropability) {
00319         nb->fireChangeNotification(NF_OVERLAY_NODE_GRACEFUL_LEAVE);
00320     }
00321 
00322     cMessage* msg = new cMessage();
00323     scheduleAt(simulation.simTime() + gracefulLeaveDelay, msg);
00324 }

void SimpleNetConfigurator::migrateNode ( NodeType  type,
TransportAddress addr = NULL 
) [virtual]

Migrates overlay nodes from one access net to another.

Parameters:
type NodeType of the node to migrate
addr NULL for random node

Implements UnderlayConfigurator.

00327 {
00328     Enter_Method_Silent();
00329 
00330     SimpleNodeEntry* entry= NULL;
00331 
00332     if (addr != NULL) {
00333         SimpleInfo* info =
00334                 dynamic_cast<SimpleInfo*>(bootstrapOracle->getPeerInfo(*addr));
00335         if (info != NULL) {
00336             entry = info->getEntry();
00337         } else
00338             opp_error("SimpleNetConfigurator: Trying to migrate node with "
00339                       "nonexistant TransportAddress!");
00340     } else {
00341         SimpleInfo* info = dynamic_cast<SimpleInfo*>(bootstrapOracle->
00342         getRandomPeerInfo(type.typeID));
00343         entry = info->getEntry();
00344     }
00345 
00346     cGate* gate = entry->getGate();
00347     cModule* node = gate->ownerModule()->parentModule();
00348 
00349     // do not migrate node that is already scheduled
00350     if (scheduledID.count(node->id()))
00351         return;
00352 
00353     IPvXAddress tmp_ip = IPAddressResolver().addressOf(node);
00354 
00355     //remove node from bootstrap oracle
00356     bootstrapOracle->killPeer(tmp_ip);
00357 
00358     node->bubble("I am migrating!");
00359 
00360     // FIXME use only IPv4?
00361     IPvXAddress address = IPAddress(nextFreeAddress++);
00362 
00363     //std::cout << "migration @ " << tmp_ip << " --> " << address << std::endl;
00364 
00365     SimpleNodeEntry* newentry;
00366 
00367     if (useXmlCoords) {
00368         // save coords before removal from assignedNodeRecords
00369         double * tmp_coords = new double[dimensions];
00370         map<IPvXAddress, NodeRecord>::iterator iter =
00371             assignedNodeRecords.find(tmp_ip);
00372         if (iter != assignedNodeRecords.end()) {
00373             for (int i=0; i<dimensions; i++) {
00374                 tmp_coords[i] = (iter->second).coords[i];
00375             }
00376         } else {
00377             opp_error("SimpleNetConfigurator: couldn't find ip in "
00378                 "assignedNodeRecords!");
00379         }
00380 
00381         // remove NodeRecord from map with used ones    
00382         assignedNodeRecords.erase(tmp_ip);
00383 
00384         // create new NR to re-insert with new address
00385         NodeRecord tmpNR = NodeRecord(dimensions);
00386         for (int i=0; i<dimensions; i++) {
00387             tmpNR.coords[i] = tmp_coords[i];
00388         }
00389         tmpNR.ip = address;
00390 
00391         // insert NodeRecord again with new address
00392         assignedNodeRecords.insert(make_pair(address, tmpNR) );
00393 
00394         newentry = new SimpleNodeEntry(node,
00395             findChannelType(channelTypes[intuniform(0, channelTypes.size() - 1)].c_str()),
00396             dimensions, tmp_coords);
00397         
00398         delete[] tmp_coords;
00399     } else {
00400         newentry = new SimpleNodeEntry(node,
00401             findChannelType(channelTypes[intuniform(0, channelTypes.size() - 1)].c_str()),
00402             fieldSize, sendQueueLength);
00403     }
00404 
00405     SimpleUDP* simple = check_and_cast<SimpleUDP*>(gate->ownerModule());
00406     simple->setNodeEntry(*newentry);
00407 
00408     InterfaceEntry* ie = IPAddressResolver().interfaceTableOf(node)->
00409     interfaceByName("dummy interface");
00410 
00411     delete ie->ipv4();
00412 
00413     // Add pseudo-Interface to node's interfaceTable
00414     IPv4InterfaceData* ifdata = new IPv4InterfaceData;
00415     ifdata->setInetAddress(address.get4());
00416     ifdata->setNetmask(IPAddress("255.255.255.255"));
00417     ie->setIPv4Data(ifdata);
00418 
00419     // create meta information
00420     SimpleInfo* newinfo = new SimpleInfo(type.typeID, node->id());
00421     newinfo->setEntry(newentry);
00422 
00423     //add node to bootstrap oracle
00424     bootstrapOracle->addPeer(address, newinfo);
00425 
00426     // inform the notofication board about the migration
00427     NotificationBoard* nb =
00428         check_and_cast<NotificationBoard*>(node->submodule("notificationBoard"));
00429     nb->fireChangeNotification(NF_OVERLAY_TRANSPORTADDRESS_CHANGED);
00430 }

uint SimpleNetConfigurator::getFieldSize (  )  [inline]

00085 { return fieldSize; };

uint SimpleNetConfigurator::getFieldDimension (  )  [inline]

00086 { return dimensions; };

uint SimpleNetConfigurator::getSendQueueLenghth (  )  [inline]

00087 { return sendQueueLength; };

void SimpleNetConfigurator::initializeUnderlay ( int  stage  )  [protected, virtual]

Enables access to the globalHashMap, sets some parameters and adds the initial number of nodes to the network.

Parameters:
stage the phase of the initialisation

Implements UnderlayConfigurator.

00055 {
00056     if (stage != MAX_STAGE_UNDERLAY)
00057         return;
00058 
00059     // fetch some parameters
00060     moduleType = findModuleType(par("overlayTerminalType")); // not used anymore!
00061     fixedNodePositions = par("fixedNodePositions");
00062 
00063     // set maximum coordinates and send queue length
00064     fieldSize = par("fieldSize");
00065     //fieldDimension = 2;
00066     sendQueueLength = par("sendQueueLength");
00067 
00068     SimpleNodeEntry::setFieldSize(fieldSize); //deprecated
00069     SimpleNodeEntry::setSendQueueLength(sendQueueLength); //deprecated
00070 
00071     // get parameter of sourcefile's name
00072     nodeCoordinateSource = par("nodeCoordinateSource");
00073 
00074     // check if exists and process xml-file containing coordinates
00075     std::ifstream check_for_xml_file(nodeCoordinateSource);
00076     if (check_for_xml_file) {
00077         useXmlCoords = 1;
00078         uint max_coord = parseCoordFile(nodeCoordinateSource);
00079         SimpleNodeEntry::setFieldSize(max_coord);
00080 
00081         EV << "[SimpleNetConfigurator::initializeUnderlay()]\n"
00082            << "    Using '" << nodeCoordinateSource
00083            << "' as Coordinate-Sourcefile" << endl;
00084     } else {
00085         useXmlCoords = 0;
00086         dimensions = 2;
00087         EV << "[SimpleNetConfigurator::initializeUnderlay()]\n"
00088            << "    Using conventional (random) coordinates for placing nodes!\n"
00089            << "    (An XML-Sourcefile could not be opened)" << endl;
00090     }
00091     check_for_xml_file.close();
00092 
00093     // FIXME get address from parameter
00094     nextFreeAddress = 0x1000001;
00095 
00096     // count the overlay clients
00097     overlayTerminalCount = 0;
00098     // Now done in base class   churnGenerator->setOverlayTerminalCount(overlayTerminalCount);
00099 
00100     numCreated = 0;
00101     numKilled = 0;
00102 
00103     //Now done in base class    churnGenerator->initializeChurn();
00104 }

void SimpleNetConfigurator::handleTimerEvent ( cMessage *  msg  )  [protected, virtual]

Reimplemented from UnderlayConfigurator.

00433 {
00434     Enter_Method_Silent();
00435 
00436     // get next scheduled node and remove it from the kill list
00437     IPvXAddress addr = killList.back();
00438     killList.pop_back();
00439 
00440     SimpleNodeEntry* entry= NULL;
00441 
00442     SimpleInfo* info =
00443             dynamic_cast<SimpleInfo*>(bootstrapOracle->getPeerInfo(addr));
00444     if (info != NULL) {
00445         entry = info->getEntry();
00446     } else
00447         opp_error("SimpleNetConfigurator: Trying to kill node with "
00448                   "nonexistant TransportAddress!");
00449 
00450     cGate* gate = entry->getGate();
00451     cModule* node = gate->ownerModule()->parentModule();
00452 
00453     scheduledID.erase(node->id());
00454     bootstrapOracle->killPeer(addr);
00455 
00456     InterfaceEntry* ie = IPAddressResolver().interfaceTableOf(node)->
00457     interfaceByName("dummy interface");
00458     delete ie->ipv4();
00459 
00460     if (useXmlCoords) {
00461         // remove node from assignedNodeRecords
00462         map<IPvXAddress, NodeRecord>::iterator iter =
00463             assignedNodeRecords.find(addr);
00464         if (iter != assignedNodeRecords.end()) {
00465             assignedNodeRecords.erase(iter);
00466         } else {
00467             opp_error("SimpleNetConfigurator::handleTimerEvent(): "
00468                       "couldn't find ip in assignedNodeRecords!");
00469         }
00470     }
00471 
00472     node->callFinish();
00473     node->deleteModule();
00474 
00475     delete msg;
00476 }

void SimpleNetConfigurator::finishUnderlay (  )  [protected, virtual]

Saves statistics, prints simulation time.

Reimplemented from UnderlayConfigurator.

00489 {
00490     // statistics
00491     recordScalar("Terminals added", numCreated);
00492     recordScalar("Terminals removed", numKilled);
00493 
00494     struct timeval now, diff;
00495     gettimeofday(&now, NULL);
00496     timersub(&now, &initFinishedTime, &diff);
00497     printf("Simulation time: %li.%06li\n", diff.tv_sec, diff.tv_usec);
00498 }

void SimpleNetConfigurator::setDisplayString (  )  [protected, virtual]

Prints statistics.

Implements UnderlayConfigurator.

00479 {
00480     //
00481     // Updates the statistics display string.
00482     //
00483     char buf[80];
00484     sprintf(buf, "%i overlay clients", overlayTerminalCount);
00485     displayString().setTagArg("t", 0, buf);
00486 }

uint SimpleNetConfigurator::parseCoordFile ( const char *  nodeCoordinateSource  )  [protected]

00224 {
00225     cXMLElement * rootElement = ev.getXMLDocument(nodeCoordinateSource);
00226 
00227     // get number of dimensions from attribute of xml rootelement
00228     dimensions = atoi(rootElement->getAttribute("dimensions"));
00229     EV << "[SimpleNetConfigurator::parseCoordFile()]\n"
00230        << "    using " << dimensions << " dimensions" << endl;
00231 
00232     double max_coord = 0;
00233     for (cXMLElement *tmpElement = rootElement->getFirstChild(); tmpElement;
00234          tmpElement = tmpElement->getNextSibling()) {
00235 
00236         // get "ip" and "isRoot" from Attributes (not needed yet)
00237         /*
00238          const char* str_ip = tmpElement->getAttribute("ip");        
00239          int tmpIP = 0;
00240          if (str_ip) sscanf(str_ip, "%x", &tmpIP);
00241          bool tmpIsRoot = atoi(tmpElement->getAttribute("isroot"));
00242          */
00243 
00244         // create tmpNode to be added to vector
00245         NodeRecord tmpNode = NodeRecord(dimensions);
00246 
00247         // get coords from childEntries and fill tmpNodes Array
00248         int i = 0;
00249         for (cXMLElement *coord = tmpElement->getFirstChild(); coord;
00250              coord = coord->getNextSibling()) {
00251             tmpNode.coords[i] = atof(coord->getNodeValue());
00252             if (fabs(tmpNode.coords[i]) > max_coord)
00253                 max_coord = fabs(tmpNode.coords[i]);
00254             i++;
00255         }
00256 
00257         // add to vector
00258         unusedNodeRecords.push_back(tmpNode);
00259     } // now all nodes from xml-file are in vector unusedRootNodes
00260 
00261     EV << "[SimpleNetConfigurator::parseCoordFile()]\n    "
00262        << unusedNodeRecords.size()
00263        << " nodes added to vector \"unusedNodeRecords\"." << endl;
00264 
00265     return (uint)ceil(max_coord);
00266 }


Member Data Documentation

uint32 SimpleNetConfigurator::nextFreeAddress [protected]

adress of the node that will be created next

cModuleType* SimpleNetConfigurator::moduleType [protected]

type of overlay terminals

std::deque<IPvXAddress> SimpleNetConfigurator::killList [protected]

stores nodes scheduled to be killed

std::set<int> SimpleNetConfigurator::scheduledID [protected]

stores nodeIds to prevent migration of prekilled nodes

uint SimpleNetConfigurator::sendQueueLength [protected]

send queue length of overlay terminals

uint SimpleNetConfigurator::fieldSize [protected]

int SimpleNetConfigurator::dimensions [protected]

bool SimpleNetConfigurator::fixedNodePositions [protected]

bool SimpleNetConfigurator::useXmlCoords [protected]

const char* SimpleNetConfigurator::nodeCoordinateSource [protected]

vector<NodeRecord> SimpleNetConfigurator::unusedNodeRecords [protected]

map<IPvXAddress, NodeRecord> SimpleNetConfigurator::assignedNodeRecords [protected]

int SimpleNetConfigurator::numCreated [protected]

number of overall created overlay terminals

int SimpleNetConfigurator::numKilled [protected]

number of overall killed overlay terminals


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