Vast.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 //
00018 
00024 #include "Vast.h"
00025 
00026 Define_Module(Vast);
00027 
00028 #include <NotifierConsts.h>
00029 
00030 #include <GlobalNodeList.h>
00031 #include <GlobalStatistics.h>
00032 #include <BootstrapList.h>
00033 
00034 void Vast::initializeOverlay(int stage)
00035 {
00036     // because of IPAddressResolver, we need to wait until interfaces are registered,
00037     // address auto-assignment takes place etc.
00038     if(stage != MIN_STAGE_OVERLAY) return;
00039 
00040     // fetch parameters
00041     debugVoronoiOutput = par("debugVastOutput");
00042     areaDimension = par("areaDimension");
00043     AOI_size = par("AOIWidth");
00044     joinTimeout = par("joinTimeout");
00045     pingTimeout = par("pingTimeout");
00046     discoveryIntervall = par("discoveryIntervall");
00047     checkCriticalIntervall = par("criticalCheckIntervall");
00048     criticalThreshold = par("criticalThreshold");
00049     stockListSize = par("stockListSize");
00050 
00051     // set node key
00052     thisNode.setKey(OverlayKey::random());
00053     thisSite.type = THIS;
00054     thisSite.addr = thisNode;
00055 
00056     geom.setDebug(debugOutput);
00057 
00058     // self-messages
00059     join_timer = new cMessage("join_timer");
00060     ping_timer = new cMessage("ping_timer");
00061     sec_timer = new cMessage("sec_timer");
00062     discovery_timer = new cMessage("discovery_timer");
00063     checkcritical_timer = new cMessage("checkcritical_timer");
00064 
00065     // statistics
00066     joinRequestBytesSent = 0;
00067     joinAcknowledgeBytesSent = 0;
00068     nodeMoveBytesSent = 0;
00069     newNeighborsBytesSent = 0;
00070     nodeLeaveBytesSent = 0;
00071     enclosingNeighborsRequestBytesSent = 0;
00072     pingBytesSent = 0;
00073     pongBytesSent = 0;
00074     discardNodeBytesSent = 0;
00075 
00076     maxBytesPerSecondSent = 0;
00077     averageBytesPerSecondSent = 0;
00078     bytesPerSecond = 0;
00079     secTimerCount = 0;
00080 
00081     // watch some variables
00082     WATCH(AOI_size);
00083     WATCH(thisSite);
00084     WATCH_MAP(Sites);
00085     WATCH_SET(Positions);
00086 
00087     WATCH(joinRequestBytesSent);
00088     WATCH(joinAcknowledgeBytesSent);
00089     WATCH(nodeMoveBytesSent);
00090     WATCH(newNeighborsBytesSent);
00091     WATCH(nodeLeaveBytesSent);
00092     WATCH(enclosingNeighborsRequestBytesSent);
00093     WATCH(pingBytesSent);
00094     WATCH(pongBytesSent);
00095     WATCH(discardNodeBytesSent);
00096 
00097     WATCH(maxBytesPerSecondSent);
00098     WATCH(bytesPerSecond);
00099 
00100     // set initial state
00101     changeState(INIT);
00102     changeState(JOINING);
00103 }
00104 
00105 void Vast::changeState(int state)
00106 {
00107     switch(state) {
00108         case INIT: {
00109             this->state = INIT;
00110             globalNodeList->removePeer(thisSite.addr);
00111             cancelEvent(join_timer);
00112             cancelEvent(ping_timer);
00113             cancelEvent(sec_timer);
00114             cancelEvent(discovery_timer);
00115             cancelEvent(checkcritical_timer);
00116         } break;
00117         case JOINING: {
00118             this->state = JOINING;
00119             scheduleAt(simTime(), join_timer);
00120             scheduleAt(simTime() + 1.0, sec_timer);
00121         } break;
00122         case READY: {
00123             this->state = READY;
00124             cancelEvent(join_timer);
00125             globalNodeList->registerPeer(thisSite.addr);
00126             scheduleAt(simTime() + pingTimeout, ping_timer);
00127             if(checkCriticalIntervall > 0.0 && discoveryIntervall > 0.0) {
00128                 scheduleAt(simTime() + checkCriticalIntervall, checkcritical_timer);
00129                 scheduleAt(simTime() + discoveryIntervall, discovery_timer);
00130             }
00131             // tell the application we are ready
00132             CompReadyMessage* readyMsg = new CompReadyMessage("OVERLAY_READY");
00133             readyMsg->setReady(true);
00134             readyMsg->setComp(getThisCompType());
00135             sendToApp(readyMsg);
00136             GameAPIResizeAOIMessage* gameMsg = new GameAPIResizeAOIMessage("RESIZE_AOI");
00137             gameMsg->setCommand(RESIZE_AOI);
00138             gameMsg->setAOIsize(AOI_size);
00139             sendToApp(gameMsg);
00140         } break;
00141     }
00142     setBootstrapedIcon();
00143     // debug output
00144     if(debugOutput) {
00145         EV << "[Vast::changeState() @ " << thisSite.addr.getAddress()
00146            << " (" << thisSite.addr.getKey().toString(16) << ")]\n"
00147            << "VAST: Node " << thisSite.addr.getAddress() << " entered ";
00148         switch(state) {
00149             case INIT: ev << "INIT"; break;
00150             case JOINING: ev << "JOINING"; break;
00151             case READY: ev << "READY"; break;
00152         }
00153         ev << " state." << endl;
00154     }
00155 }
00156 
00157 void Vast::handleTimerEvent(cMessage* msg)
00158 {
00159     if(msg->isName("join_timer")) {
00160         //reset timer
00161         cancelEvent(join_timer);
00162         scheduleAt(simTime() + joinTimeout, msg);
00163         // handle event
00164         processJoinTimer();
00165     }
00166     else if(msg->isName("ping_timer")) {
00167         //reset timer
00168         cancelEvent(ping_timer);
00169         scheduleAt(simTime() + pingTimeout, msg);
00170         // handle event
00171         processPingTimer();
00172     }
00173     else if(msg->isName("sec_timer")) {
00174         //reset timer
00175         cancelEvent(sec_timer);
00176         scheduleAt(simTime() + 1, msg);
00177         // handle event
00178         processSecTimer();
00179     }
00180     else if(msg->isName("checkcritical_timer")) {
00181         //reset timer
00182         cancelEvent(checkcritical_timer);
00183         scheduleAt(simTime() + checkCriticalIntervall, msg);
00184         // handle event
00185         processCheckCriticalTimer();
00186     }
00187     else if(msg->isName("discovery_timer")) {
00188         //reset timer
00189         cancelEvent(discovery_timer);
00190         scheduleAt(simTime() + discoveryIntervall, msg);
00191         // handle event
00192         processDiscoveryTimer();
00193     }
00194 }
00195 
00196 void Vast::handleAppMessage(cMessage* msg)
00197 {
00198     if(dynamic_cast<GameAPIMessage*>(msg)) {
00199         GameAPIMessage* gameAPIMsg = check_and_cast<GameAPIMessage*>(msg);
00200         // debug output
00201         if(debugOutput) EV << "[Vast::handleAppMessage() @ " << thisSite.addr.getAddress()
00202                            << " (" << thisSite.addr.getKey().toString(16) << ")]\n"
00203                            << "    Node " << thisSite.addr.getAddress() << " received " << gameAPIMsg->getName() << " from application."
00204                            << endl;
00205         switch(gameAPIMsg->getCommand()) {
00206             case MOVEMENT_INDICATION: {
00207                 GameAPIPositionMessage* gameAPIPosMsg = check_and_cast<GameAPIPositionMessage*>(msg);
00208                 if(state == JOINING) {
00209                     handleJoin(gameAPIPosMsg);
00210                     delete msg;
00211                 }
00212                 else if(state == READY) {
00213                     handleMove(gameAPIPosMsg);
00214                     delete msg;
00215                 }
00216             } break;
00217             case GAMEEVENT_CHAT:
00218             case GAMEEVENT_SNOW:
00219             case GAMEEVENT_FROZEN:
00220                 handleEvent( gameAPIMsg );
00221                 delete msg;
00222                 break;
00223             default: {
00224                 delete msg;
00225             }
00226         }
00227     }
00228     else delete msg;
00229 }
00230 
00231 void Vast::handleUDPMessage(BaseOverlayMessage* msg)
00232 {
00233     if(state == INIT) {
00234         delete msg;
00235         return;
00236     }
00237     if(dynamic_cast<VastMessage*>(msg)) {
00238         VastMessage* vastMsg = check_and_cast<VastMessage*>(msg);
00239         if(vastMsg->getDestKey().isUnspecified() || 
00240            thisSite.addr.getKey().isUnspecified() ||
00241            vastMsg->getDestKey() == thisSite.addr.getKey()) {
00242             // debug output
00243             if(debugOutput) EV << "[Vast::handleUDPMessage() @ " << thisSite.addr.getAddress()
00244                                << " (" << thisSite.addr.getKey().toString(16) << ")]\n"
00245                                << "    Node " << thisSite.addr.getAddress() << " received " << vastMsg->getName() << " from " << vastMsg->getSourceNode().getAddress()
00246                                << endl;
00247             bool doUpdate = true;
00248             if(state == READY) {
00249                 switch(vastMsg->getCommand()) {
00250                     case JOIN_REQUEST: {
00251                         handleJoinRequest(vastMsg);
00252                         doUpdate = false;
00253                     } break;
00254                     case NODE_MOVE: {
00255                         VastMoveMessage* vastMoveMsg = check_and_cast<VastMoveMessage*>(msg);
00256                         handleNodeMove(vastMoveMsg);
00257                     } break;
00258                     case NEW_NEIGHBORS: {
00259                         VastListMessage* vastListMsg = check_and_cast<VastListMessage*>(msg);
00260                         handleNewNeighbors(vastListMsg);
00261                     } break;
00262                     case NODE_LEAVE: {
00263                         VastListMessage* vastListMsg = check_and_cast<VastListMessage*>(msg);
00264                         handleNodeLeave(vastListMsg);
00265                     } break;
00266                     case ENCLOSING_NEIGHBORS_REQUEST: {
00267                         handleEnclosingNeighborsRequest(vastMsg);
00268                     } break;
00269                     case BACKUP_NEIGHBORS: {
00270                         VastListMessage* vastListMsg = check_and_cast<VastListMessage*>(msg);
00271                         handleBackupNeighbors(vastListMsg);
00272                     } break;
00273                     case PING: {
00274                         handlePing(vastMsg);
00275                     } break;
00276                     case PONG: {
00277                         handlePong(vastMsg);
00278                     } break;
00279                     case DISCARD_NODE: {
00280                         VastDiscardMessage* vastDiscardMsg = check_and_cast<VastDiscardMessage*>(msg);
00281                         handleDiscardNode(vastDiscardMsg);
00282                     } break;
00283                     case VAST_EVENT: {
00284                         sendToApp(vastMsg->decapsulate());
00285                         doUpdate = false;
00286                         delete vastMsg;
00287                     } break;
00288                 }
00289                 // update timestamp
00290                 if(doUpdate) {
00291                     SiteMap::iterator itSites = Sites.find(vastMsg->getSourceNode());
00292                     if(itSites != Sites.end()) {
00293                         itSites->second->tstamp = simTime();
00294                     }
00295                     delete msg;
00296                 }
00297             }
00298             else if(state == JOINING && vastMsg->getCommand() == JOIN_ACKNOWLEDGE) {
00299                 VastListMessage* vastListMsg = check_and_cast<VastListMessage*>(msg);
00300                 handleJoinAcknowledge(vastListMsg);
00301                 delete msg;
00302             }
00303             else delete msg;
00304         }
00305         else {
00306             sendDiscardNode(vastMsg);
00307             delete msg;
00308         }
00309     }
00310     else delete msg;
00311 }
00312 
00313 void Vast::addNode(Vector2D p, NodeHandle node, int NeighborCount)
00314 {
00315     if(node != thisSite.addr) {
00316         if(Sites.find(node) == Sites.end()) {
00317             Site* temp_site = new Site();
00318             temp_site->coord = p;
00319             temp_site->addr = node;
00320             temp_site->neighborCount = NeighborCount;
00321 
00322             Sites.insert(std::make_pair(temp_site->addr, temp_site));
00323             Positions.insert(temp_site->coord);
00324         }
00325         else {
00326             SiteMap::iterator itSites = Sites.find(node);
00327             Positions.erase(itSites->second->coord);
00328             itSites->second->coord = p;
00329             Positions.insert(itSites->second->coord);
00330             if(NeighborCount != 0) {
00331                 itSites->second->neighborCount = NeighborCount;
00332             }
00333         }
00334     }
00335 }
00336 
00337 void Vast::addNodeToStock(NodeHandle node)
00338 {
00339     if(node != thisSite.addr) {
00340         for(StockList::iterator itTemp = Stock.begin(); itTemp != Stock.end(); ++itTemp) {
00341             if(*itTemp == node) {
00342                 return;
00343             }
00344         }
00345         Stock.push_front(node);
00346         if(Stock.size() > stockListSize) {
00347             Stock.pop_back();
00348         }
00349     }
00350 }
00351 
00352 void Vast::removeNode(NodeHandle node)
00353 {
00354     SiteMap::iterator itSites = Sites.find(node);
00355     if(itSites != Sites.end()) {
00356         Positions.erase(itSites->second->coord);
00357         delete itSites->second;
00358         Sites.erase(itSites);
00359     }
00360 }
00361 
00362 void Vast::buildVoronoi(Vector2D old_pos, Vector2D new_pos, NodeHandle enclosingCheck)
00363 {
00364     int sqrt_nsites = 1;
00365     double xmin, xmax, ymin, ymax;
00366     double deltax, deltay;
00367 
00368     // check wether there are any neighbors
00369     if(Sites.size() == 0) return;
00370 
00371     xmin = xmax = thisSite.coord.x;
00372     ymin = ymax = thisSite.coord.y;
00373 
00374     std::map<Vector2D, Site*> sortedSites;
00375     sortedSites.insert(std::make_pair(thisSite.coord, &thisSite));
00376 
00377     for(SiteMap::iterator itTemp = Sites.begin(); itTemp != Sites.end(); ++itTemp) {
00378         // determine min/max site coordinates
00379         if(itTemp->second->coord.x < xmin) xmin = itTemp->second->coord.x;
00380         if(itTemp->second->coord.x > xmax) xmax = itTemp->second->coord.x;
00381         if(itTemp->second->coord.y < ymin) ymin = itTemp->second->coord.y;
00382         if(itTemp->second->coord.y > ymax) ymax = itTemp->second->coord.y;
00383         // reset all sites to UNDEF
00384         itTemp->second->type = UNDEF;
00385         // reset enclosing neighbors set
00386         itTemp->second->enclosingSet.clear();
00387         // fill sorted List
00388         sortedSites.insert(std::make_pair(itTemp->second->coord, itTemp->second));
00389         sqrt_nsites++;
00390     }
00391 
00392     // needed to determine appropriate hashtable size
00393     deltax = xmax - xmin;
00394     deltay = ymax - ymin;
00395     sqrt_nsites = (int)sqrt((double)(sqrt_nsites+4));
00396 
00397     // start to calculate the voronoi
00398     Site *newsite, *bot, *top, *temp, *p, *v, *bottomsite;
00399     Vector2D newintstar;
00400     int pm;
00401     Halfedge *lbnd, *rbnd, *llbnd, *rrbnd, *bisector;
00402     Edge *e;
00403 
00404     newintstar.x = newintstar.y = 0.0;
00405 
00406     std::map<Vector2D, Site*>::iterator itSortedSites = sortedSites.begin();
00407 
00408     geom.initialize(deltax, deltay, thisSite.coord, old_pos, new_pos, AOI_size);
00409     heap.PQinitialize(sqrt_nsites, ymin, deltay);
00410     bottomsite = itSortedSites->second;
00411     ++itSortedSites;
00412     edgelist.initialize(sqrt_nsites, xmin, deltax, bottomsite);
00413 
00414     newsite = itSortedSites->second;
00415     ++itSortedSites;
00416     while(true) {
00417         if(!heap.PQempty()) newintstar = heap.PQ_min();
00418 
00419         if(newsite != NULL && (heap.PQempty() ||
00420            newsite->coord.y < newintstar.y ||
00421            (newsite->coord.y == newintstar.y && newsite->coord.x < newintstar.x))) {
00422             lbnd = edgelist.ELleftbnd(&(newsite->coord));
00423             rbnd = edgelist.ELright(lbnd);
00424             bot = edgelist.rightreg(lbnd);
00425             e = geom.bisect(bot, newsite);
00426             bisector = edgelist.HEcreate(e, le);
00427             edgelist.ELinsert(lbnd, bisector);
00428             if ((p = geom.intersect(lbnd, bisector)) != NULL) {
00429                 heap.PQdelete(lbnd);
00430                 heap.PQinsert(lbnd, p, geom.dist(p, newsite));
00431             }
00432             lbnd = bisector;
00433             bisector = edgelist.HEcreate(e, re);
00434             edgelist.ELinsert(lbnd, bisector);
00435             if ((p = geom.intersect(bisector, rbnd)) != NULL) heap.PQinsert(bisector, p, geom.dist(p, newsite));
00436             if(itSortedSites != sortedSites.end()) {
00437                 newsite = itSortedSites->second;
00438                 ++itSortedSites;
00439             }
00440             else newsite = NULL;
00441         }
00442         else if (!heap.PQempty()) {
00443             lbnd = heap.PQextractmin();
00444             llbnd = edgelist.ELleft(lbnd);
00445             rbnd = edgelist.ELright(lbnd);
00446             rrbnd = edgelist.ELright(rbnd);
00447             bot = edgelist.leftreg(lbnd);
00448             top = edgelist.rightreg(rbnd);
00449             v = lbnd->vertex;
00450             geom.endpoint(lbnd->ELedge, lbnd->ELpm, v);
00451             geom.endpoint(rbnd->ELedge, rbnd->ELpm, v);
00452             edgelist.ELdelete(lbnd);
00453             heap.PQdelete(rbnd);
00454             edgelist.ELdelete(rbnd);
00455             pm = le;
00456             if (bot->coord.y > top->coord.y) {
00457                 temp = bot;
00458                 bot = top;
00459                 top = temp;
00460                 pm = re;
00461             }
00462             e = geom.bisect(bot, top);
00463             bisector = edgelist.HEcreate(e, pm);
00464             edgelist.ELinsert(llbnd, bisector);
00465             geom.endpoint(e, re-pm, v);
00466             if((p = geom.intersect(llbnd, bisector)) != NULL) {
00467                 heap.PQdelete(llbnd);
00468                 heap.PQinsert(llbnd, p, geom.dist(p, bot));
00469             }
00470             if ((p = geom.intersect(bisector, rrbnd)) != NULL) heap.PQinsert(bisector, p, geom.dist(p, bot));
00471         }
00472         else break;
00473     }
00474 
00475     // process the generated edgelist
00476     for(lbnd = edgelist.ELright(edgelist.ELleftend); lbnd != edgelist.ELrightend; lbnd = edgelist.ELright(lbnd)) {
00477         e = lbnd -> ELedge;
00478         geom.processEdge(e);
00479     }
00480     // process sites in order to determine our neighbors
00481     for(SiteMap::iterator itTemp = Sites.begin(); itTemp != Sites.end(); ++itTemp) {
00482         if(itTemp->second->innerEdge[0]) {
00483             if(itTemp->second->outerEdge) {
00484                 itTemp->second->type |= BOUNDARY;
00485                 // Debug output
00486                 if(debugOutput)
00487                     EV << "[NeighborsList::buildVoronoi()]\n"
00488                        << "    Site at [" << itTemp->second->coord.x << ", "
00489                        << itTemp->second->coord.y << "] is a boundary neighbor."
00490                        << endl;
00491             }
00492             else {
00493                 itTemp->second->type |= NEIGHBOR;
00494                 // Debug output
00495                 if(debugOutput)
00496                     EV << "[NeighborsList::buildVoronoi()]\n"
00497                        << "    Site at [" << itTemp->second->coord.x << ", "
00498                        << itTemp->second->coord.y << "] is a neighbor."
00499                        << endl;
00500             }
00501         }
00502         // Treat enclosing neighbors whose voronoi region is outside our AOI as boundary neighbors
00503         if((!itTemp->second->type & NEIGHBOR) && (itTemp->second->type & ENCLOSING)) {
00504             itTemp->second->type |= BOUNDARY;
00505             // Debug output
00506             if(debugOutput)
00507                 EV << "[NeighborsList::buildVoronoi()]\n"
00508                 << "    Site at [" << itTemp->second->coord.x << ", "
00509                 << itTemp->second->coord.y << "] is a boundary neighbor."
00510                 << endl;
00511         }
00512         if(!itTemp->second->innerEdge[1] && itTemp->second->innerEdge[2]) {
00513             itTemp->second->type |= NEW;
00514             // Debug output
00515             if(debugOutput)
00516                 EV << "[NeighborsList::buildVoronoi()]\n"
00517                    << "    Site at [" << itTemp->second->coord.x << ", "
00518                    << itTemp->second->coord.y << "] is a new neighbor for site at " << new_pos.x << ":" << new_pos.y << "."
00519                    << endl;
00520         }
00521         // enhanced enclosing check
00522         if(!enclosingCheck.isUnspecified() && (Sites.find(enclosingCheck) != Sites.end())) {
00523             Site* tempSite = Sites.find(enclosingCheck)->second;
00524             for(EnclosingSet::iterator itSet = tempSite->enclosingSet.begin(); itSet != tempSite->enclosingSet.end(); ++itSet) {
00525                 if(tempSite->oldEnclosingSet.find(*itSet) == tempSite->oldEnclosingSet.end()
00526                     && Sites.find(*itSet) != Sites.end()) {
00527                     Sites.find(*itSet)->second->type |= NEW;
00528                 }
00529             }
00530             tempSite->enclosingSet.swap(tempSite->oldEnclosingSet);
00531         }
00532         // reset inner- and outeredge indicator
00533         itTemp->second->innerEdge[0] = false;
00534         itTemp->second->innerEdge[1] = false;
00535         itTemp->second->innerEdge[2] = false;
00536         itTemp->second->outerEdge = false;
00537     }
00538     // clean up
00539     edgelist.reset();
00540     heap.PQreset();
00541     geom.reset();
00542 }
00543 
00544 void Vast::buildVoronoi()
00545 {
00546     buildVoronoi(thisSite.coord, thisSite.coord);
00547 }
00548 
00549 void Vast::removeNeighbors()
00550 {
00551     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end();) {
00552         // if current site is no neighbor remove it else go on to next site
00553         if(itSites->second->type == UNDEF) {
00554             // Debug output
00555             if(debugOutput)  EV << "[NeighborsList::removeNeighbors()]\n"
00556                                 << "    Site at [" << itSites->second->coord.x << ", " << itSites->second->coord.y
00557                                 << "] has been removed from list."
00558                                 << endl;
00559             Positions.erase(itSites->second->coord);
00560             delete itSites->second;
00561             Sites.erase(itSites++);
00562         }
00563         else ++itSites;
00564     }
00565 }
00566 
00567 void Vast::handleNodeLeaveNotification()
00568 {
00569     if(state == READY) {
00570         // debug output
00571         if(debugOutput) {
00572             EV << "[Vast::receiveChangeNotification() @ " << thisSite.addr.getAddress()
00573                << " (" << thisSite.addr.getKey().toString(16) << ")]\n"
00574                << "    Node " << thisSite.addr.getAddress() << " is leaving the overlay."
00575                << endl;
00576         }
00577 
00578         CompReadyMessage* readyMsg = new CompReadyMessage("OVERLAY_FINISHED");
00579         readyMsg->setReady(false);
00580         readyMsg->setComp(getThisCompType());
00581         sendToApp(readyMsg);
00582     }
00583 }
00584 
00585 void Vast::handleNodeGracefulLeaveNotification()
00586 {
00587      if(state == READY) {
00588         // generate node leave messages
00589         VastListMessage *vastListMsg = new VastListMessage("NODE_LEAVE");
00590         vastListMsg->setCommand(NODE_LEAVE);
00591         // fill neighbors list
00592         vastListMsg->setNeighborNodeArraySize(Sites.size());
00593         vastListMsg->setNeighborPosArraySize(Sites.size());
00594         int i = 0;
00595         for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00596             if(itSites->second->type & ENCLOSING) {
00597                 vastListMsg->setNeighborNode(i, itSites->second->addr);
00598                 vastListMsg->setNeighborPos(i, itSites->second->coord);
00599                 ++i;
00600             }
00601         }
00602         vastListMsg->setNeighborNodeArraySize(i);
00603         vastListMsg->setNeighborPosArraySize(i);
00604 
00605         vastListMsg->setBitLength(VASTLIST_L(vastListMsg));
00606         if(vastListMsg->getNeighborNodeArraySize() > 0) {
00607             for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00608                 VastListMessage *vastCopyMsg = new VastListMessage(*vastListMsg);
00609                sendMessage(vastCopyMsg, itSites->second->addr);
00610             }
00611         }
00612         delete vastListMsg;
00613         changeState(INIT);
00614     }
00615 }
00616 
00617 void Vast::processJoinTimer()
00618 {
00619     GameAPIMessage *sgcMsg = new GameAPIMessage("MOVEMENT_REQUEST");
00620     sgcMsg->setCommand(MOVEMENT_REQUEST);
00621     sendToApp(sgcMsg);
00622 }
00623 
00624 void Vast::processPingTimer()
00625 {
00626     bool abnormalLeave = false;
00627     bool boundaryLeave = false;
00628     std::set<NodeHandle> removeSet;
00629     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00630         if(itSites->second->tstamp < 0.0) { // node is dropped cause no pong has been received see below
00631             abnormalLeave = true;
00632             if(!(itSites->second->type & NEIGHBOR)) boundaryLeave = true;
00633             itSites->second->type = UNDEF;
00634             removeSet.insert( itSites->first );
00635         }
00636         else if(itSites->second->tstamp < simTime() - pingTimeout) { // node showed no activity for some time request pong and mark it to be dropped next time
00637             VastMessage *vastMsg = new VastMessage("PING");
00638             vastMsg->setCommand(PING);
00639             vastMsg->setBitLength(VAST_L(vastMsg));
00640             sendMessage(vastMsg, itSites->second->addr);
00641             itSites->second->tstamp = -1.0;
00642         }
00643     }
00644     if(abnormalLeave) {
00645         synchronizeApp();
00646         for( std::set<NodeHandle>::iterator it = removeSet.begin(); it != removeSet.end(); ++it) {
00647             removeNode( *it );
00648         }
00649         // removeNeighbors();
00650         if(boundaryLeave) {
00651             for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00652                 if(itSites->second->type & BOUNDARY) {
00653                     VastMessage *vastMsg = new VastMessage("ENCLOSING_NEIGHBORS_REQUEST");
00654                     vastMsg->setCommand(ENCLOSING_NEIGHBORS_REQUEST);
00655                     vastMsg->setBitLength(VAST_L(vastMsg));
00656                     sendMessage(vastMsg, itSites->second->addr);
00657                 }
00658             }
00659         }
00660         //buildVoronoi();
00661         //removeNeighbors(); should be superfluous
00662     }
00663 }
00664 
00665 void Vast::processSecTimer()
00666 {
00667     RECORD_STATS(
00668         if(bytesPerSecond > maxBytesPerSecondSent) {
00669             maxBytesPerSecondSent = bytesPerSecond;
00670         }
00671         averageBytesPerSecondSent += bytesPerSecond;
00672         ++secTimerCount;
00673     );
00674     bytesPerSecond = 0;
00675 }
00676 
00677 void Vast::processCheckCriticalTimer()
00678 {
00679     double NeighborLevel;
00680     int NeighborSum = 0;
00681     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00682         if(itSites->second->neighborCount > 0) {
00683             NeighborSum += itSites->second->neighborCount;
00684         }
00685     }
00686     NeighborLevel = (double)(Sites.size() * Sites.size()) / (double)NeighborSum;
00687 
00688     if(NeighborLevel < criticalThreshold) {
00689         VastListMessage *vastListMsg = new VastListMessage("BACKUP_NEIGHBORS");
00690         vastListMsg->setCommand(BACKUP_NEIGHBORS);
00691         // fill neighbors list
00692         vastListMsg->setNeighborNodeArraySize(Sites.size());
00693         vastListMsg->setNeighborPosArraySize(Sites.size());
00694         int i = 0;
00695         for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00696             vastListMsg->setNeighborNode(i, itSites->second->addr);
00697             vastListMsg->setNeighborPos(i, itSites->second->coord);
00698             ++i;
00699         }
00700         vastListMsg->setBitLength(VASTLIST_L(vastListMsg));
00701         for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00702             VastListMessage *vastCopyMsg = new VastListMessage(*vastListMsg);
00703             sendMessage(vastCopyMsg, itSites->second->addr);
00704         }
00705         delete vastListMsg;
00706     }
00707 }
00708 
00709 void Vast::processDiscoveryTimer()
00710 {
00711     for(StockList::iterator itStock = Stock.begin(); itStock != Stock.end(); ++itStock) {
00712         VastMoveMessage *vastMoveMsg = new VastMoveMessage("NODE_MOVE");
00713         vastMoveMsg->setCommand(NODE_MOVE);
00714         vastMoveMsg->setNewPos(thisSite.coord);
00715         vastMoveMsg->setRequest_list(true);
00716         vastMoveMsg->setBitLength(VASTMOVE_L(vastMoveMsg));
00717         sendMessage(vastMoveMsg, *itStock);
00718     }
00719 }
00720 
00721 void Vast::handleJoin(GameAPIPositionMessage *sgcMsg)
00722 {
00723     TransportAddress joinNode = bootstrapList->getBootstrapNode();
00724     thisSite.coord = sgcMsg->getPosition();
00725     // check if this is the only node in the overlay
00726     if(joinNode.isUnspecified()) {
00727         changeState(READY);
00728     }
00729     else {
00730         VastMessage *vastMsg = new VastMessage("JOIN_REQUEST");
00731         vastMsg->setCommand(JOIN_REQUEST);
00732         vastMsg->setBitLength(VAST_L(vastMsg));
00733         sendMessage(vastMsg, joinNode);
00734     }
00735 }
00736 
00737 void Vast::handleMove(GameAPIPositionMessage* sgcMsg)
00738 {
00739     Vector2D pos = sgcMsg->getPosition();
00740     // test if new position is legal
00741     if(Positions.find(pos) != Positions.end()) {
00742         GameAPIMessage *gameMsg = new GameAPIMessage("MOVEMENT_REQUEST");
00743         gameMsg->setCommand(MOVEMENT_REQUEST);
00744         sendToApp(gameMsg);
00745         return;
00746     }
00747     // set new position
00748     thisSite.coord = pos;
00749     // update voronoi
00750     buildVoronoi();
00751     synchronizeApp();
00752     removeNeighbors();
00753     // send position update to neighbors
00754     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00755         VastMoveMessage *vastMoveMsg = new VastMoveMessage("NODE_MOVE");
00756         vastMoveMsg->setCommand(NODE_MOVE);
00757         vastMoveMsg->setNewPos(pos);
00758         vastMoveMsg->setIs_boundary(itSites->second->type & BOUNDARY);
00759         vastMoveMsg->setBitLength(VASTMOVE_L(vastMoveMsg));
00760         sendMessage(vastMoveMsg, itSites->second->addr);
00761     }
00762 }
00763 
00764 void Vast::handleEvent( GameAPIMessage* msg )
00765 {
00766     // send event to neighbors
00767     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00768         VastEventMessage *vastMsg = new VastEventMessage("EVENT");
00769         vastMsg->setCommand(VAST_EVENT);
00770         vastMsg->encapsulate((cPacket*)msg->dup());
00771         // FIXME: Message length!
00772         sendMessage(vastMsg, itSites->second->addr);
00773     }
00774 }
00775 
00776 void Vast::handleJoinRequest(VastMessage *vastMsg)
00777 {
00778     Site *forwardSite = NULL;
00779     // start with this node
00780     double min_dist = thisSite.coord.distanceSqr(vastMsg->getPos());
00781     forwardSite = &thisSite;
00782     // iterate through all neighbors
00783     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00784         // dont forward to nodes which are still joining
00785         if(itSites->second->coord.distanceSqr(vastMsg->getPos()) < min_dist && itSites->second->neighborCount >= 0) {
00786             min_dist = itSites->second->coord.distanceSqr(vastMsg->getPos());
00787             forwardSite = itSites->second;
00788         }
00789     }
00790     // do nothing and let node retry with new position if current position is illegal
00791     if(min_dist == 0.0) {
00792         delete vastMsg;
00793     }
00794     else {
00795         // send an acknowledge or forward request if any of our neighbors is closer to joining node
00796         if(forwardSite->type & THIS) {
00797             VastListMessage *vastListMsg = new VastListMessage("JOIN_ACKNOWLEDGE");
00798             vastListMsg->setCommand(JOIN_ACKNOWLEDGE);
00799             // fill neighbors list
00800             vastListMsg->setNeighborNodeArraySize(Sites.size());
00801             vastListMsg->setNeighborPosArraySize(Sites.size());
00802             int i = 0;
00803             for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00804                 vastListMsg->setNeighborNode(i, itSites->second->addr);
00805                 vastListMsg->setNeighborPos(i, itSites->second->coord);
00806                 ++i;
00807             }
00808 
00809             vastListMsg->setBitLength(VASTLIST_L(vastListMsg));
00810             sendMessage(vastListMsg, vastMsg->getSourceNode());
00811 
00812             // add node to list to propagte its position early
00813             // nieghborCount is set to -1 to indicate node is still joining
00814             addNode(vastMsg->getPos(), vastMsg->getSourceNode(), -1);
00815             // update voronoi with new neighbors
00816             buildVoronoi();
00817             synchronizeApp();
00818             // removeNeighbors();
00819             delete vastMsg;
00820         }
00821         else {
00822             sendMessage(vastMsg, forwardSite->addr);
00823         }
00824     }
00825 }
00826 
00827 void Vast::handleJoinAcknowledge(VastListMessage *vastListMsg)
00828 {
00829     // add acceptor node
00830     changeState(READY);
00831     addNode(vastListMsg->getPos(), vastListMsg->getSourceNode(), vastListMsg->getNeighborCount());
00832     // add new neighbors
00833     for(unsigned int i=0; i<vastListMsg->getNeighborNodeArraySize(); i++) {
00834         addNode(vastListMsg->getNeighborPos(i), vastListMsg->getNeighborNode(i));
00835     }
00836     // update voronoi with new neighbors
00837     buildVoronoi();
00838     synchronizeApp();
00839     // removeNeighbors();
00840     // contact new neighbors
00841     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00842         VastMoveMessage *vastMoveMsg = new VastMoveMessage("NODE_MOVE");
00843         vastMoveMsg->setCommand(NODE_MOVE);
00844         vastMoveMsg->setNewPos(thisSite.coord);
00845         vastMoveMsg->setIs_boundary(itSites->second->type & BOUNDARY);
00846         vastMoveMsg->setRequest_list(true);
00847         vastMoveMsg->setBitLength(VASTMOVE_L(vastMoveMsg));
00848         sendMessage(vastMoveMsg, itSites->second->addr);
00849     }
00850 }
00851 
00852 void Vast::handleNodeMove(VastMoveMessage *vastMoveMsg)
00853 {
00854     RECORD_STATS(
00855             globalStatistics->addStdDev(
00856                 "Vast: MoveDelay",
00857                 SIMTIME_DBL(simTime()) - SIMTIME_DBL(vastMoveMsg->getCreationTime())
00858                 );
00859             );
00860 
00861     Vector2D old_p, new_p;
00862     old_p = vastMoveMsg->getPos();
00863     new_p = vastMoveMsg->getNewPos();
00864     addNode(new_p, vastMoveMsg->getSourceNode(), vastMoveMsg->getNeighborCount());
00865     // update voronoi with new neighbor detection or without
00866     if(vastMoveMsg->getIs_boundary() || vastMoveMsg->getRequest_list()) {
00867         buildVoronoi(old_p, new_p, vastMoveMsg->getSourceNode()); // enhanced enclosing check
00868         synchronizeApp(vastMoveMsg);
00869         // removeNeighbors();
00870         // send new neighbors
00871         VastListMessage *vastListMsg = new VastListMessage("NEW_NEIGHBORS");
00872         vastListMsg->setCommand(NEW_NEIGHBORS);
00873 
00874         vastListMsg->setNeighborNodeArraySize(Sites.size());
00875         vastListMsg->setNeighborPosArraySize(Sites.size());
00876 
00877         int i = 0;
00878         for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00879             if(itSites->second->type & NEW || vastMoveMsg->getRequest_list()) {
00880                 vastListMsg->setNeighborNode(i, itSites->second->addr);
00881                 vastListMsg->setNeighborPos(i, itSites->second->coord);
00882                 ++i;
00883             }
00884         }
00885         vastListMsg->setNeighborNodeArraySize(i);
00886         vastListMsg->setNeighborPosArraySize(i);
00887         vastListMsg->setRequestEnclosingNeighbors(true);
00888 
00889         vastListMsg->setBitLength(VASTLIST_L(vastListMsg));
00890         if(vastListMsg->getNeighborNodeArraySize() > 0) {
00891             sendMessage(vastListMsg, vastMoveMsg->getSourceNode());
00892         }
00893         else {
00894             delete vastListMsg;
00895         }
00896     }
00897     else {
00898         // buildVoronoi();
00899         synchronizeApp(vastMoveMsg);
00900         // removeNeighbors();
00901     }
00902 }
00903 
00904 void Vast::handleNewNeighbors(VastListMessage *vastListMsg)
00905 {
00906     // add new neighbors
00907     for(unsigned int i=0; i<vastListMsg->getNeighborNodeArraySize(); i++) {
00908         addNode(vastListMsg->getNeighborPos(i), vastListMsg->getNeighborNode(i));
00909 
00910         if(vastListMsg->getRequestEnclosingNeighbors()) {
00911             VastMessage *vastMsg = new VastMessage("ENCLOSING_NEIGHBORS_REQUEST");
00912             vastMsg->setCommand(ENCLOSING_NEIGHBORS_REQUEST);
00913             vastMsg->setBitLength(VAST_L(vastMsg));
00914             sendMessage(vastMsg, vastListMsg->getNeighborNode(i));
00915         }
00916     }
00917     // update voronoi with new neighbors
00918 //    buildVoronoi();
00919 //    synchronizeApp();
00920     // removeNeighbors();
00921 }
00922 
00923 void Vast::handleNodeLeave(VastListMessage *vastListMsg)
00924 {
00925     removeNode(vastListMsg->getSourceNode());
00926     // add possible new neighbors
00927     for(unsigned int i=0; i<vastListMsg->getNeighborNodeArraySize(); i++) {
00928         addNode(vastListMsg->getNeighborPos(i), vastListMsg->getNeighborNode(i));
00929     }
00930     // update voronoi with new neighbors
00931     // buildVoronoi();
00932     // synchronizeApp();
00933     // removeNeighbors();
00934 }
00935 
00936 void Vast::handleEnclosingNeighborsRequest(VastMessage *vastMsg)
00937 {
00938     // send new neighbors
00939     VastListMessage *vastListMsg = new VastListMessage("NEW_NEIGHBORS");
00940     vastListMsg->setCommand(NEW_NEIGHBORS);
00941 
00942     vastListMsg->setNeighborNodeArraySize(Sites.size());
00943     vastListMsg->setNeighborPosArraySize(Sites.size());
00944 
00945     int i = 0;
00946     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00947         if((itSites->second->type & ENCLOSING) && itSites->second->addr != vastMsg->getSourceNode()) {
00948             vastListMsg->setNeighborNode(i, itSites->second->addr);
00949             vastListMsg->setNeighborPos(i, itSites->second->coord);
00950             ++i;
00951         }
00952     }
00953     vastListMsg->setNeighborNodeArraySize(i);
00954     vastListMsg->setNeighborPosArraySize(i);
00955 
00956     vastListMsg->setBitLength(VASTLIST_L(vastListMsg));
00957     if(vastListMsg->getNeighborNodeArraySize() > 0) {
00958         sendMessage(vastListMsg, vastMsg->getSourceNode());
00959     }
00960     else {
00961         delete vastListMsg;
00962     }
00963 }
00964 
00965 void Vast::handleBackupNeighbors(VastListMessage *vastListMsg)
00966 {
00967     // add new neighbors to stock list
00968     for(unsigned int i=0; i<vastListMsg->getNeighborNodeArraySize(); i++) {
00969         if(Sites.find(vastListMsg->getNeighborNode(i)) == Sites.end()) {
00970             addNodeToStock(vastListMsg->getNeighborNode(i));
00971         }
00972     }
00973 }
00974 
00975 void Vast::handlePing(VastMessage *vastMsg)
00976 {
00977     VastMessage *vastPongMsg = new VastMessage("PONG");
00978     vastPongMsg->setCommand(PONG);
00979     vastPongMsg->setBitLength(VAST_L(vastPongMsg));
00980     sendMessage(vastPongMsg, vastMsg->getSourceNode());
00981 }
00982 
00983 void Vast::handlePong(VastMessage *vastMsg)
00984 {
00985     // replace entry cause it was probably outdated
00986     addNode(vastMsg->getPos(), vastMsg->getSourceNode(), vastMsg->getNeighborCount());
00987     // update voronoi
00988     //buildVoronoi();
00989     //synchronizeApp();
00990     // removeNeighbors();
00991 }
00992 
00993 void Vast::handleDiscardNode(VastDiscardMessage *vastMsg)
00994 {
00995     // discard outdated entry
00996     removeNode(vastMsg->getDiscardNode());
00997     // update voronoi
00998     //buildVoronoi();
00999     //synchronizeApp();
01000     // removeNeighbors();
01001 }
01002 
01003 void Vast::sendDiscardNode(VastMessage *vastMsg)
01004 {
01005     NodeHandle discardNode;
01006     discardNode.setAddress(thisSite.addr.getAddress());
01007     discardNode.setKey(vastMsg->getDestKey());
01008     // send message
01009     VastDiscardMessage *vastDiscardMsg = new VastDiscardMessage("DISCARD_NODE");
01010     vastDiscardMsg->setCommand(DISCARD_NODE);
01011     vastDiscardMsg->setDiscardNode(discardNode);
01012     // debug output
01013     if(debugOutput) EV << "[Vast::sendDiscardNode() @ " << thisSite.addr.getAddress()
01014                        << " (" << thisSite.addr.getKey().toString(16) << ")]\n"
01015                        << "    Node " << thisSite.addr.getAddress() << " is leaving the overlay."
01016                        << endl;
01017     vastDiscardMsg->setBitLength(VASTDISCARD_L(vastDiscardMsg));
01018     sendMessage(vastDiscardMsg, vastMsg->getSourceNode());
01019 }
01020 
01021 void Vast::synchronizeApp(VastMoveMessage *vastMoveMsg)
01022 {
01023     GameAPIListMessage *sgcMsg = new GameAPIListMessage("NEIGHBOR_UPDATE");
01024     sgcMsg->setCommand(NEIGHBOR_UPDATE);
01025 
01026     sgcMsg->setRemoveNeighborArraySize(Sites.size());
01027     sgcMsg->setAddNeighborArraySize(Sites.size() + 1);
01028     sgcMsg->setNeighborPositionArraySize(Sites.size() + 1);
01029 
01030     int remSize, addSize;
01031     remSize = addSize = 0;
01032     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
01033         if(itSites->second->type == UNDEF) {
01034             sgcMsg->setRemoveNeighbor(remSize, itSites->second->addr);
01035             ++remSize;
01036         }
01037         else if(!itSites->second->isAdded) {
01038             sgcMsg->setAddNeighbor(addSize, itSites->second->addr);
01039             sgcMsg->setNeighborPosition(addSize, itSites->second->coord);
01040             itSites->second->isAdded = true;
01041             ++addSize;
01042         }
01043     }
01044 
01045     if(vastMoveMsg &&
01046        Sites.find(vastMoveMsg->getSourceNode()) != Sites.end() &&
01047        Sites.find(vastMoveMsg->getSourceNode())->second->isAdded) {
01048         sgcMsg->setAddNeighbor(addSize, vastMoveMsg->getSourceNode());
01049         sgcMsg->setNeighborPosition(addSize, vastMoveMsg->getNewPos());
01050         ++addSize;
01051     }
01052 
01053     sgcMsg->setRemoveNeighborArraySize(remSize);
01054     sgcMsg->setAddNeighborArraySize(addSize);
01055     sgcMsg->setNeighborPositionArraySize(addSize);
01056 
01057     if(sgcMsg->getAddNeighborArraySize() || sgcMsg->getRemoveNeighborArraySize()) {
01058         sendToApp(sgcMsg);
01059     }
01060     else {
01061         delete sgcMsg;
01062     }
01063 }
01064 
01065 void Vast::sendToApp(cMessage *msg)
01066 {
01067     // debug output
01068     if(debugOutput) EV << "[Vast::sendToApp() @ " << thisSite.addr.getAddress()
01069                        << " (" << thisSite.addr.getKey().toString(16) << ")]\n"
01070                        << "    Node " << thisSite.addr.getAddress() << " sending " << msg->getName() << " to application."
01071                        << endl;
01072     send(msg, "appOut");
01073 }
01074 
01075 void Vast::sendMessage(VastMessage *vastMsg, NodeHandle destAddr)
01076 {
01077     // collect statistics
01078     RECORD_STATS(
01079         switch(vastMsg->getCommand()) {
01080             case JOIN_REQUEST: {
01081                 joinRequestBytesSent += vastMsg->getByteLength();
01082             } break;
01083             case JOIN_ACKNOWLEDGE: {
01084                 joinAcknowledgeBytesSent += vastMsg->getByteLength();
01085             } break;
01086             case NODE_MOVE: {
01087                 nodeMoveBytesSent += vastMsg->getByteLength();
01088             } break;
01089             case NEW_NEIGHBORS: {
01090                 newNeighborsBytesSent += vastMsg->getByteLength();
01091             } break;
01092             case NODE_LEAVE: {
01093                 nodeLeaveBytesSent += vastMsg->getByteLength();
01094             } break;
01095             case ENCLOSING_NEIGHBORS_REQUEST: {
01096                 enclosingNeighborsRequestBytesSent += vastMsg->getByteLength();
01097             } break;
01098             case PING: {
01099                 pingBytesSent += vastMsg->getByteLength();
01100             } break;
01101             case PONG: {
01102                 pongBytesSent += vastMsg->getByteLength();
01103             } break;
01104             case DISCARD_NODE: {
01105                 discardNodeBytesSent += vastMsg->getByteLength();
01106             } break;
01107         }
01108         bytesPerSecond += vastMsg->getByteLength();
01109     );
01110 
01111     // debug output
01112     if(debugOutput) EV << "[Vast::sendMessage() @ " << thisSite.addr.getAddress()
01113                        << " (" << thisSite.addr.getKey().toString(16) << ")]\n"
01114                        << "    Node " << thisSite.addr.getAddress() << " sending " << vastMsg->getName() << " to " << destAddr.getAddress() << "."
01115                        << endl;
01116     // set vastbase message stuff
01117     vastMsg->setDestKey(destAddr.getKey());
01118     // fill in sender information only if we are not forwarding a message from another node
01119     // e.g. a joining node
01120     if(vastMsg->getSourceNode().isUnspecified()) {
01121         vastMsg->setSourceNode(thisSite.addr);
01122         vastMsg->setPos(thisSite.coord);
01123         vastMsg->setNeighborCount(Sites.size());
01124     }
01125 
01126     sendMessageToUDP(destAddr, vastMsg);
01127 }
01128 
01129 void Vast::setBootstrapedIcon()
01130 {
01131     if(ev.isGUI()) {
01132         if(state == READY) {
01133             getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 1, "green");
01134             getDisplayString().setTagArg("i", 1, "green");
01135         }
01136         else if(state == JOINING) {
01137             getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 1, "yellow");
01138             getDisplayString().setTagArg("i", 1, "yellow");
01139         }
01140         else {
01141             getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 1, "red");
01142             getDisplayString().setTagArg("i", 1, "red");
01143         }
01144     }
01145 }
01146 
01147 void Vast::finishOverlay()
01148 {
01149     globalNodeList->removePeer(thisSite.addr);
01150 
01151 //    We use our own time count to avoid rounding errors
01152 //    simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
01153 //    if(time == 0) return;
01154     if(secTimerCount == 0) return;
01155 
01156     // collect statistics
01157     globalStatistics->addStdDev("Vast: JOIN_REQUEST bytes sent/s", joinRequestBytesSent/(double) secTimerCount);
01158     globalStatistics->addStdDev("Vast: JOIN_ACKNOWLEDGE bytes sent/s", joinAcknowledgeBytesSent/(double) secTimerCount);
01159     globalStatistics->addStdDev("Vast: NODE_MOVE bytes sent/s", nodeMoveBytesSent/(double) secTimerCount);
01160     globalStatistics->addStdDev("Vast: NEW_NEIGHBORS bytes sent/s", newNeighborsBytesSent/(double) secTimerCount);
01161     globalStatistics->addStdDev("Vast: NODE_LEAVE bytes sent/s", nodeLeaveBytesSent/(double) secTimerCount);
01162     globalStatistics->addStdDev("Vast: ENCLOSING_NEIGHBORS_REQUEST bytes sent/s", enclosingNeighborsRequestBytesSent/(double) secTimerCount);
01163     globalStatistics->addStdDev("Vast: PING bytes sent/s", pingBytesSent/(double) secTimerCount);
01164     globalStatistics->addStdDev("Vast: PONG bytes sent/s", pongBytesSent/(double) secTimerCount);
01165     globalStatistics->addStdDev("Vast: DISCARD_NODE bytes sent/s", discardNodeBytesSent/(double) secTimerCount);
01166 
01167     globalStatistics->addStdDev("Vast: max bytes/second sent", maxBytesPerSecondSent);
01168     globalStatistics->addStdDev("Vast: average bytes/second sent", averageBytesPerSecondSent / (double) secTimerCount);
01169 }
01170 
01171 double Vast::getAOI()
01172 {
01173     Enter_Method_Silent();
01174     return AOI_size;
01175 }
01176 
01177 Vector2D Vast::getPosition()
01178 {
01179     Enter_Method_Silent();
01180     return thisSite.coord;
01181 }
01182 
01183 NodeHandle Vast::getHandle()
01184 {
01185     Enter_Method_Silent();
01186     return thisSite.addr;
01187 }
01188 
01189 double Vast::getAreaDimension()
01190 {
01191     Enter_Method_Silent();
01192     return areaDimension;
01193 }
01194 
01195 Vast::~Vast()
01196 {
01197     if(Sites.size()) {
01198         for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
01199             delete itSites->second;
01200         }
01201         Sites.clear();
01202         Positions.clear();
01203     }
01204     // destroy self timer messages
01205     cancelAndDelete(join_timer);
01206     cancelAndDelete(ping_timer);
01207     cancelAndDelete(sec_timer);
01208     cancelAndDelete(discovery_timer);
01209     cancelAndDelete(checkcritical_timer);
01210 }
Generated on Wed May 26 16:21:15 2010 for OverSim by  doxygen 1.6.3