00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00037
00038 if(stage != MIN_STAGE_OVERLAY) return;
00039
00040
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
00052 thisNode.setKey(OverlayKey::random());
00053 thisSite.type = THIS;
00054 thisSite.addr = thisNode;
00055
00056 geom.setDebug(debugOutput);
00057
00058
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
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
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
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
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
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
00161 cancelEvent(join_timer);
00162 scheduleAt(simTime() + joinTimeout, msg);
00163
00164 processJoinTimer();
00165 }
00166 else if(msg->isName("ping_timer")) {
00167
00168 cancelEvent(ping_timer);
00169 scheduleAt(simTime() + pingTimeout, msg);
00170
00171 processPingTimer();
00172 }
00173 else if(msg->isName("sec_timer")) {
00174
00175 cancelEvent(sec_timer);
00176 scheduleAt(simTime() + 1, msg);
00177
00178 processSecTimer();
00179 }
00180 else if(msg->isName("checkcritical_timer")) {
00181
00182 cancelEvent(checkcritical_timer);
00183 scheduleAt(simTime() + checkCriticalIntervall, msg);
00184
00185 processCheckCriticalTimer();
00186 }
00187 else if(msg->isName("discovery_timer")) {
00188
00189 cancelEvent(discovery_timer);
00190 scheduleAt(simTime() + discoveryIntervall, msg);
00191
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
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
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
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
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
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
00384 itTemp->second->type = UNDEF;
00385
00386 itTemp->second->enclosingSet.clear();
00387
00388 sortedSites.insert(std::make_pair(itTemp->second->coord, itTemp->second));
00389 sqrt_nsites++;
00390 }
00391
00392
00393 deltax = xmax - xmin;
00394 deltay = ymax - ymin;
00395 sqrt_nsites = (int)sqrt((double)(sqrt_nsites+4));
00396
00397
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
00476 for(lbnd = edgelist.ELright(edgelist.ELleftend); lbnd != edgelist.ELrightend; lbnd = edgelist.ELright(lbnd)) {
00477 e = lbnd -> ELedge;
00478 geom.processEdge(e);
00479 }
00480
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
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
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
00503 if((!itTemp->second->type & NEIGHBOR) && (itTemp->second->type & ENCLOSING)) {
00504 itTemp->second->type |= BOUNDARY;
00505
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
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
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
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
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
00553 if(itSites->second->type == UNDEF) {
00554
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
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
00589 VastListMessage *vastListMsg = new VastListMessage("NODE_LEAVE");
00590 vastListMsg->setCommand(NODE_LEAVE);
00591
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) {
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) {
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
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
00661
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
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
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
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
00748 thisSite.coord = pos;
00749
00750 buildVoronoi();
00751 synchronizeApp();
00752 removeNeighbors();
00753
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
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
00772 sendMessage(vastMsg, itSites->second->addr);
00773 }
00774 }
00775
00776 void Vast::handleJoinRequest(VastMessage *vastMsg)
00777 {
00778 Site *forwardSite = NULL;
00779
00780 double min_dist = thisSite.coord.distanceSqr(vastMsg->getPos());
00781 forwardSite = &thisSite;
00782
00783 for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00784
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
00791 if(min_dist == 0.0) {
00792 delete vastMsg;
00793 }
00794 else {
00795
00796 if(forwardSite->type & THIS) {
00797 VastListMessage *vastListMsg = new VastListMessage("JOIN_ACKNOWLEDGE");
00798 vastListMsg->setCommand(JOIN_ACKNOWLEDGE);
00799
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
00813
00814 addNode(vastMsg->getPos(), vastMsg->getSourceNode(), -1);
00815
00816 buildVoronoi();
00817 synchronizeApp();
00818
00819 delete vastMsg;
00820 }
00821 else {
00822 sendMessage(vastMsg, forwardSite->addr);
00823 }
00824 }
00825 }
00826
00827 void Vast::handleJoinAcknowledge(VastListMessage *vastListMsg)
00828 {
00829
00830 changeState(READY);
00831 addNode(vastListMsg->getPos(), vastListMsg->getSourceNode(), vastListMsg->getNeighborCount());
00832
00833 for(unsigned int i=0; i<vastListMsg->getNeighborNodeArraySize(); i++) {
00834 addNode(vastListMsg->getNeighborPos(i), vastListMsg->getNeighborNode(i));
00835 }
00836
00837 buildVoronoi();
00838 synchronizeApp();
00839
00840
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
00866 if(vastMoveMsg->getIs_boundary() || vastMoveMsg->getRequest_list()) {
00867 buildVoronoi(old_p, new_p, vastMoveMsg->getSourceNode());
00868 synchronizeApp(vastMoveMsg);
00869
00870
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
00899 synchronizeApp(vastMoveMsg);
00900
00901 }
00902 }
00903
00904 void Vast::handleNewNeighbors(VastListMessage *vastListMsg)
00905 {
00906
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
00918
00919
00920
00921 }
00922
00923 void Vast::handleNodeLeave(VastListMessage *vastListMsg)
00924 {
00925 removeNode(vastListMsg->getSourceNode());
00926
00927 for(unsigned int i=0; i<vastListMsg->getNeighborNodeArraySize(); i++) {
00928 addNode(vastListMsg->getNeighborPos(i), vastListMsg->getNeighborNode(i));
00929 }
00930
00931
00932
00933
00934 }
00935
00936 void Vast::handleEnclosingNeighborsRequest(VastMessage *vastMsg)
00937 {
00938
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
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
00986 addNode(vastMsg->getPos(), vastMsg->getSourceNode(), vastMsg->getNeighborCount());
00987
00988
00989
00990
00991 }
00992
00993 void Vast::handleDiscardNode(VastDiscardMessage *vastMsg)
00994 {
00995
00996 removeNode(vastMsg->getDiscardNode());
00997
00998
00999
01000
01001 }
01002
01003 void Vast::sendDiscardNode(VastMessage *vastMsg)
01004 {
01005 NodeHandle discardNode;
01006 discardNode.setAddress(thisSite.addr.getAddress());
01007 discardNode.setKey(vastMsg->getDestKey());
01008
01009 VastDiscardMessage *vastDiscardMsg = new VastDiscardMessage("DISCARD_NODE");
01010 vastDiscardMsg->setCommand(DISCARD_NODE);
01011 vastDiscardMsg->setDiscardNode(discardNode);
01012
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
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
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
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
01117 vastMsg->setDestKey(destAddr.getKey());
01118
01119
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
01152
01153
01154 if(secTimerCount == 0) return;
01155
01156
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
01205 cancelAndDelete(join_timer);
01206 cancelAndDelete(ping_timer);
01207 cancelAndDelete(sec_timer);
01208 cancelAndDelete(discovery_timer);
01209 cancelAndDelete(checkcritical_timer);
01210 }