CoordBasedRouting.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2008 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 <fstream>
00026 #include <string>
00027 #include <cassert>
00028 
00029 #include <omnetpp.h>
00030 
00031 #include <GlobalNodeListAccess.h>
00032 #include <PeerInfo.h>
00033 
00034 #include "CoordBasedRouting.h"
00035 
00036 
00037 Define_Module(CoordBasedRouting);
00038 
00039 const std::string CoordBasedRouting::NOPREFIX = "NOPREFIX";
00040 
00041 void CoordBasedRouting::initialize()
00042 {
00043     areaCoordinateSource = par("areaCoordinateSource");
00044     cbrStartAtDigit = par("CBRstartAtDigit");
00045     cbrStopAtDigit = par("CBRstopAtDigit");
00046     globalNodeList = GlobalNodeListAccess().get();
00047 
00048     // XML file found?
00049     std::ifstream check_for_xml_file(areaCoordinateSource);
00050     if (!check_for_xml_file) {
00051         check_for_xml_file.close();
00052         throw cRuntimeError("CBR area file not found!");
00053         return;
00054     }
00055     else {
00056         EV << "[CoordBasedRouting::initialize()]\n    CBR area file '"
00057            << areaCoordinateSource << "' loaded." << endl;
00058         check_for_xml_file.close();
00059     }
00060 
00061     // XML file found, let's parse it
00062     parseSource(areaCoordinateSource);
00063 }
00064 
00065 void CoordBasedRouting::finish()
00066 {
00067     for (uint32_t i = 0; i < CBRAreaPool.size(); i++) {
00068         delete CBRAreaPool[i];
00069     }
00070     CBRAreaPool.clear();
00071 }
00072 
00073 
00074 void CoordBasedRouting::parseSource(const char* areaCoordinateSource)
00075 {
00076     cXMLElement* rootElement = ev.getXMLDocument(areaCoordinateSource);
00077 
00078     xmlDimensions = atoi(rootElement->getAttribute("dimensions"));
00079 
00080     for (cXMLElement *area = rootElement->getFirstChildWithTag("area"); area;
00081          area = area->getNextSiblingWithTag("area") ) {
00082         CBRArea* tmpArea = new CBRArea(xmlDimensions);
00083         for (cXMLElement *areavals = area->getFirstChild(); areavals;
00084              areavals = areavals->getNextSibling() ) {
00085             std::string tagname = std::string(areavals->getTagName());
00086             if (tagname == "min") {
00087                 uint8_t currentdim = atoi(areavals->getAttribute("dimension"));
00088                 double value = atof(areavals->getNodeValue());
00089                 tmpArea->min[currentdim] = value;
00090             }
00091 
00092             else if (tagname == "max") {
00093                 uint8_t currentdim = atoi(areavals->getAttribute("dimension"));
00094                 double value = atof(areavals->getNodeValue());
00095                 tmpArea->max[currentdim] = value;
00096             }
00097 
00098             else if (tagname == "prefix") {
00099                 tmpArea->prefix = areavals->getNodeValue();
00100             }
00101         }
00102         CBRAreaPool.push_back(tmpArea);
00103     }
00104 
00105     EV << "[CoordBasedRouting::parseSource()]" << endl;
00106     EV << "    " << CBRAreaPool.size() << " prefix areas detected." << endl;
00107 }
00108 
00109 OverlayKey CoordBasedRouting::getNodeId(const std::vector<double>& coords,
00110                                         uint8_t bpd, uint8_t length) const
00111 {
00112     std::string prefix = getPrefix(coords);
00113 
00114     // if no prefix is returned, something is seriously wrong with the Area Source XML
00115     if (prefix == NOPREFIX) {
00116         opp_error("[CoordBasedRouting::getNodeId()]: "
00117                   "No prefix for given coords found. "
00118                   "Check your area source file!");
00119     }
00120     std::string idString;
00121 
00122     // ID string:
00123     //                          |- endPos
00124     // 00000000000000011010101010000000000000
00125     // |_startLength_||_prefix_||_endLength_|
00126     // |__  .. beforeEnd ..  __|
00127     // |___        .... length ....      ___|
00128     //
00129     // startLength and endLength bits are set to 0 at first, then
00130     // randomized
00131     // Prefix will be cut off if stop digit is exceeded
00132 
00133     uint8_t startLength = (bpd * cbrStartAtDigit < length) ?
00134                           (bpd * cbrStartAtDigit) : length;
00135     uint8_t beforeEnd = (startLength + prefix.length() < length) ?
00136                         (startLength + prefix.length()) : length;
00137     uint8_t endPos = (bpd * cbrStopAtDigit < beforeEnd) ?
00138                      (bpd * cbrStopAtDigit) : beforeEnd;
00139     uint8_t endLength = length - endPos;
00140 
00141     // Fill startLength bits with zeros
00142     for (uint8_t i = 0; i < startLength; i++)
00143         idString += "0";
00144 
00145     // Now add prefix and cut it off if stop digit and/or key length is exceeded
00146     idString += prefix;
00147     if (endPos < idString.length())
00148         idString.erase(endPos);
00149     if (length < idString.length())
00150         idString.erase(length);
00151 
00152     // fill endLength bits with zeros, thus key length is reached
00153     for (uint8_t i = 0; i < endLength; i++)
00154         idString += "0";
00155 
00156     OverlayKey nodeId(idString, 2);
00157 
00158     // randomize non-prefix (zero filled) parts
00159     if (startLength > 0)
00160         nodeId = nodeId.randomPrefix(length - startLength);
00161     if (endLength > 0)
00162         nodeId = nodeId.randomSuffix(endLength);
00163 
00164     EV << "[CoordBasedRouting::getNodeId()]\n"
00165        <<"    calculated id: " << nodeId << endl;
00166     return nodeId;
00167 }
00168 
00169 std::string CoordBasedRouting::getPrefix(const std::vector<double>& coords) const
00170 {
00171     bool areaFound = false;
00172     uint32_t iter = 0;
00173 
00174     // Return no prefix if coords dimensions don't match area file dimensions
00175     if (!checkDimensions(coords.size()))
00176         return NOPREFIX;
00177 
00178     while (!areaFound && iter < CBRAreaPool.size()) {
00179         CBRArea* thisArea = CBRAreaPool[iter];
00180 
00181         // assume we're in the correct area unless any dimension tells us otherwise
00182         areaFound = true;
00183         for (uint8_t thisdim = 0; thisdim < coords.size(); thisdim++) {
00184             if (coords[thisdim] < thisArea->min[thisdim] ||
00185                 coords[thisdim] > thisArea->max[thisdim]) {
00186                 areaFound = false;
00187                 break;
00188             }
00189         }
00190 
00191         // no borders are broken in any dimension -> we're in the correct area,
00192         // return corresponding prefix
00193         if (areaFound) {
00194             EV << "[CoordBasedRouting::getPrefix()]\n"
00195                <<"    calculated prefix: " << thisArea->prefix << endl;
00196             return thisArea->prefix;
00197         }
00198         iter++;
00199     }
00200 
00201     // no corresponding prefix found, XML file broken?
00202     EV << "[CoordBasedRouting::getPrefix()]\n"
00203        << "    No corresponding prefix found, check your area source file!"
00204        << endl;
00205 
00206     return NOPREFIX;
00207 }
00208 
00209 double CoordBasedRouting::getEuclidianDistanceByKeyAndCoords(const OverlayKey& destKey,
00210                                                              const std::vector<double>& coords,
00211                                                              uint8_t bpd) const
00212 {
00213     assert(!destKey.isUnspecified());
00214     uint32_t iter = 0;
00215     while (iter < CBRAreaPool.size()) {
00216         CBRArea* thisArea = CBRAreaPool[iter];
00217 
00218         // Take CBR Start/Stop Digit into account
00219         uint8_t startbit = bpd * cbrStartAtDigit;
00220         uint8_t length = (bpd * cbrStopAtDigit - bpd * cbrStartAtDigit <
00221                 (uint8_t)thisArea->prefix.length() - bpd * cbrStartAtDigit)
00222                 ? (bpd * cbrStopAtDigit - bpd * cbrStartAtDigit)
00223                 : (thisArea->prefix.length() - bpd * cbrStartAtDigit);
00224         if (destKey.toString(2).substr(startbit, length) ==
00225             thisArea->prefix.substr(startbit, length)) {
00226             // Get euclidian distance of area center to given coords
00227             std::vector<double> areaCenterCoords;
00228             areaCenterCoords.resize(getXmlDimensions());
00229             double sumofsquares = 0;
00230             for (uint8_t dim = 0; dim < getXmlDimensions(); dim++) {
00231                 areaCenterCoords[dim] =
00232                     (thisArea->min[dim] + thisArea->max[dim]) / 2;
00233                 sumofsquares += pow((coords[dim] - areaCenterCoords[dim]), 2);
00234             }
00235             return sqrt(sumofsquares);
00236         }
00237         iter++;
00238     }
00239     // while loop finished -> no area with needed prefix found
00240     // (this shouldn't happen!)
00241     throw cRuntimeError("[CoordBasedRouting::"
00242                         "getEuclidianDistanceByKeyAndCoords]: "
00243                         "No prefix for search key found!");
00244     return -1;
00245 }
00246 
00247 
00248 bool CoordBasedRouting::checkDimensions(uint8_t dims) const
00249 {
00250     if (dims == xmlDimensions) {
00251         return true;
00252     } else {
00253         EV << "[CoordBasedRouting::checkDimensions()]" << endl;
00254         EV << "    ERROR: Given coordinate dimensions do not match dimensions "
00255               "in the used area source file. Mapping results will be wrong."
00256            << endl;
00257         return false;
00258     }
00259 }
00260 
00261 
00265 CBRArea::CBRArea(uint8_t dim)
00266 {
00267     min.reserve(dim);
00268     max.reserve(dim);
00269 }
00270 
Generated on Wed May 26 16:21:14 2010 for OverSim by  doxygen 1.6.3