Nps.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2009 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 //
00018 
00024 #include <GlobalNodeList.h>
00025 #include <PeerInfo.h>
00026 #include <RpcMacros.h>
00027 #include <NeighborCache.h>
00028 #include <GlobalNodeListAccess.h>
00029 #include <Landmark.h>
00030 #include <UnderlayConfigurator.h>
00031 #include <SimpleNodeEntry.h>
00032 #include <SimpleInfo.h>
00033 #include <CoordBasedRoutingAccess.h>
00034 #include <GlobalStatistics.h>
00035 
00036 #include <Nps_m.h>
00037 
00038 #include <Nps.h>
00039 
00040 
00041 void Nps::init(NeighborCache* neighborCache)
00042 {
00043     this->neighborCache = neighborCache;
00044     overlay = neighborCache->overlay;
00045 
00046     npsMaxLayer = neighborCache->par("npsMaxLayer");
00047     npsDimensions = neighborCache->par("npsDimensions");
00048     landmarkTimeout = neighborCache->par("landmarkTimeout");
00049 
00050     GnpNpsCoordsInfo::setDimension(npsDimensions);
00051     ownCoords = new GnpNpsCoordsInfo();
00052 
00053     receivedCalls = 0;
00054     pendingRequests = 0;
00055     coordCalcRuns = neighborCache->par("npsCoordCalcRuns");
00056 
00057     WATCH(*ownCoords);
00058     WATCH_VECTOR(landmarkSet);
00059 
00060     coordBasedRouting = CoordBasedRoutingAccess().get();
00061     globalNodeList = GlobalNodeListAccess().get();
00062 
00063     if (neighborCache->getParentModule()->getModuleByRelativePath("tier1")
00064         ->getModuleByRelativePath("landmark") == NULL) {
00065         landmarkTimer = new cMessage("landmarkTimer");
00066         neighborCache->scheduleAt(simTime() + landmarkTimeout, landmarkTimer);
00067     } else {
00068         // GNP-landmark or NPS-Layer-0-landmark
00069         ownCoords->setLayer(0); //TODO double, see Landmark.cc
00070     }
00071 }
00072 
00073 void Nps::handleTimerEvent(cMessage* msg)
00074 {
00075     // process landmark timer message
00076     if (msg == landmarkTimer) {
00077         if (enoughLandmarks()) {
00078             delete msg;
00079             //std::cout << "[" << getThisNode().getAddress() << "] (Re-)Trying to contact landmarks" << std::endl;
00080             sendCoordRequests();
00081         } else {
00082             neighborCache->scheduleAt(simTime() + landmarkTimeout, msg);
00083         }
00084     }
00085 }
00086 
00087 void Nps::handleRpcResponse(BaseResponseMessage* msg,
00088                             cPolymorphic* context,
00089                             int rpcId, simtime_t rtt)
00090 {
00091     // call rpc stubs
00092     RPC_SWITCH_START( msg );
00093         RPC_ON_RESPONSE( CoordsReq ) {
00094             coordsReqRpcResponse(_CoordsReqResponse, context, rpcId, rtt);
00095         }
00096 #ifdef EXTJOIN_DISCOVERY
00097         RPC_ON_RESPONSE( RttToNode ) {
00098             rttToNodeRpcResponse(_RttToNodeResponse, context, rpcId, rtt);
00099         }
00100 #endif
00101     RPC_SWITCH_END( );
00102 
00103     return;
00104 }
00105 
00106 void Nps::handleRpcTimeout(BaseCallMessage* msg,
00107                            const TransportAddress& dest,
00108                            cPolymorphic* context, int rpcId,
00109                            const OverlayKey& destKey)
00110 {
00111     RPC_SWITCH_START( msg ) {
00112 
00113         RPC_ON_CALL( CoordsReq ) {
00114             if (true/*doingNodeMeasurement()*/) {//TODO
00115 #ifdef EXTJOIN_DISCOVERY
00116                 if (getPendingRttsReq(dest) == -1) {
00117                     RttToNodeCall* call = getNodeMessage(dest);
00118 
00119                     RttToNodeResponse* rttRes = new RttToNodeResponse("RttToNodeXRes");
00120                     rttRes->setPingedNode(dest);
00121                     rttRes->setRttToNode(0);
00122                     std::vector<double> tempOwnCoords;
00123                     tempOwnCoords = getOwnCoordinates();
00124                     rttRes->setOwnCoordinatesArraySize(tempOwnCoords.size());
00125                     for (uint i = 0; i < tempOwnCoords.size(); i++) {
00126                         rttRes->setOwnCoordinates(i, tempOwnCoords[i]);
00127                     }
00128                     sendRpcResponse(call, rttRes);
00129                     deleteNodeMeasurement(dest);
00130                 } else {
00131 #endif
00132                     updateNodeMeasurement(dest, -1);
00133 #ifdef EXTJOIN_DISCOVERY
00134                 }
00135 #endif
00136 
00137             } else {
00138                 pendingRequests--;
00139             }
00140         }
00141 #ifdef EXTJOIN_DISCOVERY
00142         RPC_ON_CALL( RttToNode ) {
00143             updateNodeMeasurement(dest, -1);
00144         }
00145 #endif
00146     }
00147     RPC_SWITCH_END( )
00148 }
00149 
00150 bool Nps::handleRpcCall(BaseCallMessage* msg)
00151 {
00152     RPC_SWITCH_START( msg );
00153         RPC_DELEGATE( CoordsReq, coordsReqRpc );
00154         //if (discovery)
00155     RPC_SWITCH_END( );
00156 
00157     return RPC_HANDLED;
00158 }
00159 
00160 void Nps::coordsReqRpc(CoordsReqCall* msg)
00161 {
00162     receivedCalls++;
00163     CoordsReqResponse* coordResp = new CoordsReqResponse("CoordsReqResp");
00164     coordResp->setLayer(getOwnLayer()); //TODO
00165     coordResp->setNcsInfoArraySize(npsDimensions + 1);
00166 
00167     //if (getOwnLayer() != 0) {
00168     // ordinary node
00169 
00170     const std::vector<double>& ownCoordinates = getOwnCoordinates();
00171 
00172     uint8_t i;
00173     for (i = 0; i < ownCoordinates.size(); ++i) {
00174         coordResp->setNcsInfo(i, ownCoordinates[i]);
00175     }
00176     coordResp->setNcsInfo(i, getOwnLayer());
00177 
00178     /*} else {
00179         // landmark node
00180         Landmark* landmark = check_and_cast<Landmark*>(neighborCache->getParentModule()
00181             ->getModuleByRelativePath("tier1.landmark"));
00182         assert(landmark);
00183         const std::vector<double>& ownCoordinates = landmark->getOwnNpsCoords();
00184 
00185         uint8_t i;
00186         for (i = 0; i < ownCoordinates.size(); ++i) {
00187             coordResp->setNcsInfo(i, ownCoordinates[i]);
00188         }
00189         coordResp->setNcsInfo(i, getOwnLayer());
00190     }*/
00191 
00192     coordResp->setBitLength(COORDSREQRESPONSE_L(coordResp));
00193     neighborCache->sendRpcResponse(msg, coordResp);
00194 }
00195 
00196 #ifdef EXTJOIN_DISCOVERY
00197 void Nps::rttToNodeRpc(RttToNodeCall* msg)
00198 {
00199     incReceivedCalls();
00200     TransportAddress dest = msg->getNodeToPing();
00201 //std::cout << "Set Node Message";
00202     setNodeMessage(dest, msg);
00203     sendCoordsReqCall(dest, -1);
00204 }
00205 #endif
00206 
00207 void Nps::coordsReqRpcResponse(CoordsReqResponse* response,
00208                                cPolymorphic* context, int rpcId, simtime_t rtt)
00209 {
00210     pendingRequests--;
00211     NodeHandle& srcNode = response->getSrcNode();
00212 
00213     std::vector<double> tempCoords;
00214     for (uint8_t i = 0; i < response->getNcsInfoArraySize(); i++) {
00215         tempCoords.push_back(response->getNcsInfo(i));
00216     }
00217     GnpNpsCoordsInfo* coordsInfo =
00218         static_cast<GnpNpsCoordsInfo*>(createNcsInfo(tempCoords));
00219 
00220     EV << "[Nps::coordsReqRpcResponse() @ " << neighborCache->thisNode.getAddress()
00221        << " (" << neighborCache->thisNode.getKey().toString(16) << ")]\n    received landmark coords: "
00222        << tempCoords[0];
00223 
00224     for (uint8_t i = 1; i < npsDimensions; i++) {
00225         EV << ", " << tempCoords[i];
00226     }
00227     EV  << " (rtt = " << rtt << ")" << endl;
00228 
00229 #ifdef EXTJOIN_DISCOVERY
00230     if (doingDiscovery()) {
00231         //if in Discovery insert RTT only if lower then already set RTT
00232         if ((isEntry(srcNode) && rtt < getNodeRtt(srcNode))
00233             || (isEntry(srcNode) && getNodeRtt(srcNode) < 0) ) {
00234             updateNode(srcNode, rtt, tempCoords, 0);
00235         } else if (!(isEntry(srcNode))) {
00236             updateNode(srcNode, rtt, tempCoords, 0);
00237         } else {
00238             updateNode(srcNode, getNodeRtt(srcNode), tempCoords, 0);
00239         }
00240         setNodeLayer(srcNode, tempLayer);
00241     }
00242     else if (doingNodeMeasurement()) {
00243         if (getPendingRttsReq(srcNode) == -1) {
00244             updateNode(srcNode, rtt, tempCoords, 0);
00245             setNodeLayer(srcNode, tempLayer);
00246             RttToNodeCall* prevCall = getNodeMessage(srcNode);
00247 
00248             RttToNodeResponse* rttRes = new RttToNodeResponse("RttToNodeXRes");
00249             rttRes->setPingedNode(srcNode);
00250             rttRes->setRttToNode(rtt);
00251             std::vector<double> tempOwnCoords;
00252             tempOwnCoords = getOwnCoordinates();
00253             rttRes->setOwnCoordinatesArraySize(tempOwnCoords.size());
00254             for (uint i = 0; i < tempOwnCoords.size(); i++) {
00255                 rttRes->setOwnCoordinates(i, tempOwnCoords[i]);
00256             }
00257 
00258             sendRpcResponse(prevCall, rttRes);
00259             deleteNodeMeasurement(srcNode);
00260         } else {
00261             updateNode(srcNode, rtt, tempCoords, 0);
00262             setNodeLayer(srcNode, tempLayer);
00263             if (checkCoordinates(getOwnCoordinates(), tempCoords, rtt)) {
00264                 updateNodeMeasurement(srcNode, -1, 0, 1);
00265             } else {
00266                 updateNodeMeasurement(srcNode, -1, 0, 0);
00267             }
00268         }
00269     }
00270     else
00271 #endif
00272     if (pendingRequests == 0) {
00273         // got all responses, now compute own coordinates and join overlay
00274         neighborCache->updateNode(srcNode, rtt, NodeHandle::UNSPECIFIED_NODE,
00275                                   coordsInfo);
00276 
00277         std::vector<LandmarkDataEntry> probedLandmarks;
00278         if (getLandmarkSetSize() < npsDimensions + 1) {
00279             setLandmarkSet(npsDimensions + 1, npsMaxLayer, &landmarkSet);
00280         }
00281 
00282         for (std::vector<TransportAddress>::iterator it = landmarkSet.begin();
00283              it != landmarkSet.end(); ++it) {
00284             const GnpNpsCoordsInfo* tempInfo =
00285                 dynamic_cast<const GnpNpsCoordsInfo*>(neighborCache->getNodeCoordsInfo(*it));
00286 
00287             assert(tempInfo);
00288 
00289             LandmarkDataEntry temp;
00290             temp.coordinates.resize(tempInfo->getDimension());
00291             temp.rtt = neighborCache->getNodeRtt(*it).first;
00292             temp.layer = tempInfo->getLayer();
00293             for (uint8_t i = 0; i < tempInfo->getDimension(); ++i) {
00294                 temp.coordinates[i] = tempInfo->getCoords(i);
00295             }
00296             temp.ip = NULL;
00297 
00298             probedLandmarks.push_back(temp);
00299         }
00300         assert(probedLandmarks.size() > 0);
00301 
00302         computeOwnCoordinates(probedLandmarks);
00303         computeOwnLayer(probedLandmarks);
00304 
00305         std::vector<double> coords = getOwnCoordinates();
00306         EV << "[Nps::coordsReqRpcResponse() @ " << neighborCache->thisNode.getAddress()
00307            << " (" << neighborCache->thisNode.getKey().toString(16) << ")]\n    setting own coords: "
00308            << coords[0];
00309         for (uint8_t i = 1; i < npsDimensions; i++) {
00310             EV << ", " << coords[i];
00311         }
00312         EV << endl;
00313 
00314         //test
00315         /*
00316         ChurnGenerator* lmChurnGen = NULL;
00317         for (uint8_t i = 0; i < neighborCache->underlayConfigurator->getChurnGeneratorNum(); i++) {
00318             ChurnGenerator* searchedGen;
00319             searchedGen = neighborCache->underlayConfigurator->getChurnGenerator(i);
00320             if (searchedGen->getNodeType().overlayType != "oversim.common.cbr.LandmarkModules") {
00321                 lmChurnGen = searchedGen;
00322             }
00323         }
00324         */
00325 
00326         SimpleNodeEntry* entry =
00327                 dynamic_cast<SimpleInfo*>(globalNodeList->
00328                                           getPeerInfo(neighborCache->thisNode.getAddress()))->getEntry();
00329 
00330         double error = 0;
00331         for (uint8_t i = 1; i < entry->getDim(); i++) {
00332             error += pow(coords[i] - entry->getCoords(i), 2);
00333         }
00334         error = sqrt(error);
00335 
00336         neighborCache->globalStatistics
00337           ->addStdDev("NPS: Coordinate difference", error);
00338 
00339         neighborCache->neighborCache.clear(); //TODO
00340         neighborCache->neighborCacheExpireMap.clear(); //TODO
00341 
00342         neighborCache->getParentModule()
00343             ->bubble("GNP/NPS coordinates calculated -> JOIN overlay!");
00344 
00345         if (coordBasedRouting) {
00346             int bitsPerDigit = neighborCache->overlay->getBitsPerDigit();
00347             neighborCache->thisNode.setKey(
00348                 coordBasedRouting->getNodeId(coords, bitsPerDigit,
00349                                              OverlayKey::getLength()));
00350 
00351             EV << "[Nps::coordsReqRpcResponse() @ "
00352                << neighborCache->thisNode.getAddress()
00353                << " (" << neighborCache->thisNode.getKey().toString(16) << ")]"
00354                << "\n    -> nodeID ( 2): "
00355                << neighborCache->thisNode.getKey().toString(2)
00356                << "\n    -> nodeID (16): "
00357                << neighborCache->thisNode.getKey().toString(16) << endl;
00358 
00359             // returning to BaseOverlay
00360             neighborCache->overlay->join(neighborCache->thisNode.getKey());
00361         } else {
00362             // returning to BaseOverlay
00363             neighborCache->overlay->join();
00364         }
00365     } else {
00366         neighborCache->updateNode(srcNode, rtt, NodeHandle::UNSPECIFIED_NODE,
00367                                   coordsInfo);
00368     }
00369 }
00370 
00371 #ifdef EXTJOIN_DISCOVERY
00372 void Nps::rttToNodeRpcResponse(RttToNodeResponse* response,
00373                                                cPolymorphic* context, int rpcId, simtime_t rtt)
00374 {
00375     uint dim = coordBasedRouting->getXmlDimensions();
00376     TransportAddress nodeToCheck = response->getPingedNode();
00377     std::vector<double> tempCoords;
00378     tempCoords.resize(dim);
00379     for (uint i = 0; i < dim; i++) {
00380         tempCoords[i] = response->getOwnCoordinates(i);
00381     }
00382     if (checkCoordinates(tempCoords, getNodeCoords(nodeToCheck), response->getRttToNode())) {
00383         updateNodeMeasurement(nodeToCheck, -1, 0, 1);
00384     } else {
00385         updateNodeMeasurement(nodeToCheck, -1, 0, 0);
00386     }
00387     delete context;
00388 }
00389 #endif
00390 
00391 
00392 bool Nps::setLandmarkSet(uint8_t howManyLM, uint8_t maxLayer,
00393                          std::vector<TransportAddress>* landmarkSet)
00394 {
00395     landmarkSet->clear();
00396     NeighborCache::NeighborCacheIterator it;
00397     uint availableLM = 0;
00398     TransportAddress landmark;
00399     for(it = neighborCache->neighborCache.begin(); it != neighborCache->neighborCache.end(); it++ ) {
00400         if (dynamic_cast<GnpNpsCoordsInfo*>(it->second.coordsInfo) &&
00401             static_cast<GnpNpsCoordsInfo*>(it->second.coordsInfo)->getLayer()
00402                 < maxLayer) {
00403             landmark.setAddress(it->first.getAddress());
00404             landmark.setPort(it->second.nodeRef.getPort());
00405             landmarkSet->push_back(landmark);
00406             availableLM++;
00407         }
00408     }
00409     if (availableLM < howManyLM) {
00410         return false;
00411     } else {
00412         uint i = availableLM;
00413         while (i > howManyLM) {
00414             uint randomNumber = (intuniform(0, landmarkSet->size()));
00415             landmarkSet->erase(landmarkSet->begin() + randomNumber);
00416             i--;
00417         }
00418         return true;
00419     }
00420 }
00421 
00422 void Nps::sendCoordRequests()
00423 {
00424     std::vector <TransportAddress> landmarks;
00425     landmarks = getLandmarks(npsDimensions + 1);
00426 
00427     simtime_t timeout = -1;
00428 
00429     if (landmarks.size() > 0) {
00430         for (size_t i = 0; i < landmarks.size(); i++) {
00431             const TransportAddress& tolm = landmarks[i];
00432             sendCoordsReqCall(tolm, timeout);
00433         }
00434         setLandmarkSet(npsDimensions + 1, npsMaxLayer, &landmarkSet);
00435     }
00436 }
00437 
00438 void Nps::sendCoordsReqCall(const TransportAddress& dest,
00439                             simtime_t timeout)
00440 {
00441     CoordsReqCall* coordReq = new CoordsReqCall("CoordsReq");
00442     coordReq->setBitLength(COORDSREQCALL_L(coordReq));
00443     neighborCache->sendRouteRpcCall(neighborCache->getThisCompType(), dest,
00444                                     coordReq, NULL, NO_OVERLAY_ROUTING,
00445                                     timeout, 0, -1, this);
00446     pendingRequests++;
00447 }
00448 
00449 void Nps::computeOwnLayer(const std::vector<LandmarkDataEntry>& landmarks)
00450 {
00451     int8_t computedLayer = getOwnLayer();
00452     for (uint i = 0; i < landmarks.size(); i++) {
00453         if (computedLayer <= landmarks[i].layer) {
00454             computedLayer = landmarks[i].layer + 1;
00455         }
00456     }
00457     setOwnLayer(computedLayer);
00458 }
00459 
00460 void Nps::setOwnLayer(int8_t layer)
00461 {
00462     ownCoords->setLayer(layer);
00463 
00464     // Update in BootstrapOracle
00465     PeerInfo* thisInfo = globalNodeList->getPeerInfo(neighborCache->getThisNode());
00466     thisInfo->setNpsLayer(layer);
00467 
00468     // Workaround against -1 ports in BS oracle
00469     if (layer > 0) globalNodeList->refreshEntry(neighborCache->overlay->getThisNode());
00470     if (layer < npsMaxLayer) {
00471         globalNodeList->incLandmarkPeerSize();
00472         globalNodeList->incLandmarkPeerSizePerType(thisInfo->getTypeID());
00473     }
00474 }
00475 
00476 #ifdef EXTJOIN_DISCOVERY
00477 bool Nps::checkCoordinates(std::vector<double> coordsOK, std::vector<double> coordsToCheck, simtime_t dist)
00478 {
00479     simtime_t predDist = 0.0;
00480 
00481     for (uint i = 0; i < coordsOK.size(); i++) {
00482         predDist += pow(coordsOK[i] - coordsToCheck[i], 2);
00483     }
00484     simtime_t predDistLow = sqrt(SIMTIME_DBL(predDist)) * 2 * (1 - /*(coordBasedRouting->getCoordCheckPercentage() / 100)*/0.3) / 1000;
00485     simtime_t predDistHigh = sqrt(SIMTIME_DBL(predDist)) * 2 * (1 + /*(coordBasedRouting->getCoordCheckPercentage() / 100)*/0.3) / 1000;
00486     if (dist > predDistLow && dist < predDistHigh) {
00487         return true;
00488     } else {
00489 //        std::cout << "check of Coordinates Failed! Intervall: [ " << predDistLow << " ; " << predDistHigh << " ] and dist: " << dist << endl;
00490         return false;
00491     }
00492 }
00493 #endif
00494 
00495 void Nps::computeOwnCoordinates(const std::vector<LandmarkDataEntry>& landmarks)
00496 {
00497     CoordCalcFunction coordcalcf(landmarks);
00498 
00499     Vec_DP initCoordinates(npsDimensions);
00500     Vec_DP bestCoordinates(npsDimensions);
00501     std::vector<double> computedCoordinatesStdVector(npsDimensions);
00502 
00503     double bestval;
00504     double resval;
00505 
00506     for (uint runs = 0; runs < coordCalcRuns; runs++) {
00507         // start with random coordinates (-100..100 in each dim)
00508         for (uint i = 0; i < npsDimensions; i++) {
00509             initCoordinates[i] = uniform(-100, 100);
00510         }
00511         // compute minimum coordinates via Simplex-Downhill minimum
00512         // function value is returned, coords are written into initCoordinates
00513         // (call by reference)
00514         resval = CoordCalcFunction::simplex_min(&coordcalcf, initCoordinates);
00515         if (runs == 0 || (runs > 0 && resval < bestval) ) {
00516             bestval = resval;
00517             bestCoordinates = initCoordinates;
00518         }
00519     }
00520 
00521     for (uint i = 0; i < npsDimensions; i++) {
00522         computedCoordinatesStdVector[i] = bestCoordinates[i];
00523     }
00524 
00525     setOwnCoordinates(computedCoordinatesStdVector);
00526 }
00527 
00528 std::vector<TransportAddress> Nps::getLandmarks(uint8_t howmany)
00529 {
00530     std::vector<TransportAddress> returnPool;
00531 
00532     if (howmany > globalNodeList->getLandmarkPeerSize()) {
00533         throw cRuntimeError("Not enough landmarks available in network!");
00534     }
00535 
00536     while (returnPool.size() < howmany) {
00537         TransportAddress* lm = globalNodeList->getRandomAliveNode();
00538         PeerInfo* lmInfo = globalNodeList->getPeerInfo(lm->getAddress());
00539         if (lmInfo->getNpsLayer() >= 0 &&
00540             lmInfo->getNpsLayer() < npsMaxLayer) {
00541             // already in returnPool?
00542             bool alreadyin = false;
00543             for (uint8_t i = 0; i < returnPool.size(); i++) {
00544                 if (returnPool[i] == *lm)
00545                     alreadyin = true;
00546             }
00547             if (alreadyin == false) {
00548                 returnPool.push_back(*lm);
00549             }
00550         }
00551     }
00552     return returnPool;
00553 }
00554 
00555 bool Nps::enoughLandmarks()
00556 {
00557     return (globalNodeList->getLandmarkPeerSize() > npsDimensions);
00558 }
00559 
00560 
00561 Prox Nps::getCoordinateBasedProx(const AbstractNcsNodeInfo& abstractInfo) const
00562 {
00563     return ownCoords->getDistance(abstractInfo);
00564 
00565     /*
00566     if (!dynamic_cast<const GnpNpsCoordsInfo*>(&abstractInfo)) {
00567             throw cRuntimeError("GNP/NPS coords needed!");
00568     }
00569 
00570     const GnpNpsCoordsInfo& info =
00571         *(static_cast<const GnpNpsCoordsInfo*>(&abstractInfo));
00572 
00573     double dist = 0.0;
00574     uint32_t size = info.getDimension();
00575 
00576     for (uint32_t i = 0; i < size; i++) {
00577         dist += pow(ownCoords->getCoords(i) - info.getCoords(i), 2);
00578     }
00579     dist = sqrt(dist);
00580 
00581     return Prox(dist, 0.0); //TODO accuracy
00582     */
00583 }
00584 
00585 void Nps::updateNodeMeasurement(const TransportAddress& node,
00586                                 uint8_t pending,
00587                                 uint8_t sent,
00588                                 uint8_t passed)
00589 {
00590     bool alreadySet = false;
00591     for(uint i = 0; i < nodeMeasurements.size(); i++) {
00592         if (nodeMeasurements[i].measuredNode == node && sent == 0) {
00593             nodeMeasurements[i].rttsPending += pending;
00594             nodeMeasurements[i].rttsSent += sent;
00595             nodeMeasurements[i].coordsPassed += passed;
00596             alreadySet = true;
00597             i = nodeMeasurements.size();
00598         } else if (nodeMeasurements[i].measuredNode == node) {
00599             nodeMeasurements[i].rttsPending = pending;
00600             nodeMeasurements[i].rttsSent = sent;
00601             nodeMeasurements[i].coordsPassed = passed;
00602             alreadySet = true;
00603             i = nodeMeasurements.size();
00604         }
00605     }
00606     if (!alreadySet) {
00607         RttMeasurement newNode;
00608         newNode.measuredNode = node;
00609         newNode.rttsPending = pending;
00610         newNode.rttsSent = sent;
00611         newNode.coordsPassed = passed;
00612         nodeMeasurements.push_back(newNode);
00613     }
00614 }
00615 
00616 void Nps::deleteNodeMeasurement(const TransportAddress& node)
00617 {
00618     for(uint i = 0; i < nodeMeasurements.size(); i++) {
00619         if (nodeMeasurements[i].measuredNode == node) {
00620 #ifdef EXTJOIN_DISCOVERY
00621             delete nodeMeasurements[i].message;
00622 #endif
00623             nodeMeasurements.erase(nodeMeasurements.begin()+i);
00624             i--;
00625         }
00626     }
00627     if (nodeMeasurements.size() == 0) {
00628         //stopNodeMeasurement();
00629     }
00630 }
00631 
00632 
00633 AbstractNcsNodeInfo* Nps::createNcsInfo(const std::vector<double>& coords) const
00634 {
00635     assert(coords.size() > 1);
00636     GnpNpsCoordsInfo* info = new GnpNpsCoordsInfo();
00637 
00638     uint8_t i;
00639     for (i = 0; i < coords.size() - 1; ++i) {
00640         info->setCoords(i, coords[i]);
00641     }
00642     info->setLayer(coords[i]);
00643 
00644     return info;
00645 }
00646 
00647 
00648 double CoordCalcFunction::simplex_min(CoordCalcFunction *functionObject,
00649                                       Vec_DP& init)
00650 {
00651     double accf = 0.0000001;
00652     double accx = 0.0000001;
00653     uint32_t nmax = 30001;
00654     uint8_t dim = init.size();
00655     Simplex spx(dim);
00656 
00657     int ihi;    // Index of highest point at start of each iteration
00658     Vec_DP phi(dim);   // Highest point at start of each iteration.
00659     double vhi;    // Function value at highest point at start of each iteration.
00660     double vre;    // Function value at reflected point.
00661     double vlo, diff;  // for checking convergence.
00662     uint32_t count;
00663 
00664     // Initialize Simplex
00665     Vec_DP tmp(dim);
00666     spx.functionObject = functionObject;
00667     spx[0] = init;
00668     for (uint8_t i = 0; i < dim; i++) {
00669         tmp[i] = 1;
00670         spx[i+1] = init + tmp;
00671         tmp[i] = 0;
00672     }
00673 
00674     Vec_DP debugCoords(dim);
00675 
00676     for (count = 1; count <= nmax; count++) {
00677         /*
00678         if ((count % 10000) == 0) {
00679             std::cout << "running loop #" << count << " of " << nmax << endl;
00680             std::cout << "diff: " << diff << std::endl;
00681             std::cout << "vhi: " << vhi << std::endl;
00682             std::cout << "vlo: " << vlo << std::endl;
00683             debugCoords = spx[spx.low()];
00684             std::cout << "Coords: " << debugCoords << std::endl;
00685         }
00686         */
00687         ihi = spx.high(&vhi);
00688         phi = spx[ihi];
00689         spx.reflect();
00690         vre = functionObject->f(spx[ihi]);
00691         if (vre < functionObject->f(spx[spx.low()])) {
00692             spx[ihi] = phi;  // Undo reflection.
00693             spx.reflect_exp();
00694             vre = functionObject->f(spx[ihi]);
00695             if (vre > functionObject->f(spx[spx.low()])) {
00696                 spx[ihi] = phi;
00697                 spx.reflect();
00698             }
00699         } else if (vre >= vhi) { // Equal sign important!
00700             spx[ihi] = phi;  // Undo reflection.
00701             spx.contract();
00702             if (functionObject->f(spx[ihi]) > vhi) {
00703                 spx[ihi] = phi; // Undo contraction.
00704                 spx.reduce();
00705             } // else contraction ok.
00706         } // else reflection ok
00707 
00708         spx.high(&vhi);
00709         spx.low(&vlo);
00710         diff = vhi - vlo;
00711         if (diff < accf)
00712             if (spx.size() < accx)
00713                 break;
00714     }
00715     init = spx[spx.low()];
00716     return vlo;
00717 }
00718 
00719 double CoordCalcFunction::f(const Vec_DP& initCoordinates) const
00720 {
00721     double sum = 0;
00722     double rel_diff = 0;
00723 
00724     for (uint i = 0; i < landmarks.size(); i++) {
00725         // Distance = RTT in ms / 2
00726         double diff = SIMTIME_DBL(landmarks[i].rtt) / 2 * 1000 -
00727             endnodeDistance(initCoordinates, landmarks[i]);
00728 
00729         if (SIMTIME_DBL(landmarks[i].rtt) != 0) {
00730             rel_diff = diff / (SIMTIME_DBL(landmarks[i].rtt) / 2 * 1000);
00731         } else {
00732             opp_error("[CBR] RTT == 0. Node is landmark? This shouldn't happen.");
00733         }
00734         sum += rel_diff * rel_diff;
00735     }
00736     return sum;
00737 }
00738 
00739 double CoordCalcFunction::endnodeDistance(const Vec_DP& nodeCoordinates,
00740                                           LandmarkDataEntry landmark) const
00741 {
00742     double sum_of_squares = 0.0;
00743     for (int i = 0; i < nodeCoordinates.size(); i++) {
00744         sum_of_squares += pow(landmark.coordinates[i] - nodeCoordinates[i], 2);
00745     }
00746     double result = sqrt(sum_of_squares);
00747     return result;
00748 }
00749 
Generated on Wed May 26 16:21:14 2010 for OverSim by  doxygen 1.6.3