Quon.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 
00025 #include <Quon.h>
00026 #include <BootstrapList.h>
00027 #include <limits>
00028 
00029 Define_Module(Quon);
00030 
00031 void Quon::initializeOverlay(int stage)
00032 {
00033     // because of IPAddressResolver, we need to wait until interfaces are registered,
00034     // address auto-assignment takes place etc.
00035     if(stage != MIN_STAGE_OVERLAY) {
00036         return;
00037     }
00038 
00039     // fetch parameters
00040     minAOI = (double)par("minAOIWidth") + (double)par("AOIBuffer"); // FIXME: use buffer only where required
00041     maxAOI = (double)par("AOIWidth") + (double)par("AOIBuffer"); // FIXME: use buffer only where required
00042     AOIWidth = maxAOI;
00043     connectionLimit = par("connectionLimit");
00044     areaDimension = par("areaDimension");
00045     joinTimeout = par("joinTimeout");
00046     deleteTimeout = par("deleteTimeout");
00047     aliveTimeout = (double)par("aliveTimeout") / 2.0;
00048     backupIntervall = par("contactBackupIntervall");
00049     numBackups = par("numBackups");
00050     AOIAdaptionIntervall = par("AOIAdaptionIntervall");
00051     linearAdaption = par("AOIAdaptLinear");
00052     adaptionSensitivity = par("AOIAdaptionSensitivity");
00053     gossipSensitivity = par("AOIGossipSensitivity");
00054     useSquareMetric = par("useSquareMetric");
00055 
00056     bindingBackup = new NodeHandle[numBackups][4];
00057 
00058     // determine wether we want dynamic AOI or not
00059     useDynamicAOI = (connectionLimit > 0 && minAOI < maxAOI && AOIAdaptionIntervall > 0.0) ? true : false;
00060 
00061     // set node key and thisSite pointer
00062     thisNode.setKey(OverlayKey::random());
00063     thisSite = new QuonSite();
00064     thisSite->address = thisNode;
00065     thisSite->type = QTHIS;
00066 
00067     // initialize self-messages
00068     join_timer = new cMessage("join_timer");
00069     sec_timer = new cMessage("sec_timer");
00070     alive_timer = new cMessage("alive_timer");
00071     backup_timer = new cMessage("backup_timer");
00072     adaption_timer = new cMessage("adaption_timer");
00073 
00074     // statistics
00075     joinRequestBytesSend = 0.0;
00076     joinAcknowledgeBytesSend = 0.0;
00077     nodeMoveBytesSend = 0.0;
00078     newNeighborsBytesSend = 0.0;
00079     nodeLeaveBytesSend = 0.0;
00080     maxBytesPerSecondSend = 0.0;
00081     averageBytesPerSecondSend = 0.0;
00082     bytesPerSecond = 0.0;
00083     softConnections = 0;
00084     softNeighborCount = 0;
00085     bindingNeighborCount = 0;
00086     directNeighborCount = 0;
00087     secTimerCount = 0;
00088     //rejoinCount = 0;
00089     avgAOI= 0 ;
00090 
00091     // watch some variables
00092     WATCH(thisSite->address);
00093     WATCH(thisSite->position);
00094     WATCH(AOIWidth);
00095     //WATCH_POINTER_MAP(Sites);
00096     //WATCH_POINTER_MAP(deletedSites);
00097     //WATCH_SET(Positions);
00098     WATCH(joinRequestBytesSend);
00099     WATCH(joinAcknowledgeBytesSend);
00100     WATCH(nodeMoveBytesSend);
00101     WATCH(newNeighborsBytesSend);
00102     WATCH(nodeLeaveBytesSend);
00103     WATCH(maxBytesPerSecondSend);
00104     WATCH(bytesPerSecond);
00105     WATCH(softConnections);
00106     WATCH(softNeighborCount);
00107     WATCH(bindingNeighborCount);
00108     WATCH(directNeighborCount);
00109     //WATCH(rejoinCount);
00110 
00111     // set initial state
00112     changeState(QUNINITIALIZED);
00113     changeState(QJOINING);
00114 }
00115 
00116 void Quon::changeState(QState qstate)
00117 {
00118     this->qstate = qstate;
00119     switch(qstate) {
00120         case QUNINITIALIZED:
00121             globalNodeList->removePeer(thisSite->address);
00122             cancelEvent(join_timer);
00123             cancelEvent(sec_timer);
00124             cancelEvent(alive_timer);
00125             cancelEvent(backup_timer);
00126             cancelEvent(adaption_timer);
00127             break;
00128         case QJOINING:
00129             scheduleAt(simTime(), join_timer);
00130             scheduleAt(simTime() + 1.0, sec_timer);
00131             break;
00132         case QREADY:
00133             cancelEvent(join_timer);
00134             globalNodeList->registerPeer(thisSite->address);
00135             // tell the application we are ready unless we are rejoining the overlay
00136             //if(rejoinCount == 0) {
00137             CompReadyMessage* readyMsg = new CompReadyMessage("OVERLAY_READY");
00138             readyMsg->setReady(true);
00139             readyMsg->setComp(getThisCompType());
00140             // TODO/FIXME: use overlay->sendMessageToAllComp(msg, getThisCompType())?
00141             sendToApp(readyMsg);
00142             //}
00143             // set initial AOI size
00144             AOIWidth = maxAOI;
00145             GameAPIResizeAOIMessage* gameMsg = new GameAPIResizeAOIMessage("RESIZE_AOI");
00146             gameMsg->setCommand(RESIZE_AOI);
00147             gameMsg->setAOIsize(AOIWidth);
00148             sendToApp(gameMsg);
00149             if(aliveTimeout > 0.0) {
00150                 scheduleAt(simTime() + aliveTimeout, alive_timer);
00151             }
00152             if(backupIntervall > 0.0) {
00153                 scheduleAt(simTime() + backupIntervall, backup_timer);
00154             }
00155             if(useDynamicAOI) {
00156                 scheduleAt(simTime() + AOIAdaptionIntervall, adaption_timer);
00157             }
00158             break;
00159     }
00160     setBootstrapedIcon();
00161     // debug output
00162     if(debugOutput) {
00163         EV << "[Quon::changeState() @ " << thisNode.getAddress()
00164            << " (" << thisNode.getKey().toString(16) << ")]\n"
00165            << "    Node " << thisSite->address.getAddress() << " entered ";
00166         switch(qstate) {
00167             case QUNINITIALIZED:
00168                 EV << "UNINITIALIZED";
00169                 break;
00170             case QJOINING:
00171                 EV << "JOINING";
00172                 break;
00173             case QREADY:
00174                 EV << "READY";
00175                 break;
00176         }
00177         EV << " state." << endl;
00178     }
00179 }
00180 
00181 void Quon::handleTimerEvent(cMessage* msg)
00182 {
00183     if(msg->isName("join_timer")) {
00184         //reset timer
00185         cancelEvent(join_timer);
00186         if(qstate != QREADY) {
00187             scheduleAt(simTime() + joinTimeout, msg);
00188             // handle event
00189             processJoinTimer();
00190         }
00191     }
00192     else if(msg->isName("sec_timer")) {
00193         //reset timer
00194         cancelEvent(sec_timer);
00195         scheduleAt(simTime() + 1, msg);
00196         // handle event
00197         processSecTimer();
00198     }
00199     else if(msg->isName("delete_timer")) {
00200         // handle event
00201         processDeleteTimer(msg);
00202     }
00203     else if(msg->isName("alive_timer")) {
00204         //reset timer
00205         cancelEvent(alive_timer);
00206         scheduleAt(simTime() + aliveTimeout, msg);
00207         // handle event
00208         processAliveTimer();
00209     }
00210     else if(msg->isName("backup_timer")) {
00211         //reset timer
00212         cancelEvent(backup_timer);
00213         scheduleAt(simTime() + backupIntervall, msg);
00214         // handle event
00215         processBackupTimer();
00216     }
00217     else if(msg->isName("adaption_timer")) {
00218         //reset timer
00219         cancelEvent(adaption_timer);
00220         scheduleAt(simTime() + AOIAdaptionIntervall, msg);
00221         // adjust AOIWidth
00222 #if 0
00223         // Old simple adaption
00224         if((Sites.size() > connectionLimit && AOIWidth > minAOI) || (Sites.size() < connectionLimit && AOIWidth < maxAOI)) {
00225             AOIWidth -= (maxAOI - minAOI) * (Sites.size() - connectionLimit) / 200.0;
00226             if(AOIWidth > maxAOI) {
00227                 AOIWidth = maxAOI;
00228             }
00229             else if(AOIWidth < minAOI) {
00230                 AOIWidth = minAOI;
00231             }
00232             GameAPIResizeAOIMessage* gameMsg = new GameAPIResizeAOIMessage("RESIZE_AOI");
00233             gameMsg->setCommand(RESIZE_AOI);
00234             gameMsg->setAOIsize(AOIWidth);
00235             sendToApp(gameMsg);
00236         }
00237 
00238 #endif
00239         double oldAOI = AOIWidth;
00240         if( linearAdaption ) {
00241             AOIWidth -= (maxAOI - minAOI) * ((double) Sites.size() - (double) connectionLimit) * adaptionSensitivity / (double) connectionLimit;
00242         } else if( Sites.size() > 0 ){
00243             AOIWidth *= (1-adaptionSensitivity) + (double) connectionLimit * adaptionSensitivity / (double) Sites.size();
00244         }
00245         if( gossipSensitivity > 0  && Sites.size() > 0 ) {
00246             double avgNeighborAOI = 0;
00247             for( QuonSiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites ){
00248                 avgNeighborAOI += itSites->second->AOIwidth;
00249             }
00250             avgNeighborAOI /= Sites.size();
00251             AOIWidth = AOIWidth*(1-gossipSensitivity) + avgNeighborAOI*gossipSensitivity;
00252         }
00253         if(AOIWidth > maxAOI) {
00254             AOIWidth = maxAOI;
00255         }
00256         else if(AOIWidth < minAOI) {
00257             AOIWidth = minAOI;
00258         }
00259 
00260         if( oldAOI != AOIWidth ){
00261             GameAPIResizeAOIMessage* gameMsg = new GameAPIResizeAOIMessage("RESIZE_AOI");
00262             gameMsg->setCommand(RESIZE_AOI);
00263             gameMsg->setAOIsize(AOIWidth);
00264             sendToApp(gameMsg);
00265         }
00266     }
00267 }
00268 
00269 void Quon::handleAppMessage(cMessage* msg)
00270 {
00271     GameAPIMessage* gameAPIMsg = dynamic_cast<GameAPIMessage*>(msg);
00272     if(gameAPIMsg != NULL) {
00273         // debug output
00274         if(debugOutput) {
00275             EV << "[Quon::handleAppMessage() @ " << thisNode.getAddress()
00276                << " (" << thisNode.getKey().toString(16) << ")]\n"
00277                << "    Node " << thisSite->address.getAddress() << " received " << gameAPIMsg->getName() << " from application."
00278                << endl;
00279         }
00280         switch(gameAPIMsg->getCommand()) {
00281             case MOVEMENT_INDICATION: {
00282                 GameAPIPositionMessage* gameAPIPositionMsg = dynamic_cast<GameAPIPositionMessage*>(msg);
00283                 if(qstate == QJOINING) {
00284                     handleJoin(gameAPIPositionMsg);
00285                 }
00286                 else if(qstate == QREADY) {
00287                     handleMove(gameAPIPositionMsg);
00288                 }
00289             } break;
00290             case GAMEEVENT_CHAT:
00291             case GAMEEVENT_SNOW:
00292             case GAMEEVENT_FROZEN: {
00293                 handleEvent(gameAPIMsg);
00294             } break;
00295         }
00296     }
00297     delete msg;
00298 }
00299 
00300 void Quon::handleUDPMessage(BaseOverlayMessage* msg)
00301 {
00302     if(qstate == QUNINITIALIZED) {
00303         delete msg;
00304         return;
00305     }
00306     QuonMessage* quonMsg = dynamic_cast<QuonMessage*>(msg);
00307     if(quonMsg != NULL) {
00308         // debug output
00309         if(debugOutput) {
00310             EV << "[Quon::handleUDPMessage() @ " << thisNode.getAddress()
00311                << " (" << thisNode.getKey().toString(16) << ")]\n"
00312                << "    Node " << thisSite->address.getAddress() << " received " << quonMsg->getName() << " from " << quonMsg->getSender().getAddress() << "."
00313                << endl;
00314         }
00315         if(qstate == QREADY) {
00316             switch(quonMsg->getCommand()) {
00317                 case JOIN_REQUEST: {
00318                     handleJoinRequest(quonMsg);
00319                 } break;
00320                 case NODE_MOVE: {
00321                     QuonMoveMessage* quonMoveMsg = dynamic_cast<QuonMoveMessage*>(msg);
00322                     handleNodeMove(quonMoveMsg);
00323                     delete msg;
00324                 } break;
00325                 case NEW_NEIGHBORS: {
00326                     QuonListMessage* quonListMsg = dynamic_cast<QuonListMessage*>(msg);
00327                     handleNewNeighbors(quonListMsg);
00328                     delete msg;
00329                 } break;
00330                 case NODE_LEAVE: {
00331                     QuonListMessage* quonListMsg = dynamic_cast<QuonListMessage*>(msg);
00332                     handleNodeLeave(quonListMsg);
00333                     delete msg;
00334                 } break;
00335                 case QUON_EVENT: {
00336                     sendToApp(quonMsg->decapsulate());
00337                     delete quonMsg;
00338                 } break;
00339             }
00340         }
00341         else if(qstate == QJOINING && quonMsg->getCommand() == JOIN_ACKNOWLEDGE) {
00342             QuonListMessage* quonListMsg = dynamic_cast<QuonListMessage*>(msg);
00343             handleJoinAcknowledge(quonListMsg);
00344             delete msg;
00345         }
00346         else {
00347             delete msg;
00348         }
00349     }
00350     else {
00351         delete msg;
00352     }
00353 }
00354 
00355 bool Quon::addSite(Vector2D p, NodeHandle node, double AOI, bool isSoft, QUpdateType update)
00356 {
00357     QuonSiteMap::iterator itSites = Sites.find(node.getKey());
00358     QDeleteMap::iterator delIt = deletedSites.find(node.getKey());
00359     // add node if he is not in the delete list OR has changed position since 
00360     // put in the delete list. don't add node if he has signled his leave himself
00361     // (i.e. his position in the delete list is 0,0)
00362     if(node.getKey() != thisSite->address.getKey() && 
00363             (delIt == deletedSites.end() || (delIt->second != Vector2D(0,0) && delIt->second != p) )){
00364         if(itSites == Sites.end()) {
00365             if(debugOutput) {
00366                 EV << "[Quon::addSite() @ " << thisNode.getAddress()
00367                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00368                    << "    Site " << node.getAddress() << " at " << p << " has been added to the list."
00369                    << endl;
00370             }
00371             QuonSite* temp = new QuonSite();
00372             temp->position = p;
00373             temp->address = node;
00374             if(update == QDIRECT) {
00375                 temp->dirty = true;
00376             }
00377             temp->alive = true;
00378             temp->type = QUNDEFINED;
00379             temp->softNeighbor = isSoft;
00380             temp->AOIwidth = AOI;
00381 
00382             Sites.insert(std::make_pair(temp->address.getKey(), temp));
00383         }
00384         else if(update == QDIRECT || !itSites->second->alive) {
00385             if(debugOutput) {
00386                 EV << "[Quon::addSite() @ " << thisNode.getAddress()
00387                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00388                    << "    Site " << node.getAddress() << " at " << p << " has been updated in the list."
00389                    << endl;
00390             }
00391             itSites->second->position = p;
00392             itSites->second->dirty = true;
00393             itSites->second->alive = true;
00394             itSites->second->softNeighbor = isSoft;
00395             itSites->second->type = QUNDEFINED;
00396             itSites->second->AOIwidth = AOI;
00397         }
00398         return true;
00399     }
00400     return false;
00401 }
00402 
00403 void Quon::updateThisSite(Vector2D p)
00404 {
00405     if(debugOutput) {
00406         EV << "[Quon::updateThisSite() @ " << thisNode.getAddress()
00407            << " (" << thisNode.getKey().toString(16) << ")]\n"
00408            << "    This Site position has been updated to " << p << "."
00409            << endl;
00410     }
00411     thisSite->position = p;
00412 }
00413 
00414 void Quon::classifySites()
00415 {
00416     if(Sites.size() > 0) {
00417         QuonAOI AOI(thisSite->position, AOIWidth, useSquareMetric);
00418         QuonSite* (*bindingCandidates)[4] = new QuonSite*[numBackups+1][4];
00419         for( int i = 0; i <= numBackups; ++i ){
00420             for( int ii = 0; ii < 4; ++ii ){
00421                 bindingCandidates[i][ii] = 0;
00422             }
00423         }
00424         double (*bindingDistance)[4] = new double[numBackups+1][4];
00425         for( int i = 0; i <= numBackups; ++i ){
00426             for( int ii = 0; ii < 4; ++ii ){
00427                 bindingDistance[i][ii] = std::numeric_limits<double>::infinity();
00428             }
00429         }
00430 
00431         for(QuonSiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00432             QuonAOI NeighborAOI(itSites->second->position, itSites->second->AOIwidth, useSquareMetric);
00433             if(AOI.collide(itSites->second->position) || NeighborAOI.collide(thisSite->position)) {
00434                 if(itSites->second->type != QNEIGHBOR) {
00435                     itSites->second->type = QNEIGHBOR;
00436                     itSites->second->dirty = true;
00437                 }
00438             }
00439             else if(itSites->second->type != QUNDEFINED) {
00440                 itSites->second->type = QUNDEFINED;
00441                 itSites->second->dirty = true;
00442             }
00443             int quad = thisSite->position.getQuadrant( itSites->second->position );
00444             double dist;
00445             if( useSquareMetric ) {
00446                 dist = thisSite->position.xyMaxDistance(itSites->second->position);
00447             } else {
00448                 dist = thisSite->position.distanceSqr(itSites->second->position);
00449             }
00450 
00451             // if dist is smaller than the most far binding candidate
00452             if( dist < bindingDistance[numBackups][quad] ){
00453             // Go through list of binding candidates until distance to current candidate
00454             // is greater than distance to new candidate (i.e. look where in the binding
00455             // candidate list the node belongs)
00456                 int backupPos = numBackups-1;
00457                 while( backupPos >= 0 && dist < bindingDistance[backupPos][quad] ){
00458                     // move old candidate one position back in the queue to make
00459                     // room for new candidate
00460                     bindingCandidates[backupPos+1][quad] = bindingCandidates[backupPos][quad];
00461                     bindingDistance[backupPos+1][quad] = bindingDistance[backupPos][quad];
00462                     --backupPos;
00463                 }
00464                 // place new candidate at appropriate position in candidate list
00465                 bindingCandidates[backupPos+1][quad] = itSites->second;
00466                 bindingDistance[backupPos+1][quad] = dist;
00467             }
00468 
00469         }
00470         for( int i = 0; i < 4; ++i ){
00471             if( bindingCandidates[0][i] ){
00472                 bindingCandidates[0][i]->type = QBINDING;
00473                 bindingCandidates[0][i]->dirty = true;
00474                 for( int ii = 1; ii <= numBackups; ++ii ){
00475                     if( bindingCandidates[ii][i] ){
00476                         bindingBackup[ii-1][i] = bindingCandidates[ii][i]->address;
00477                     }
00478                 }
00479             }
00480         }
00481 
00482         delete[] bindingCandidates;
00483         delete[] bindingDistance;
00484     }
00485     else {
00486         ++rejoinCount;
00487 
00488         changeState(QUNINITIALIZED);
00489         changeState(QJOINING);
00490     }
00491 }
00492 
00493 bool Quon::deleteSite(NodeHandle node)
00494 {
00495     QuonSiteMap::iterator itSites = Sites.find(node.getKey());
00496     if(itSites != Sites.end()) {
00497         if(debugOutput) {
00498             EV << "[Quon::deleteSite() @ " << thisNode.getAddress()
00499                << " (" << thisNode.getKey().toString(16) << ")]\n"
00500                << "    Site " << node.getAddress() << " at " << itSites->second->position << " has been removed from the list."
00501                << endl;
00502         }
00503         delete itSites->second;
00504         Sites.erase(itSites);
00505         return true;
00506     }
00507     return false;
00508 }
00509 
00510 int Quon::purgeSites(QPurgeType purgeSoftSites)
00511 {
00512     int purged = 0;
00513     QuonSiteMap::iterator itSites = Sites.begin();
00514     while(itSites != Sites.end()) {
00515         // Purge softNeighbors only if QPURGESOFT is set
00516         if(itSites->second->type == QUNDEFINED && ( purgeSoftSites == QPURGESOFT || !itSites->second->softNeighbor) ) {
00517             if(debugOutput) {
00518                 EV << "[Quon::purgeSites() @ " << thisNode.getAddress()
00519                    << " (" << thisNode.getKey().toString(16) << ")]\n"
00520                    << "    Site " << itSites->second->address.getAddress() << " at " << itSites->second->position << " has been removed from the list.\n"
00521                    << "    Status: " << ((itSites->second->type == QUNDEFINED) ? "QUNDEFINED" : "QSOFT")
00522                    << endl;
00523             }
00524             delete itSites->second;
00525             Sites.erase(itSites++);
00526             ++purged;
00527         }
00528         else {
00529             ++itSites;
00530         }
00531     }
00532     return purged;
00533 }
00534 
00535 void Quon::handleNodeGracefulLeaveNotification()
00536 {
00537     if(qstate == QREADY) {
00538         CompReadyMessage* readyMsg = new CompReadyMessage("OVERLAY_FINISHED");
00539         readyMsg->setReady(false);
00540         readyMsg->setComp(getThisCompType());
00541         // TODO/FIXME: use overlay->sendMessageToAllComp(msg, getThisCompType())?
00542         sendToApp(readyMsg);
00543         if(Sites.size() > 0) {
00544             // generate node leave messages
00545             QuonListMessage* quonListMsg = new QuonListMessage("NODE_LEAVE");
00546             quonListMsg->setCommand(NODE_LEAVE);
00547             quonListMsg->setSender(thisSite->address);
00548             quonListMsg->setPosition(thisSite->position);
00549             quonListMsg->setAOIsize(AOIWidth);
00550             // fill neighbors list
00551             quonListMsg->setNeighborHandleArraySize(Sites.size());
00552             quonListMsg->setNeighborPositionArraySize(Sites.size());
00553             int i = 0;
00554             for(QuonSiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00555                 quonListMsg->setNeighborHandle(i, itSites->second->address);
00556                 quonListMsg->setNeighborPosition(i, itSites->second->position);
00557                 ++i;
00558             }
00559             quonListMsg->setBitLength(QUONLIST_L(quonListMsg));
00560 
00561             for(QuonSiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00562                 QuonListMessage* quonCopyMsg = new QuonListMessage(*quonListMsg);
00563                 sendMessage(quonCopyMsg, itSites->second->address);
00564             }
00565             delete quonListMsg;
00566         }
00567         changeState(QUNINITIALIZED);
00568     }
00569 }
00570 
00571 void Quon::processJoinTimer()
00572 {
00573     GameAPIMessage* gameMsg = new GameAPIMessage("MOVEMENT_REQUEST");
00574     gameMsg->setCommand(MOVEMENT_REQUEST);
00575     sendToApp(gameMsg);
00576 }
00577 
00578 void Quon::processSecTimer()
00579 {
00580     RECORD_STATS(
00581         if(bytesPerSecond > maxBytesPerSecondSend) {
00582             maxBytesPerSecondSend = bytesPerSecond;
00583         }
00584         avgAOI += AOIWidth;
00585         averageBytesPerSecondSend += bytesPerSecond;
00586         for(QuonSiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00587             switch(itSites->second->type) {
00588                 case QNEIGHBOR:
00589                     directNeighborCount++;
00590                     break;
00591                 case QBINDING:
00592                     bindingNeighborCount++;
00593                     break;
00594                 case QUNDEFINED:
00595                     if( itSites->second->softNeighbor ){
00596                         softNeighborCount++;
00597                     }
00598                     break;
00599                 case QTHIS:
00600                     break;
00601             }
00602         }
00603         ++secTimerCount;
00604     );
00605     bytesPerSecond = 0.0;
00606 }
00607 
00608 void Quon::processDeleteTimer(cMessage* msg)
00609 {
00610     QuonSelfMessage* quonMsg = dynamic_cast<QuonSelfMessage*>(msg);
00611     QDeleteMap::iterator itSite = deletedSites.find(quonMsg->getKey());
00612     if(itSite != deletedSites.end()) {
00613         deletedSites.erase(itSite);
00614     }
00615     cancelAndDelete(quonMsg);
00616 }
00617 
00618 void Quon::processAliveTimer()
00619 {
00620     bool rebuild = false;
00621     QuonSiteMap::iterator itSites = Sites.begin();
00622     while(itSites != Sites.end()) {
00623         if(itSites->second->alive) {
00624             itSites->second->alive = false;
00625             ++itSites;
00626         }
00627         else {
00628             NodeHandle node = itSites->second->address;
00629             QuonSelfMessage* msg = new QuonSelfMessage("delete_timer");
00630             msg->setKey(node.getKey());
00631             scheduleAt(simTime() + deleteTimeout, msg);
00632             deletedSites.insert(std::make_pair(node.getKey(), itSites->second->position));
00633             ++itSites;
00634             deleteSite(node);
00635             // update simple client
00636             deleteAppNeighbor(node);
00637             if(!rebuild) {
00638                 rebuild = true;
00639             }
00640         }
00641     }
00642     if(rebuild) {
00643         classifySites();
00644         // update simple client
00645         synchronizeAppNeighbors();
00646         purgeSites();
00647     }
00648 }
00649 
00650 void Quon::processBackupTimer()
00651 {
00652     QuonMoveMessage* quonMoveMsg = new QuonMoveMessage("NODE_MOVE");
00653     quonMoveMsg->setCommand(NODE_MOVE);
00654     quonMoveMsg->setSender(thisSite->address);
00655     quonMoveMsg->setPosition(thisSite->position);
00656     quonMoveMsg->setAOIsize(AOIWidth);
00657     quonMoveMsg->setNewPosition(thisSite->position);
00658     quonMoveMsg->setIsBinding(true);
00659     for(unsigned int i=0; i<4; i++) {
00660         for( int ii = 0; ii < numBackups; ++ii ){
00661             if(!bindingBackup[ii][i].isUnspecified()) {
00662                 QuonMoveMessage* copyMsg = new QuonMoveMessage(*quonMoveMsg);
00663                 copyMsg->setBitLength(QUONMOVE_L(copyMsg));
00664                 sendMessage(copyMsg, bindingBackup[ii][i]);
00665             }
00666         }
00667     }
00668     delete quonMoveMsg;
00669 }
00670 
00671 void Quon::handleJoin(GameAPIPositionMessage* gameMsg)
00672 {
00673     TransportAddress joinNode = bootstrapList->getBootstrapNode();
00674     thisSite->position = gameMsg->getPosition();
00675     // check if this is the only node in the overlay
00676     if(joinNode.isUnspecified()) {
00677         changeState(QREADY);
00678     }
00679     else {
00680         QuonMessage* quonMsg = new QuonMessage("JOIN_REQUEST");
00681         quonMsg->setCommand(JOIN_REQUEST);
00682         quonMsg->setSender(thisSite->address);
00683         quonMsg->setPosition(thisSite->position);
00684         quonMsg->setAOIsize(AOIWidth);
00685         quonMsg->setBitLength(QUON_L(quonMsg));
00686         sendMessage(quonMsg, joinNode);
00687     }
00688 }
00689 
00690 void Quon::handleMove(GameAPIPositionMessage* gameMsg)
00691 {
00692     Vector2D position = gameMsg->getPosition();
00693     // send position update to neighbors
00694     QuonMoveMessage* quonMoveMsg = new QuonMoveMessage("NODE_MOVE");
00695     quonMoveMsg->setCommand(NODE_MOVE);
00696     quonMoveMsg->setSender(thisSite->address);
00697     quonMoveMsg->setPosition(thisSite->position);
00698     quonMoveMsg->setAOIsize(AOIWidth);
00699     quonMoveMsg->setNewPosition(position);
00700     quonMoveMsg->setBitLength(QUONMOVE_L(quonMoveMsg));
00701 
00702     QuonMoveMessage* quonMoveBindingMsg = new QuonMoveMessage(*quonMoveMsg);
00703     quonMoveBindingMsg->setNeighborHandleArraySize(Sites.size());
00704     quonMoveBindingMsg->setNeighborPositionArraySize(Sites.size());
00705     int i = 0;
00706     for(QuonSiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00707       if(itSites->second->type == QBINDING || itSites->second->softNeighbor ) {
00708         quonMoveBindingMsg->setNeighborHandle(i, itSites->second->address);
00709         quonMoveBindingMsg->setNeighborPosition(i, itSites->second->position);
00710         ++i;
00711       }
00712     }
00713     quonMoveBindingMsg->setNeighborHandleArraySize(i);
00714     quonMoveBindingMsg->setNeighborPositionArraySize(i);
00715     if(i > 0) {
00716       // speedhack:
00717       // instead of building individual MoveMessages for every binding and softstate neighbor,
00718       // we just send all binding/soft to every other binding/soft neighbor and pretend we did not send  neighbors their own neighborslistentry
00719       quonMoveBindingMsg->setBitLength(QUONMOVE_L(quonMoveBindingMsg) - QUONENTRY_L);
00720     }
00721 
00722     for(QuonSiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00723       QuonMoveMessage* copyMsg;
00724       if(itSites->second->type == QBINDING || itSites->second->softNeighbor ) {
00725         copyMsg = new QuonMoveMessage(*quonMoveBindingMsg);
00726         if(itSites->second->type == QBINDING) {
00727           copyMsg->setIsBinding(true);
00728         }
00729         else {
00730           ++softConnections;
00731         }
00732       }
00733       else {
00734         copyMsg = new QuonMoveMessage(*quonMoveMsg);
00735       }
00736       sendMessage(copyMsg, itSites->second->address);
00737     }
00738     delete quonMoveMsg;
00739     delete quonMoveBindingMsg;
00740 
00741     // update position
00742     updateThisSite(position);
00743     classifySites();
00744     // update simple client
00745     synchronizeAppNeighbors(QPURGESOFT);
00746     purgeSites(QPURGESOFT);
00747 }
00748 
00749 void Quon::handleEvent(GameAPIMessage* msg)
00750 {
00751     // send event to neighbors
00752     for(QuonSiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00753         QuonEventMessage *quonMsg = new QuonEventMessage("EVENT");
00754         quonMsg->setCommand(QUON_EVENT);
00755         quonMsg->encapsulate((cPacket*)msg->dup());
00756         // FIXME: Message length!
00757         sendMessage(quonMsg, itSites->second->address);
00758     }
00759 }
00760 
00761 void Quon::handleJoinRequest(QuonMessage* quonMsg)
00762 {
00763     Vector2D joinPosition = quonMsg->getPosition();
00764     // start with this node
00765     double min_dist = thisSite->position.distanceSqr(joinPosition);
00766     QuonSite* forwardSite = thisSite;
00767     // iterate through all neighbors
00768     for(QuonSiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00769         if(itSites->second->position.distanceSqr(joinPosition) < min_dist) { //FIXME: use xy metric if desired?
00770             min_dist = itSites->second->position.distanceSqr(joinPosition);
00771             forwardSite = itSites->second;
00772         }
00773     }
00774 
00775     // do nothing and let node retry with new position if current position is illegal
00776     if(min_dist == 0.0) {
00777         delete quonMsg;
00778     }
00779     else if(forwardSite->type == QTHIS) {
00780         QuonListMessage* quonListMsg = new QuonListMessage("JOIN_ACKNOWLEDGE");
00781         quonListMsg->setCommand(JOIN_ACKNOWLEDGE);
00782         quonListMsg->setSender(thisSite->address);
00783         quonListMsg->setPosition(thisSite->position);
00784         quonListMsg->setAOIsize(AOIWidth);
00785         // fill neighbors list
00786         quonListMsg->setNeighborHandleArraySize(Sites.size());
00787         quonListMsg->setNeighborPositionArraySize(Sites.size());
00788         int i = 0;
00789         for(QuonSiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00790             quonListMsg->setNeighborHandle(i, itSites->second->address);
00791             quonListMsg->setNeighborPosition(i, itSites->second->position);
00792             ++i;
00793         }
00794         quonListMsg->setNeighborHandleArraySize(i);
00795         quonListMsg->setNeighborPositionArraySize(i);
00796 
00797         quonListMsg->setBitLength(QUONLIST_L(quonListMsg));
00798         sendMessage(quonListMsg, quonMsg->getSender());
00799         delete quonMsg;
00800     }
00801     else {
00802         sendMessage(quonMsg, forwardSite->address);
00803     }
00804 }
00805 
00806 void Quon::handleJoinAcknowledge(QuonListMessage* quonListMsg)
00807 {
00808     // add acceptor node
00809     changeState(QREADY);
00810     addSite(quonListMsg->getPosition(), quonListMsg->getSender(), quonListMsg->getAOIsize(), false, QDIRECT);
00811     // add new neighbors
00812     for(unsigned int i=0; i<quonListMsg->getNeighborHandleArraySize(); i++) {
00813         addSite(quonListMsg->getNeighborPosition(i), quonListMsg->getNeighborHandle(i), quonListMsg->getAOIsize());
00814     }
00815     classifySites();
00816     // update simple client
00817     synchronizeAppNeighbors();
00818     purgeSites();
00819     // contact new neighbors
00820     for(QuonSiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00821         QuonMoveMessage* quonMoveMsg = new QuonMoveMessage("NODE_MOVE");
00822         quonMoveMsg->setCommand(NODE_MOVE);
00823         quonMoveMsg->setSender(thisSite->address);
00824         quonMoveMsg->setPosition(quonListMsg->getPosition());
00825         quonMoveMsg->setAOIsize(AOIWidth);
00826         quonMoveMsg->setNewPosition(thisSite->position);
00827         if(itSites->second->type == QBINDING) {
00828             quonMoveMsg->setIsBinding(true);
00829         }
00830         quonMoveMsg->setBitLength(QUONMOVE_L(quonMoveMsg));
00831         sendMessage(quonMoveMsg, itSites->second->address);
00832     }
00833     bytesPerSecond = 0.0;
00834 }
00835 
00836 void Quon::handleNodeMove(QuonMoveMessage* quonMoveMsg)
00837 {
00838     RECORD_STATS(
00839             globalStatistics->addStdDev(
00840                 "QuON: MoveDelay",
00841                 SIMTIME_DBL(simTime()) - SIMTIME_DBL(quonMoveMsg->getCreationTime())
00842                 );
00843             );
00844 
00845     // IF node was marked for deletetion, remove it from the delete list
00846     QDeleteMap::iterator delIt = deletedSites.find(quonMoveMsg->getSender().getKey());
00847     if( delIt != deletedSites.end() ){
00848         deletedSites.erase( delIt );
00849     }
00850 
00851     // Compute old and new AOI of moving node
00852     QuonAOI oldAOI(quonMoveMsg->getPosition(), quonMoveMsg->getAOIsize(), useSquareMetric);
00853     QuonAOI newAOI(quonMoveMsg->getNewPosition(), quonMoveMsg->getAOIsize(), useSquareMetric);
00854     if(useDynamicAOI) {
00855         QuonSiteMap::iterator itSites = Sites.find(quonMoveMsg->getSender().getKey());
00856         if(itSites != Sites.end() && itSites->second->AOIwidth < quonMoveMsg->getAOIsize()) {
00857             oldAOI.resize(itSites->second->AOIwidth);
00858         }
00859     }
00860 
00861     addSite(quonMoveMsg->getNewPosition(), quonMoveMsg->getSender(), quonMoveMsg->getAOIsize(), quonMoveMsg->getIsBinding(), QDIRECT);
00862     // add new neighbors
00863     handleInvalidNode(quonMoveMsg);
00864     for(unsigned int i=0; i<quonMoveMsg->getNeighborHandleArraySize(); i++) {
00865         addSite(quonMoveMsg->getNeighborPosition(i), quonMoveMsg->getNeighborHandle(i), quonMoveMsg->getAOIsize());
00866     }
00867     classifySites();
00868     // update simple client
00869     synchronizeAppNeighbors();
00870     purgeSites();
00871 
00872     // send new neighbors
00873     QuonListMessage* quonListMsg = new QuonListMessage("NEW_NEIGHBORS");
00874     quonListMsg->setCommand(NEW_NEIGHBORS);
00875     quonListMsg->setSender(thisSite->address);
00876     quonListMsg->setPosition(thisSite->position);
00877     quonListMsg->setAOIsize(AOIWidth);
00878 
00879     quonListMsg->setNeighborHandleArraySize(Sites.size());
00880     quonListMsg->setNeighborPositionArraySize(Sites.size());
00881 
00882     int i = 0;
00883     for(QuonSiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00884         if(quonMoveMsg->getSender() != itSites->second->address &&
00885            !oldAOI.collide(itSites->second->position) &&
00886            newAOI.collide(itSites->second->position)) {
00887             quonListMsg->setNeighborHandle(i, itSites->second->address);
00888             quonListMsg->setNeighborPosition(i, itSites->second->position);
00889             ++i;
00890         }
00891     }
00892 
00893     if(i > 0) {
00894         quonListMsg->setNeighborHandleArraySize(i);
00895         quonListMsg->setNeighborPositionArraySize(i);
00896         quonListMsg->setBitLength(QUONLIST_L(quonListMsg));
00897         sendMessage(quonListMsg, quonMoveMsg->getSender());
00898     }
00899     else {
00900         delete quonListMsg;
00901     }
00902 }
00903 
00904 void Quon::handleNewNeighbors(QuonListMessage* quonListMsg)
00905 {
00906     addSite(quonListMsg->getPosition(), quonListMsg->getSender(), quonListMsg->getAOIsize(), false, QDIRECT);
00907 
00908     // add new neighbors
00909     handleInvalidNode(quonListMsg);
00910     for(unsigned int i=0; i<quonListMsg->getNeighborHandleArraySize(); i++) {
00911         addSite(quonListMsg->getNeighborPosition(i), quonListMsg->getNeighborHandle(i), quonListMsg->getAOIsize());
00912     }
00913     classifySites();
00914     // update simple client
00915     synchronizeAppNeighbors();
00916     purgeSites();
00917 }
00918 
00919 void Quon::handleNodeLeave(QuonListMessage* quonListMsg)
00920 {
00921     deleteSite(quonListMsg->getSender());
00922     // update simple client
00923     deleteAppNeighbor(quonListMsg->getSender());
00924 
00925     // insert into delete list
00926     QuonSelfMessage* msg = new QuonSelfMessage("delete_timer");
00927     msg->setKey(quonListMsg->getSender().getKey());
00928     scheduleAt(simTime() + deleteTimeout, msg);
00929     deletedSites.insert(std::make_pair(quonListMsg->getSender().getKey(), Vector2D(0,0)));
00930 
00931     // add possible new neighbors
00932     handleInvalidNode(quonListMsg);
00933     for(unsigned int i=0; i<quonListMsg->getNeighborHandleArraySize(); i++) {
00934         addSite(quonListMsg->getNeighborPosition(i), quonListMsg->getNeighborHandle(i), quonListMsg->getAOIsize(), true);
00935     }
00936     classifySites();
00937     // update simple client
00938     synchronizeAppNeighbors();
00939     purgeSites();
00940 }
00941 
00942 // XXX FIXME Disabled, may cause exessive traffic
00943 void Quon::handleInvalidNode(QuonListMessage* quonListMsg)
00944 {
00945     return;
00946     for(unsigned int i=0; i<quonListMsg->getNeighborHandleArraySize(); i++) {
00947         if(deletedSites.find(quonListMsg->getNeighborHandle(i).getKey()) != deletedSites.end()) {
00948             QuonListMessage* quonLeaveMsg = new QuonListMessage("NODE_LEAVE");
00949             quonLeaveMsg->setCommand(NODE_LEAVE);
00950             quonLeaveMsg->setSender(quonListMsg->getNeighborHandle(i));
00951             quonLeaveMsg->setPosition(quonListMsg->getNeighborPosition(i));
00952             quonLeaveMsg->setAOIsize(AOIWidth);
00953             quonLeaveMsg->setNeighborHandleArraySize(Sites.size());
00954             quonLeaveMsg->setNeighborPositionArraySize(Sites.size());
00955             int i = 0;
00956             for(QuonSiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00957                 if(itSites->second->type == QBINDING) {
00958                     quonLeaveMsg->setNeighborHandle(i, itSites->second->address);
00959                     quonLeaveMsg->setNeighborPosition(i, itSites->second->position);
00960                     ++i;
00961                 }
00962             }
00963             quonLeaveMsg->setNeighborHandleArraySize(i);
00964             quonLeaveMsg->setNeighborPositionArraySize(i);
00965             quonLeaveMsg->setBitLength(QUONLIST_L(quonLeaveMsg));
00966             sendMessage(quonLeaveMsg, quonListMsg->getSender());
00967         }
00968     }
00969 }
00970 
00971 void Quon::synchronizeAppNeighbors(QPurgeType purgeSoftSites)
00972 {
00973     GameAPIListMessage* gameMsg = new GameAPIListMessage("NEIGHBOR_UPDATE");
00974     gameMsg->setCommand(NEIGHBOR_UPDATE);
00975 
00976     gameMsg->setRemoveNeighborArraySize(Sites.size());
00977     gameMsg->setAddNeighborArraySize(Sites.size());
00978     gameMsg->setNeighborPositionArraySize(Sites.size());
00979 
00980     int remSize, addSize;
00981     remSize = addSize = 0;
00982     for(QuonSiteMap::iterator itSites = Sites.begin(); itSites != Sites.end(); ++itSites) {
00983         if(itSites->second->type == QUNDEFINED && (purgeSoftSites == QPURGESOFT || !itSites->second->softNeighbor) && itSites->second->dirty) {
00984             gameMsg->setRemoveNeighbor(remSize, itSites->second->address);
00985             ++remSize;
00986         }
00987         else if(itSites->second->dirty) {
00988             gameMsg->setAddNeighbor(addSize, itSites->second->address);
00989             gameMsg->setNeighborPosition(addSize, itSites->second->position);
00990             itSites->second->dirty = false;
00991             ++addSize;
00992         }
00993     }
00994 
00995     if(remSize > 0 || addSize > 0) {
00996         gameMsg->setRemoveNeighborArraySize(remSize);
00997         gameMsg->setAddNeighborArraySize(addSize);
00998         gameMsg->setNeighborPositionArraySize(addSize);
00999         sendToApp(gameMsg);
01000     }
01001     else {
01002         delete gameMsg;
01003     }
01004 }
01005 
01006 void Quon::deleteAppNeighbor(NodeHandle node)
01007 {
01008     GameAPIListMessage* gameMsg = new GameAPIListMessage("NEIGHBOR_UPDATE");
01009     gameMsg->setCommand(NEIGHBOR_UPDATE);
01010     gameMsg->setRemoveNeighborArraySize(1);
01011     gameMsg->setAddNeighborArraySize(0);
01012     gameMsg->setNeighborPositionArraySize(0);
01013     gameMsg->setRemoveNeighbor(0, node);
01014     sendToApp(gameMsg);
01015 }
01016 
01017 void Quon::sendToApp(cMessage* msg)
01018 {
01019     // debug output
01020     if(debugOutput) {
01021         EV << "[Quon::sendToApp() @ " << thisNode.getAddress()
01022            << " (" << thisNode.getKey().toString(16) << ")]\n"
01023            << "    Node " << thisSite->address.getAddress() << " sending " << msg->getName() << " to application."
01024            << endl;
01025     }
01026     send(msg, "appOut");
01027 }
01028 
01029 void Quon::sendMessage(QuonMessage* quonMsg, NodeHandle destination)
01030 {
01031     // collect statistics
01032     RECORD_STATS(
01033         switch(quonMsg->getCommand()) {
01034             case JOIN_REQUEST:
01035                 joinRequestBytesSend += quonMsg->getByteLength();
01036             break;
01037             case JOIN_ACKNOWLEDGE:
01038                 joinAcknowledgeBytesSend += quonMsg->getByteLength();
01039             break;
01040             case NODE_MOVE:
01041                 nodeMoveBytesSend += quonMsg->getByteLength();
01042             break;
01043             case NEW_NEIGHBORS:
01044                 newNeighborsBytesSend += quonMsg->getByteLength();
01045             break;
01046             case NODE_LEAVE:
01047                 nodeLeaveBytesSend += quonMsg->getByteLength();
01048             break;
01049         }
01050         if(qstate == QREADY) {
01051             bytesPerSecond += quonMsg->getByteLength();
01052         }
01053     );
01054 
01055     // debug output
01056     if(debugOutput) {
01057         EV << "[Quon::sendMessage() @ " << thisNode.getAddress()
01058            << " (" << thisNode.getKey().toString(16) << ")]\n"
01059            << "    Node " << thisSite->address.getAddress() << " sending " << quonMsg->getName() << " to " << destination.getAddress() << "."
01060            << endl;
01061     }
01062     sendMessageToUDP(destination, quonMsg);
01063 }
01064 
01065 void Quon::setBootstrapedIcon()
01066 {
01067     if(ev.isGUI()) {
01068         switch(qstate) {
01069             case QUNINITIALIZED:
01070                 getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 1, "red");
01071                 getDisplayString().setTagArg("i", 1, "red");
01072                 break;
01073             case QJOINING:
01074                 getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 1, "yellow");
01075                 getDisplayString().setTagArg("i", 1, "yellow");
01076                 break;
01077             case QREADY:
01078                 getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 1, "green");
01079                 getDisplayString().setTagArg("i", 1, "green");
01080                 break;
01081         }
01082     }
01083 }
01084 
01085 void Quon::finishOverlay()
01086 {
01087     double overallBytesSend = joinRequestBytesSend
01088                             + joinAcknowledgeBytesSend
01089                             + nodeMoveBytesSend
01090                             + newNeighborsBytesSend
01091                             + nodeLeaveBytesSend;
01092     if(overallBytesSend != 0.0) {
01093         // collect statistics in percent
01094         globalStatistics->addStdDev("Quon: fraction of JOIN_REQUEST bytes sent ", joinRequestBytesSend / overallBytesSend);
01095         globalStatistics->addStdDev("Quon: fraction of JOIN_ACKNOWLEDGE bytes sent", joinAcknowledgeBytesSend / overallBytesSend);
01096         globalStatistics->addStdDev("Quon: fraction of NODE_MOVE bytes sent", nodeMoveBytesSend / overallBytesSend);
01097         globalStatistics->addStdDev("Quon: fraction of NEW_NEIGHBORS bytes sent", newNeighborsBytesSend / overallBytesSend);
01098         globalStatistics->addStdDev("Quon: fraction of NODE_LEAVE bytes sent", nodeLeaveBytesSend / overallBytesSend);
01099     }
01100     globalStatistics->addStdDev("Quon: max bytes/second sent", maxBytesPerSecondSend);
01101 
01102 //    We use our own time count to avoid rounding errors
01103 //    simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
01104 //    if(time != 0.0) {
01105     if(secTimerCount != 0) {
01106         globalStatistics->addStdDev("Quon: average bytes/second sent", averageBytesPerSecondSend / (double) secTimerCount);
01107         globalStatistics->addStdDev("Quon: average direct-neighbor count", directNeighborCount / (double) secTimerCount);
01108         globalStatistics->addStdDev("Quon: average binding-neighbor count", bindingNeighborCount / (double) secTimerCount);
01109         globalStatistics->addStdDev("Quon: average soft-neighbor count", softNeighborCount / (double) secTimerCount);
01110         //globalStatistics->addStdDev("Quon: average rejoin count", rejoinCount);
01111         globalStatistics->addStdDev("Quon: average AOI width", avgAOI / (double) secTimerCount);
01112     }
01113 
01114     changeState(QUNINITIALIZED);
01115 }
01116 
01117 QState Quon::getState()
01118 {
01119     Enter_Method_Silent();
01120     return qstate;
01121 }
01122 
01123 double Quon::getAOI()
01124 {
01125     Enter_Method_Silent();
01126     return AOIWidth - (double)par("AOIBuffer");
01127 }
01128 
01129 Vector2D Quon::getPosition()
01130 {
01131     Enter_Method_Silent();
01132     return thisSite->position;
01133 }
01134 
01135 double Quon::getAreaDimension()
01136 {
01137     Enter_Method_Silent();
01138     return areaDimension;
01139 }
01140 
01141 OverlayKey Quon::getKey()
01142 {
01143     Enter_Method_Silent();
01144     return thisSite->address.getKey();
01145 }
01146 
01147 long Quon::getSoftNeighborCount()
01148 {
01149     Enter_Method_Silent();
01150     long temp = softConnections;
01151     softConnections = 0;
01152     return temp;
01153 }
01154 
01155 Quon::~Quon()
01156 {
01157     // destroy self timer messages
01158     cancelAndDelete(join_timer);
01159     cancelAndDelete(sec_timer);
01160     cancelAndDelete(alive_timer);
01161     cancelAndDelete(backup_timer);
01162     cancelAndDelete(adaption_timer);
01163     delete thisSite;
01164     QuonSiteMap::iterator itSites = Sites.begin();
01165     while(itSites != Sites.end()) {
01166         delete itSites->second;
01167         ++itSites;
01168     }
01169 }
Generated on Wed May 26 16:21:15 2010 for OverSim by  doxygen 1.6.3