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)
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         // fill sorted List
00386         sortedSites.insert(std::make_pair(itTemp->second->coord, itTemp->second));
00387         sqrt_nsites++;
00388     }
00389 
00390     // needed to determine appropriate hashtable size
00391     deltax = xmax - xmin;
00392     deltay = ymax - ymin;
00393     sqrt_nsites = (int)sqrt((double)(sqrt_nsites+4));
00394 
00395     // start to calculate the voronoi
00396     Site *newsite, *bot, *top, *temp, *p, *v, *bottomsite;
00397     Vector2D newintstar;
00398     int pm;
00399     Halfedge *lbnd, *rbnd, *llbnd, *rrbnd, *bisector;
00400     Edge *e;
00401 
00402     newintstar.x = newintstar.y = 0.0;
00403 
00404     std::map<Vector2D, Site*>::iterator itSortedSites = sortedSites.begin();
00405 
00406     geom.initialize(deltax, deltay, thisSite.coord, old_pos, new_pos, AOI_size);
00407     heap.PQinitialize(sqrt_nsites, ymin, deltay);
00408     bottomsite = itSortedSites->second;
00409     ++itSortedSites;
00410     edgelist.initialize(sqrt_nsites, xmin, deltax, bottomsite);
00411 
00412     newsite = itSortedSites->second;
00413     ++itSortedSites;
00414     while(true) {
00415         if(!heap.PQempty()) newintstar = heap.PQ_min();
00416 
00417         if(newsite != NULL && (heap.PQempty() ||
00418            newsite->coord.y < newintstar.y ||
00419            (newsite->coord.y == newintstar.y && newsite->coord.x < newintstar.x))) {
00420             lbnd = edgelist.ELleftbnd(&(newsite->coord));
00421             rbnd = edgelist.ELright(lbnd);
00422             bot = edgelist.rightreg(lbnd);
00423             e = geom.bisect(bot, newsite);
00424             bisector = edgelist.HEcreate(e, le);
00425             edgelist.ELinsert(lbnd, bisector);
00426             if ((p = geom.intersect(lbnd, bisector)) != NULL) {
00427                 heap.PQdelete(lbnd);
00428                 heap.PQinsert(lbnd, p, geom.dist(p, newsite));
00429             }
00430             lbnd = bisector;
00431             bisector = edgelist.HEcreate(e, re);
00432             edgelist.ELinsert(lbnd, bisector);
00433             if ((p = geom.intersect(bisector, rbnd)) != NULL) heap.PQinsert(bisector, p, geom.dist(p, newsite));
00434             if(itSortedSites != sortedSites.end()) {
00435                 newsite = itSortedSites->second;
00436                 ++itSortedSites;
00437             }
00438             else newsite = NULL;
00439         }
00440         else if (!heap.PQempty()) {
00441             lbnd = heap.PQextractmin();
00442             llbnd = edgelist.ELleft(lbnd);
00443             rbnd = edgelist.ELright(lbnd);
00444             rrbnd = edgelist.ELright(rbnd);
00445             bot = edgelist.leftreg(lbnd);
00446             top = edgelist.rightreg(rbnd);
00447             v = lbnd->vertex;
00448             geom.endpoint(lbnd->ELedge, lbnd->ELpm, v);
00449             geom.endpoint(rbnd->ELedge, rbnd->ELpm, v);
00450             edgelist.ELdelete(lbnd);
00451             heap.PQdelete(rbnd);
00452             edgelist.ELdelete(rbnd);
00453             pm = le;
00454             if (bot->coord.y > top->coord.y) {
00455                 temp = bot;
00456                 bot = top;
00457                 top = temp;
00458                 pm = re;
00459             }
00460             e = geom.bisect(bot, top);
00461             bisector = edgelist.HEcreate(e, pm);
00462             edgelist.ELinsert(llbnd, bisector);
00463             geom.endpoint(e, re-pm, v);
00464             if((p = geom.intersect(llbnd, bisector)) != NULL) {
00465                 heap.PQdelete(llbnd);
00466                 heap.PQinsert(llbnd, p, geom.dist(p, bot));
00467             }
00468             if ((p = geom.intersect(bisector, rrbnd)) != NULL) heap.PQinsert(bisector, p, geom.dist(p, bot));
00469         }
00470         else break;
00471     }
00472 
00473     // process the generated edgelist
00474     for(lbnd = edgelist.ELright(edgelist.ELleftend); lbnd != edgelist.ELrightend; lbnd = edgelist.ELright(lbnd)) {
00475         e = lbnd -> ELedge;
00476         geom.processEdge(e);
00477     }
00478     // process sites in order to determine our neighbors
00479     for(SiteMap::iterator itTemp = Sites.begin(); itTemp != Sites.end(); ++itTemp) {
00480         if(itTemp->second->innerEdge[0]) {
00481             if(itTemp->second->outerEdge) {
00482                 itTemp->second->type |= BOUNDARY;
00483                 // Debug output
00484                 if(debugOutput)
00485                     EV << "[NeighborsList::buildVoronoi()]\n"
00486                        << "    Site at [" << itTemp->second->coord.x << ", "
00487                        << itTemp->second->coord.y << "] is a boundary neighbor."
00488                        << endl;
00489             }
00490             else {
00491                 itTemp->second->type |= NEIGHBOR;
00492                 // Debug output
00493                 if(debugOutput)
00494                     EV << "[NeighborsList::buildVoronoi()]\n"
00495                        << "    Site at [" << itTemp->second->coord.x << ", "
00496                        << itTemp->second->coord.y << "] is a neighbor."
00497                        << endl;
00498             }
00499         }
00500         if(!itTemp->second->innerEdge[1] && itTemp->second->innerEdge[2]) {
00501             itTemp->second->type |= NEW;
00502             // Debug output
00503             if(debugOutput)
00504                 EV << "[NeighborsList::buildVoronoi()]\n"
00505                    << "    Site at [" << itTemp->second->coord.x << ", "
00506                    << itTemp->second->coord.y << "] is a new neighbor for site at " << new_pos.x << ":" << new_pos.y << "."
00507                    << endl;
00508         }
00509         // reset inner- and outeredge indicator
00510         itTemp->second->innerEdge[0] = false;
00511         itTemp->second->innerEdge[1] = false;
00512         itTemp->second->innerEdge[2] = false;
00513         itTemp->second->outerEdge = false;
00514     }
00515     // clean up
00516     edgelist.reset();
00517     heap.PQreset();
00518     geom.reset();
00519 }
00520 
00521 void Vast::buildVoronoi()
00522 {
00523     buildVoronoi(thisSite.coord, thisSite.coord);
00524 }
00525 
00526 void Vast::removeNeighbors()
00527 {
00528     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end();) {
00529         // if current site is no neighbor remove it else go on to next site
00530         if(itSites->second->type == UNDEF) {
00531             // Debug output
00532             if(debugOutput)  EV << "[NeighborsList::removeNeighbors()]\n"
00533                                 << "    Site at [" << itSites->second->coord.x << ", " << itSites->second->coord.y
00534                                 << "] has been removed from list."
00535                                 << endl;
00536             Positions.erase(itSites->second->coord);
00537             delete itSites->second;
00538             Sites.erase(itSites++);
00539         }
00540         else ++itSites;
00541     }
00542 }
00543 
00544 void Vast::handleNodeLeaveNotification()
00545 {
00546     if(state == READY) {
00547         // debug output
00548         if(debugOutput) {
00549             EV << "[Vast::receiveChangeNotification() @ " << thisSite.addr.getAddress()
00550                << " (" << thisSite.addr.getKey().toString(16) << ")]\n"
00551                << "    Node " << thisSite.addr.getAddress() << " is leaving the overlay."
00552                << endl;
00553         }
00554 
00555         CompReadyMessage* readyMsg = new CompReadyMessage("OVERLAY_FINISHED");
00556         readyMsg->setReady(false);
00557         readyMsg->setComp(getThisCompType());
00558         sendToApp(readyMsg);
00559     }
00560 }
00561 
00562 void Vast::handleNodeGracefulLeaveNotification()
00563 {
00564      if(state == READY) {
00565         // generate node leave messages
00566         VastListMessage *vastListMsg = new VastListMessage("NODE_LEAVE");
00567         vastListMsg->setCommand(NODE_LEAVE);
00568         // fill neighbors list
00569         vastListMsg->setNeighborNodeArraySize(Sites.size());
00570         vastListMsg->setNeighborPosArraySize(Sites.size());
00571         int i = 0;
00572         for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00573             if(itSites->second->type & ENCLOSING) {
00574                 vastListMsg->setNeighborNode(i, itSites->second->addr);
00575                 vastListMsg->setNeighborPos(i, itSites->second->coord);
00576                 ++i;
00577             }
00578         }
00579         vastListMsg->setNeighborNodeArraySize(i);
00580         vastListMsg->setNeighborPosArraySize(i);
00581 
00582         vastListMsg->setBitLength(VASTLIST_L(vastListMsg));
00583         if(vastListMsg->getNeighborNodeArraySize() > 0) {
00584             for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00585                 VastListMessage *vastCopyMsg = new VastListMessage(*vastListMsg);
00586                sendMessage(vastCopyMsg, itSites->second->addr);
00587             }
00588         }
00589         delete vastListMsg;
00590         changeState(INIT);
00591     }
00592 }
00593 
00594 void Vast::processJoinTimer()
00595 {
00596     GameAPIMessage *sgcMsg = new GameAPIMessage("MOVEMENT_REQUEST");
00597     sgcMsg->setCommand(MOVEMENT_REQUEST);
00598     sendToApp(sgcMsg);
00599 }
00600 
00601 void Vast::processPingTimer()
00602 {
00603     bool abnormalLeave = false;
00604     bool boundaryLeave = false;
00605     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00606         if(itSites->second->tstamp < 0.0) { // node is dropped cause no pong has been received see below
00607             abnormalLeave = true;
00608             if(!(itSites->second->type & NEIGHBOR)) boundaryLeave = true;
00609             itSites->second->type = UNDEF;
00610         }
00611         else if(itSites->second->tstamp < simTime() - pingTimeout) { // node showed no activity for some time request pong and mark it to be dropped next time
00612             VastMessage *vastMsg = new VastMessage("PING");
00613             vastMsg->setCommand(PING);
00614             vastMsg->setBitLength(VAST_L(vastMsg));
00615             sendMessage(vastMsg, itSites->second->addr);
00616             itSites->second->tstamp = -1.0;
00617         }
00618     }
00619     if(abnormalLeave) {
00620         synchronizeApp();
00621         removeNeighbors();
00622         if(boundaryLeave) {
00623             for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00624                 if(itSites->second->type & BOUNDARY) {
00625                     VastMessage *vastMsg = new VastMessage("ENCLOSING_NEIGHBORS_REQUEST");
00626                     vastMsg->setCommand(ENCLOSING_NEIGHBORS_REQUEST);
00627                     vastMsg->setBitLength(VAST_L(vastMsg));
00628                     sendMessage(vastMsg, itSites->second->addr);
00629                 }
00630             }
00631         }
00632         buildVoronoi();
00633         //removeNeighbors(); should be superfluous
00634     }
00635 }
00636 
00637 void Vast::processSecTimer()
00638 {
00639     RECORD_STATS(
00640         if(bytesPerSecond > maxBytesPerSecondSent) {
00641             maxBytesPerSecondSent = bytesPerSecond;
00642         }
00643         averageBytesPerSecondSent += bytesPerSecond;
00644         ++secTimerCount;
00645     );
00646     bytesPerSecond = 0;
00647 }
00648 
00649 void Vast::processCheckCriticalTimer()
00650 {
00651     double NeighborLevel;
00652     int NeighborSum = 0;
00653     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00654         if(itSites->second->neighborCount > 0) {
00655             NeighborSum += itSites->second->neighborCount;
00656         }
00657     }
00658     NeighborLevel = (double)(Sites.size() * Sites.size()) / (double)NeighborSum;
00659 
00660     if(NeighborLevel < criticalThreshold) {
00661         VastListMessage *vastListMsg = new VastListMessage("BACKUP_NEIGHBORS");
00662         vastListMsg->setCommand(BACKUP_NEIGHBORS);
00663         // fill neighbors list
00664         vastListMsg->setNeighborNodeArraySize(Sites.size());
00665         vastListMsg->setNeighborPosArraySize(Sites.size());
00666         int i = 0;
00667         for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00668             vastListMsg->setNeighborNode(i, itSites->second->addr);
00669             vastListMsg->setNeighborPos(i, itSites->second->coord);
00670             ++i;
00671         }
00672         vastListMsg->setBitLength(VASTLIST_L(vastListMsg));
00673         for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00674             VastListMessage *vastCopyMsg = new VastListMessage(*vastListMsg);
00675             sendMessage(vastCopyMsg, itSites->second->addr);
00676         }
00677         delete vastListMsg;
00678     }
00679 }
00680 
00681 void Vast::processDiscoveryTimer()
00682 {
00683     for(StockList::iterator itStock = Stock.begin(); itStock != Stock.end(); ++itStock) {
00684         VastMoveMessage *vastMoveMsg = new VastMoveMessage("NODE_MOVE");
00685         vastMoveMsg->setCommand(NODE_MOVE);
00686         vastMoveMsg->setNewPos(thisSite.coord);
00687         vastMoveMsg->setRequest_list(true);
00688         vastMoveMsg->setBitLength(VASTMOVE_L(vastMoveMsg));
00689         sendMessage(vastMoveMsg, *itStock);
00690     }
00691 }
00692 
00693 void Vast::handleJoin(GameAPIPositionMessage *sgcMsg)
00694 {
00695     TransportAddress joinNode = bootstrapList->getBootstrapNode();
00696     thisSite.coord = sgcMsg->getPosition();
00697     // check if this is the only node in the overlay
00698     if(joinNode.isUnspecified()) {
00699         changeState(READY);
00700     }
00701     else {
00702         VastMessage *vastMsg = new VastMessage("JOIN_REQUEST");
00703         vastMsg->setCommand(JOIN_REQUEST);
00704         vastMsg->setBitLength(VAST_L(vastMsg));
00705         sendMessage(vastMsg, joinNode);
00706     }
00707 }
00708 
00709 void Vast::handleMove(GameAPIPositionMessage* sgcMsg)
00710 {
00711     Vector2D pos = sgcMsg->getPosition();
00712     // test if new position is legal
00713     if(Positions.find(pos) != Positions.end()) {
00714         GameAPIMessage *gameMsg = new GameAPIMessage("MOVEMENT_REQUEST");
00715         gameMsg->setCommand(MOVEMENT_REQUEST);
00716         sendToApp(gameMsg);
00717         return;
00718     }
00719     // send position update to neighbors
00720     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00721         VastMoveMessage *vastMoveMsg = new VastMoveMessage("NODE_MOVE");
00722         vastMoveMsg->setCommand(NODE_MOVE);
00723         vastMoveMsg->setNewPos(pos);
00724         vastMoveMsg->setIs_boundary(itSites->second->type & BOUNDARY);
00725         vastMoveMsg->setBitLength(VASTMOVE_L(vastMoveMsg));
00726         sendMessage(vastMoveMsg, itSites->second->addr);
00727     }
00728     // set new position
00729     thisSite.coord = pos;
00730     // update voronoi
00731     buildVoronoi();
00732     synchronizeApp();
00733     removeNeighbors();
00734 }
00735 
00736 void Vast::handleEvent( GameAPIMessage* msg )
00737 {
00738     // send event to neighbors
00739     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00740         VastEventMessage *vastMsg = new VastEventMessage("EVENT");
00741         vastMsg->setCommand(VAST_EVENT);
00742         vastMsg->encapsulate((cPacket*)msg->dup());
00743         // FIXME: Message length!
00744         sendMessage(vastMsg, itSites->second->addr);
00745     }
00746 }
00747 
00748 void Vast::handleJoinRequest(VastMessage *vastMsg)
00749 {
00750     Site *forwardSite = NULL;
00751     // start with this node
00752     double min_dist = thisSite.coord.distanceSqr(vastMsg->getPos());
00753     forwardSite = &thisSite;
00754     // iterate through all neighbors
00755     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00756         // dont forward to nodes which are still joining
00757         if(itSites->second->coord.distanceSqr(vastMsg->getPos()) < min_dist && itSites->second->neighborCount >= 0) {
00758             min_dist = itSites->second->coord.distanceSqr(vastMsg->getPos());
00759             forwardSite = itSites->second;
00760         }
00761     }
00762     // do nothing and let node retry with new position if current position is illegal
00763     if(min_dist == 0.0) {
00764         delete vastMsg;
00765     }
00766     else {
00767         // send an acknowledge or forward request if any of our neighbors is closer to joining node
00768         if(forwardSite->type & THIS) {
00769             VastListMessage *vastListMsg = new VastListMessage("JOIN_ACKNOWLEDGE");
00770             vastListMsg->setCommand(JOIN_ACKNOWLEDGE);
00771             // fill neighbors list
00772             vastListMsg->setNeighborNodeArraySize(Sites.size());
00773             vastListMsg->setNeighborPosArraySize(Sites.size());
00774             int i = 0;
00775             for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00776                 vastListMsg->setNeighborNode(i, itSites->second->addr);
00777                 vastListMsg->setNeighborPos(i, itSites->second->coord);
00778                 ++i;
00779             }
00780 
00781             vastListMsg->setBitLength(VASTLIST_L(vastListMsg));
00782             sendMessage(vastListMsg, vastMsg->getSourceNode());
00783 
00784             // add node to list to propagte its position early
00785             // nieghborCount is set to -1 to indicate node is still joining
00786             addNode(vastMsg->getPos(), vastMsg->getSourceNode(), -1);
00787             // update voronoi with new neighbors
00788             buildVoronoi();
00789             synchronizeApp();
00790             removeNeighbors();
00791             delete vastMsg;
00792         }
00793         else {
00794             sendMessage(vastMsg, forwardSite->addr);
00795         }
00796     }
00797 }
00798 
00799 void Vast::handleJoinAcknowledge(VastListMessage *vastListMsg)
00800 {
00801     // add acceptor node
00802     changeState(READY);
00803     addNode(vastListMsg->getPos(), vastListMsg->getSourceNode(), vastListMsg->getNeighborCount());
00804     // add new neighbors
00805     for(unsigned int i=0; i<vastListMsg->getNeighborNodeArraySize(); i++) {
00806         addNode(vastListMsg->getNeighborPos(i), vastListMsg->getNeighborNode(i));
00807     }
00808     // update voronoi with new neighbors
00809     buildVoronoi();
00810     synchronizeApp();
00811     removeNeighbors();
00812     // contact new neighbors
00813     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00814         VastMoveMessage *vastMoveMsg = new VastMoveMessage("NODE_MOVE");
00815         vastMoveMsg->setCommand(NODE_MOVE);
00816         vastMoveMsg->setNewPos(thisSite.coord);
00817         vastMoveMsg->setIs_boundary(itSites->second->type & BOUNDARY);
00818         vastMoveMsg->setRequest_list(true);
00819         vastMoveMsg->setBitLength(VASTMOVE_L(vastMoveMsg));
00820         sendMessage(vastMoveMsg, itSites->second->addr);
00821     }
00822 }
00823 
00824 void Vast::handleNodeMove(VastMoveMessage *vastMoveMsg)
00825 {
00826     RECORD_STATS(
00827             globalStatistics->addStdDev(
00828                 "Vast: MoveDelay",
00829                 SIMTIME_DBL(simTime()) - SIMTIME_DBL(vastMoveMsg->getCreationTime())
00830                 );
00831             );
00832 
00833     Vector2D old_p, new_p;
00834     old_p = vastMoveMsg->getPos();
00835     new_p = vastMoveMsg->getNewPos();
00836     addNode(new_p, vastMoveMsg->getSourceNode(), vastMoveMsg->getNeighborCount());
00837     // update voronoi with new neighbor detection or without
00838     if(vastMoveMsg->getIs_boundary() || vastMoveMsg->getRequest_list()) {
00839         if(!vastMoveMsg->getRequest_list()) {
00840             buildVoronoi(old_p, new_p);
00841             synchronizeApp(vastMoveMsg);
00842             removeNeighbors();
00843         }
00844         // send new neighbors
00845         VastListMessage *vastListMsg = new VastListMessage("NEW_NEIGHBORS");
00846         vastListMsg->setCommand(NEW_NEIGHBORS);
00847 
00848         vastListMsg->setNeighborNodeArraySize(Sites.size());
00849         vastListMsg->setNeighborPosArraySize(Sites.size());
00850 
00851         int i = 0;
00852         for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00853             if(itSites->second->type & NEW || vastMoveMsg->getRequest_list()) {
00854                 vastListMsg->setNeighborNode(i, itSites->second->addr);
00855                 vastListMsg->setNeighborPos(i, itSites->second->coord);
00856                 ++i;
00857             }
00858         }
00859         vastListMsg->setNeighborNodeArraySize(i);
00860         vastListMsg->setNeighborPosArraySize(i);
00861         vastListMsg->setRequestEnclosingNeighbors(true);
00862 
00863         vastListMsg->setBitLength(VASTLIST_L(vastListMsg));
00864         if(vastListMsg->getNeighborNodeArraySize() > 0) {
00865             sendMessage(vastListMsg, vastMoveMsg->getSourceNode());
00866         }
00867         else {
00868             delete vastListMsg;
00869         }
00870     }
00871     else {
00872         buildVoronoi();
00873         synchronizeApp(vastMoveMsg);
00874         removeNeighbors();
00875     }
00876 }
00877 
00878 void Vast::handleNewNeighbors(VastListMessage *vastListMsg)
00879 {
00880     // add new neighbors
00881     for(unsigned int i=0; i<vastListMsg->getNeighborNodeArraySize(); i++) {
00882         addNode(vastListMsg->getNeighborPos(i), vastListMsg->getNeighborNode(i));
00883 
00884         if(vastListMsg->getRequestEnclosingNeighbors()) {
00885             VastMessage *vastMsg = new VastMessage("ENCLOSING_NEIGHBORS_REQUEST");
00886             vastMsg->setCommand(ENCLOSING_NEIGHBORS_REQUEST);
00887             vastMsg->setBitLength(VAST_L(vastMsg));
00888             sendMessage(vastMsg, vastListMsg->getNeighborNode(i));
00889         }
00890     }
00891     // update voronoi with new neighbors
00892     buildVoronoi();
00893     synchronizeApp();
00894     removeNeighbors();
00895 }
00896 
00897 void Vast::handleNodeLeave(VastListMessage *vastListMsg)
00898 {
00899     removeNode(vastListMsg->getSourceNode());
00900     // add possible new neighbors
00901     for(unsigned int i=0; i<vastListMsg->getNeighborNodeArraySize(); i++) {
00902         addNode(vastListMsg->getNeighborPos(i), vastListMsg->getNeighborNode(i));
00903     }
00904     // update voronoi with new neighbors
00905     buildVoronoi();
00906     synchronizeApp();
00907     removeNeighbors();
00908 }
00909 
00910 void Vast::handleEnclosingNeighborsRequest(VastMessage *vastMsg)
00911 {
00912     // send new neighbors
00913     VastListMessage *vastListMsg = new VastListMessage("NEW_NEIGHBORS");
00914     vastListMsg->setCommand(NEW_NEIGHBORS);
00915 
00916     vastListMsg->setNeighborNodeArraySize(Sites.size());
00917     vastListMsg->setNeighborPosArraySize(Sites.size());
00918 
00919     int i = 0;
00920     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00921         if((itSites->second->type & ENCLOSING) && itSites->second->addr != vastMsg->getSourceNode()) {
00922             vastListMsg->setNeighborNode(i, itSites->second->addr);
00923             vastListMsg->setNeighborPos(i, itSites->second->coord);
00924             ++i;
00925         }
00926     }
00927     vastListMsg->setNeighborNodeArraySize(i);
00928     vastListMsg->setNeighborPosArraySize(i);
00929 
00930     vastListMsg->setBitLength(VASTLIST_L(vastListMsg));
00931     if(vastListMsg->getNeighborNodeArraySize() > 0) {
00932         sendMessage(vastListMsg, vastMsg->getSourceNode());
00933     }
00934     else {
00935         delete vastListMsg;
00936     }
00937 }
00938 
00939 void Vast::handleBackupNeighbors(VastListMessage *vastListMsg)
00940 {
00941     // add new neighbors to stock list
00942     for(unsigned int i=0; i<vastListMsg->getNeighborNodeArraySize(); i++) {
00943         if(Sites.find(vastListMsg->getNeighborNode(i)) == Sites.end()) {
00944             addNodeToStock(vastListMsg->getNeighborNode(i));
00945         }
00946     }
00947 }
00948 
00949 void Vast::handlePing(VastMessage *vastMsg)
00950 {
00951     VastMessage *vastPongMsg = new VastMessage("PONG");
00952     vastPongMsg->setCommand(PONG);
00953     vastPongMsg->setBitLength(VAST_L(vastPongMsg));
00954     sendMessage(vastPongMsg, vastMsg->getSourceNode());
00955 }
00956 
00957 void Vast::handlePong(VastMessage *vastMsg)
00958 {
00959     // replace entry cause it was probably outdated
00960     addNode(vastMsg->getPos(), vastMsg->getSourceNode(), vastMsg->getNeighborCount());
00961     // update voronoi
00962     buildVoronoi();
00963     synchronizeApp();
00964     removeNeighbors();
00965 }
00966 
00967 void Vast::handleDiscardNode(VastDiscardMessage *vastMsg)
00968 {
00969     // discard outdated entry
00970     removeNode(vastMsg->getDiscardNode());
00971     // update voronoi
00972     buildVoronoi();
00973     synchronizeApp();
00974     removeNeighbors();
00975 }
00976 
00977 void Vast::sendDiscardNode(VastMessage *vastMsg)
00978 {
00979     NodeHandle discardNode;
00980     discardNode.setAddress(thisSite.addr.getAddress());
00981     discardNode.setKey(vastMsg->getDestKey());
00982     // send message
00983     VastDiscardMessage *vastDiscardMsg = new VastDiscardMessage("DISCARD_NODE");
00984     vastDiscardMsg->setCommand(DISCARD_NODE);
00985     vastDiscardMsg->setDiscardNode(discardNode);
00986     // debug output
00987     if(debugOutput) EV << "[Vast::sendDiscardNode() @ " << thisSite.addr.getAddress()
00988                        << " (" << thisSite.addr.getKey().toString(16) << ")]\n"
00989                        << "    Node " << thisSite.addr.getAddress() << " is leaving the overlay."
00990                        << endl;
00991     vastDiscardMsg->setBitLength(VASTDISCARD_L(vastDiscardMsg));
00992     sendMessage(vastDiscardMsg, vastMsg->getSourceNode());
00993 }
00994 
00995 void Vast::synchronizeApp(VastMoveMessage *vastMoveMsg)
00996 {
00997     GameAPIListMessage *sgcMsg = new GameAPIListMessage("NEIGHBOR_UPDATE");
00998     sgcMsg->setCommand(NEIGHBOR_UPDATE);
00999 
01000     sgcMsg->setRemoveNeighborArraySize(Sites.size());
01001     sgcMsg->setAddNeighborArraySize(Sites.size() + 1);
01002     sgcMsg->setNeighborPositionArraySize(Sites.size() + 1);
01003 
01004     int remSize, addSize;
01005     remSize = addSize = 0;
01006     for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
01007         if(itSites->second->type == UNDEF) {
01008             sgcMsg->setRemoveNeighbor(remSize, itSites->second->addr);
01009             ++remSize;
01010         }
01011         else if(!itSites->second->isAdded) {
01012             sgcMsg->setAddNeighbor(addSize, itSites->second->addr);
01013             sgcMsg->setNeighborPosition(addSize, itSites->second->coord);
01014             itSites->second->isAdded = true;
01015             ++addSize;
01016         }
01017     }
01018 
01019     if(vastMoveMsg &&
01020        Sites.find(vastMoveMsg->getSourceNode()) != Sites.end() &&
01021        Sites.find(vastMoveMsg->getSourceNode())->second->isAdded) {
01022         sgcMsg->setAddNeighbor(addSize, vastMoveMsg->getSourceNode());
01023         sgcMsg->setNeighborPosition(addSize, vastMoveMsg->getNewPos());
01024         ++addSize;
01025     }
01026 
01027     sgcMsg->setRemoveNeighborArraySize(remSize);
01028     sgcMsg->setAddNeighborArraySize(addSize);
01029     sgcMsg->setNeighborPositionArraySize(addSize);
01030 
01031     if(sgcMsg->getAddNeighborArraySize() || sgcMsg->getRemoveNeighborArraySize()) {
01032         sendToApp(sgcMsg);
01033     }
01034     else {
01035         delete sgcMsg;
01036     }
01037 }
01038 
01039 void Vast::sendToApp(cMessage *msg)
01040 {
01041     // debug output
01042     if(debugOutput) EV << "[Vast::sendToApp() @ " << thisSite.addr.getAddress()
01043                        << " (" << thisSite.addr.getKey().toString(16) << ")]\n"
01044                        << "    Node " << thisSite.addr.getAddress() << " sending " << msg->getName() << " to application."
01045                        << endl;
01046     send(msg, "appOut");
01047 }
01048 
01049 void Vast::sendMessage(VastMessage *vastMsg, NodeHandle destAddr)
01050 {
01051     // collect statistics
01052     RECORD_STATS(
01053         switch(vastMsg->getCommand()) {
01054             case JOIN_REQUEST: {
01055                 joinRequestBytesSent += vastMsg->getByteLength();
01056             } break;
01057             case JOIN_ACKNOWLEDGE: {
01058                 joinAcknowledgeBytesSent += vastMsg->getByteLength();
01059             } break;
01060             case NODE_MOVE: {
01061                 nodeMoveBytesSent += vastMsg->getByteLength();
01062             } break;
01063             case NEW_NEIGHBORS: {
01064                 newNeighborsBytesSent += vastMsg->getByteLength();
01065             } break;
01066             case NODE_LEAVE: {
01067                 nodeLeaveBytesSent += vastMsg->getByteLength();
01068             } break;
01069             case ENCLOSING_NEIGHBORS_REQUEST: {
01070                 enclosingNeighborsRequestBytesSent += vastMsg->getByteLength();
01071             } break;
01072             case PING: {
01073                 pingBytesSent += vastMsg->getByteLength();
01074             } break;
01075             case PONG: {
01076                 pongBytesSent += vastMsg->getByteLength();
01077             } break;
01078             case DISCARD_NODE: {
01079                 discardNodeBytesSent += vastMsg->getByteLength();
01080             } break;
01081         }
01082         bytesPerSecond += vastMsg->getByteLength();
01083     );
01084 
01085     // debug output
01086     if(debugOutput) EV << "[Vast::sendMessage() @ " << thisSite.addr.getAddress()
01087                        << " (" << thisSite.addr.getKey().toString(16) << ")]\n"
01088                        << "    Node " << thisSite.addr.getAddress() << " sending " << vastMsg->getName() << " to " << destAddr.getAddress() << "."
01089                        << endl;
01090     // set vastbase message stuff
01091     vastMsg->setDestKey(destAddr.getKey());
01092     // fill in sender information only if we are not forwarding a message from another node
01093     // e.g. a joining node
01094     if(vastMsg->getSourceNode().isUnspecified()) {
01095         vastMsg->setSourceNode(thisSite.addr);
01096         vastMsg->setPos(thisSite.coord);
01097         vastMsg->setNeighborCount(Sites.size());
01098     }
01099 
01100     sendMessageToUDP(destAddr, vastMsg);
01101 }
01102 
01103 void Vast::setBootstrapedIcon()
01104 {
01105     if(ev.isGUI()) {
01106         if(state == READY) {
01107             getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 1, "green");
01108             getDisplayString().setTagArg("i", 1, "green");
01109         }
01110         else if(state == JOINING) {
01111             getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 1, "yellow");
01112             getDisplayString().setTagArg("i", 1, "yellow");
01113         }
01114         else {
01115             getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 1, "red");
01116             getDisplayString().setTagArg("i", 1, "red");
01117         }
01118     }
01119 }
01120 
01121 void Vast::finishOverlay()
01122 {
01123     globalNodeList->removePeer(thisSite.addr);
01124 
01125 //    We use our own time count to avoid rounding errors
01126 //    simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
01127 //    if(time == 0) return;
01128     if(secTimerCount == 0) return;
01129 
01130     // collect statistics
01131     globalStatistics->addStdDev("Vast: JOIN_REQUEST bytes sent/s", joinRequestBytesSent/(double) secTimerCount);
01132     globalStatistics->addStdDev("Vast: JOIN_ACKNOWLEDGE bytes sent/s", joinAcknowledgeBytesSent/(double) secTimerCount);
01133     globalStatistics->addStdDev("Vast: NODE_MOVE bytes sent/s", nodeMoveBytesSent/(double) secTimerCount);
01134     globalStatistics->addStdDev("Vast: NEW_NEIGHBORS bytes sent/s", newNeighborsBytesSent/(double) secTimerCount);
01135     globalStatistics->addStdDev("Vast: NODE_LEAVE bytes sent/s", nodeLeaveBytesSent/(double) secTimerCount);
01136     globalStatistics->addStdDev("Vast: ENCLOSING_NEIGHBORS_REQUEST bytes sent/s", enclosingNeighborsRequestBytesSent/(double) secTimerCount);
01137     globalStatistics->addStdDev("Vast: PING bytes sent/s", pingBytesSent/(double) secTimerCount);
01138     globalStatistics->addStdDev("Vast: PONG bytes sent/s", pongBytesSent/(double) secTimerCount);
01139     globalStatistics->addStdDev("Vast: DISCARD_NODE bytes sent/s", discardNodeBytesSent/(double) secTimerCount);
01140 
01141     globalStatistics->addStdDev("Vast: max bytes/second sent", maxBytesPerSecondSent);
01142     globalStatistics->addStdDev("Vast: average bytes/second sent", averageBytesPerSecondSent / (double) secTimerCount);
01143 }
01144 
01145 double Vast::getAOI()
01146 {
01147     Enter_Method_Silent();
01148     return AOI_size;
01149 }
01150 
01151 Vector2D Vast::getPosition()
01152 {
01153     Enter_Method_Silent();
01154     return thisSite.coord;
01155 }
01156 
01157 NodeHandle Vast::getHandle()
01158 {
01159     Enter_Method_Silent();
01160     return thisSite.addr;
01161 }
01162 
01163 double Vast::getAreaDimension()
01164 {
01165     Enter_Method_Silent();
01166     return areaDimension;
01167 }
01168 
01169 Vast::~Vast()
01170 {
01171     if(Sites.size()) {
01172         for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
01173             delete itSites->second;
01174         }
01175         Sites.clear();
01176         Positions.clear();
01177     }
01178     // destroy self timer messages
01179     cancelAndDelete(join_timer);
01180     cancelAndDelete(ping_timer);
01181     cancelAndDelete(sec_timer);
01182     cancelAndDelete(discovery_timer);
01183     cancelAndDelete(checkcritical_timer);
01184 }

Generated on Tue Sep 8 17:26:54 2009 for OverSim by  doxygen 1.5.8