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)
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 sortedSites.insert(std::make_pair(itTemp->second->coord, itTemp->second));
00387 sqrt_nsites++;
00388 }
00389
00390
00391 deltax = xmax - xmin;
00392 deltay = ymax - ymin;
00393 sqrt_nsites = (int)sqrt((double)(sqrt_nsites+4));
00394
00395
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
00474 for(lbnd = edgelist.ELright(edgelist.ELleftend); lbnd != edgelist.ELrightend; lbnd = edgelist.ELright(lbnd)) {
00475 e = lbnd -> ELedge;
00476 geom.processEdge(e);
00477 }
00478
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
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
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
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
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
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
00530 if(itSites->second->type == UNDEF) {
00531
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
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
00566 VastListMessage *vastListMsg = new VastListMessage("NODE_LEAVE");
00567 vastListMsg->setCommand(NODE_LEAVE);
00568
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) {
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) {
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
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
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
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
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
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
00729 thisSite.coord = pos;
00730
00731 buildVoronoi();
00732 synchronizeApp();
00733 removeNeighbors();
00734 }
00735
00736 void Vast::handleEvent( GameAPIMessage* msg )
00737 {
00738
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
00744 sendMessage(vastMsg, itSites->second->addr);
00745 }
00746 }
00747
00748 void Vast::handleJoinRequest(VastMessage *vastMsg)
00749 {
00750 Site *forwardSite = NULL;
00751
00752 double min_dist = thisSite.coord.distanceSqr(vastMsg->getPos());
00753 forwardSite = &thisSite;
00754
00755 for(SiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00756
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
00763 if(min_dist == 0.0) {
00764 delete vastMsg;
00765 }
00766 else {
00767
00768 if(forwardSite->type & THIS) {
00769 VastListMessage *vastListMsg = new VastListMessage("JOIN_ACKNOWLEDGE");
00770 vastListMsg->setCommand(JOIN_ACKNOWLEDGE);
00771
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
00785
00786 addNode(vastMsg->getPos(), vastMsg->getSourceNode(), -1);
00787
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
00802 changeState(READY);
00803 addNode(vastListMsg->getPos(), vastListMsg->getSourceNode(), vastListMsg->getNeighborCount());
00804
00805 for(unsigned int i=0; i<vastListMsg->getNeighborNodeArraySize(); i++) {
00806 addNode(vastListMsg->getNeighborPos(i), vastListMsg->getNeighborNode(i));
00807 }
00808
00809 buildVoronoi();
00810 synchronizeApp();
00811 removeNeighbors();
00812
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
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
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
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
00892 buildVoronoi();
00893 synchronizeApp();
00894 removeNeighbors();
00895 }
00896
00897 void Vast::handleNodeLeave(VastListMessage *vastListMsg)
00898 {
00899 removeNode(vastListMsg->getSourceNode());
00900
00901 for(unsigned int i=0; i<vastListMsg->getNeighborNodeArraySize(); i++) {
00902 addNode(vastListMsg->getNeighborPos(i), vastListMsg->getNeighborNode(i));
00903 }
00904
00905 buildVoronoi();
00906 synchronizeApp();
00907 removeNeighbors();
00908 }
00909
00910 void Vast::handleEnclosingNeighborsRequest(VastMessage *vastMsg)
00911 {
00912
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
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
00960 addNode(vastMsg->getPos(), vastMsg->getSourceNode(), vastMsg->getNeighborCount());
00961
00962 buildVoronoi();
00963 synchronizeApp();
00964 removeNeighbors();
00965 }
00966
00967 void Vast::handleDiscardNode(VastDiscardMessage *vastMsg)
00968 {
00969
00970 removeNode(vastMsg->getDiscardNode());
00971
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
00983 VastDiscardMessage *vastDiscardMsg = new VastDiscardMessage("DISCARD_NODE");
00984 vastDiscardMsg->setCommand(DISCARD_NODE);
00985 vastDiscardMsg->setDiscardNode(discardNode);
00986
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
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
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
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
01091 vastMsg->setDestKey(destAddr.getKey());
01092
01093
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
01126
01127
01128 if(secTimerCount == 0) return;
01129
01130
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
01179 cancelAndDelete(join_timer);
01180 cancelAndDelete(ping_timer);
01181 cancelAndDelete(sec_timer);
01182 cancelAndDelete(discovery_timer);
01183 cancelAndDelete(checkcritical_timer);
01184 }