ChordFingerTable.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 
00024 #include <cfloat>
00025 
00026 #include "hashWatch.h"
00027 
00028 #include "Chord.h"
00029 #include "ChordSuccessorList.h"
00030 #include "ChordFingerTable.h"
00031 
00032 namespace oversim {
00033 
00034 Define_Module(ChordFingerTable);
00035 
00036 void ChordFingerTable::initialize(int stage)
00037 {
00038     // because of IPAddressResolver, we need to wait until interfaces
00039     // are registered, address auto-assignment takes place etc.
00040     if(stage != MIN_STAGE_OVERLAY)
00041         return;
00042 
00043     maxSize = 0;
00044 
00045     WATCH_DEQUE(fingerTable);
00046 }
00047 
00048 void ChordFingerTable::handleMessage(cMessage* msg)
00049 {
00050     error("this module doesn't handle messages, it runs only in initialize()");
00051 }
00052 
00053 void ChordFingerTable::initializeTable(uint32_t size, const NodeHandle& owner,
00054                                        Chord* overlay)
00055 {
00056     maxSize = size;
00057     this->overlay = overlay;
00058     fingerTable.clear();
00059 }
00060 
00061 uint32_t ChordFingerTable::getSize()
00062 {
00063     return maxSize;
00064 }
00065 
00066 void ChordFingerTable::setFinger(uint32_t pos, const NodeHandle& node,
00067                                  Successors const* sucNodes)
00068 {
00069     if (pos >= maxSize) {
00070         throw new cRuntimeError("ChordFingerTable::setFinger(): "
00071                                 "Index out of bound");
00072     }
00073 
00074     uint32_t p = maxSize - pos - 1;
00075     Successors tempSuccessors;
00076 
00077     while (fingerTable.size() <= p) {
00078         fingerTable.push_back(FingerEntry(NodeHandle::UNSPECIFIED_NODE,
00079                                           tempSuccessors));
00080     }
00081 
00082     if (sucNodes != NULL) {
00083         fingerTable[p] = FingerEntry(node, *sucNodes);
00084     } else {
00085         fingerTable[p] = FingerEntry(node, tempSuccessors);
00086     }
00087 }
00088 
00089 void ChordFingerTable::setFinger(uint32_t pos, const Successors& nodes)
00090 {
00091     setFinger(pos, nodes.begin()->second, &nodes);
00092 }
00093 
00094 bool ChordFingerTable::updateFinger(uint32_t pos, const NodeHandle& node,
00095                                     simtime_t rtt)
00096 {
00097     if (rtt < 0)
00098         return false;
00099 
00100     if (pos >= maxSize) {
00101          throw new cRuntimeError("ChordFingerTable::updateFinger(): "
00102                                  "Index out of bound");
00103      }
00104 
00105     uint32_t p = maxSize - pos - 1;
00106 
00107     while (fingerTable.size() <= p) {
00108         Successors tempSuccessors;
00109         fingerTable.push_back(FingerEntry(NodeHandle::UNSPECIFIED_NODE,
00110                                           tempSuccessors));
00111     }
00112 
00113     Successors::iterator it;
00114     for (it = fingerTable[p].second.begin(); it != fingerTable[p].second.end();
00115          it++) {
00116 
00117         if (it->second == node) {
00118             break;
00119         }
00120     }
00121 
00122     if (it == fingerTable[p].second.end()) {
00123         return false;
00124     }
00125 
00126     fingerTable[p].second.erase(it);
00127     fingerTable[p].second.insert(std::make_pair(rtt, node));
00128 
00129     return true;
00130 }
00131 
00132 bool ChordFingerTable::handleFailedNode(const TransportAddress& failed)
00133 {
00134     bool ret = false;
00135     for (int p = fingerTable.size() - 1; p >= 0; p--) {
00136         if (!fingerTable[p].first.isUnspecified() &&
00137             failed == fingerTable[p].first) {
00138             fingerTable[p].first = NodeHandle::UNSPECIFIED_NODE;
00139             ret = true;
00140         }
00141         for (std::multimap<simtime_t, NodeHandle>::iterator it =
00142              fingerTable[p].second.begin(); it != fingerTable[p].second.end();
00143              ++it) {
00144             if (failed == it->second) {
00145                 fingerTable[p].second.erase(it);
00146                 break;
00147             }
00148         }
00149     }
00150 
00151     return ret;
00152 }
00153 
00154 void ChordFingerTable::removeFinger(uint32_t pos)
00155 {
00156     if (pos >= maxSize) {
00157         throw new cRuntimeError("ChordFingerTable::removeFinger(): "
00158                                 "Index out of bound");
00159     }
00160 
00161     uint32_t p = maxSize - pos - 1;
00162 
00163     if (p >= fingerTable.size()) {
00164         return;
00165     } else if (p == (fingerTable.size() - 1)) {
00166         fingerTable.pop_back();
00167     } else {
00168         Successors tempSuccessors;
00169         fingerTable[p] = FingerEntry(NodeHandle::UNSPECIFIED_NODE,
00170                                      tempSuccessors);
00171     }
00172 }
00173 
00174 const NodeHandle& ChordFingerTable::getFinger(uint32_t pos)
00175 {
00176     if (pos >= maxSize) {
00177         throw new cRuntimeError("ChordFingerTable::getFinger(): "
00178                                 "Index out of bound");
00179     }
00180 
00181     uint32_t p = maxSize - pos - 1;
00182 
00183     if (p >= fingerTable.size()) {
00184         return overlay->successorList->getSuccessor();
00185     }
00186     while (fingerTable[p].first.isUnspecified() &&
00187             (p < (fingerTable.size() - 1))) {
00188         ++p;
00189     }
00190     if (fingerTable[p].first.isUnspecified())
00191         return overlay->successorList->getSuccessor();
00192     return fingerTable[p].first;
00193 }
00194 
00195 NodeVector* ChordFingerTable::getFinger(uint32_t pos, const OverlayKey& key)
00196 {
00197     if (pos >= maxSize) {
00198         throw new cRuntimeError("ChordFingerTable::getFinger(): "
00199                                 "Index out of bound");
00200     }
00201 
00202     NodeVector* nextHop = new NodeVector();
00203     uint32_t p = maxSize - pos - 1;
00204 
00205     if (p < fingerTable.size()) {
00206         for (Successors::const_iterator it = fingerTable[p].second.begin();
00207              it != fingerTable[p].second.end(); it++) {
00208 
00209             if(!key.isBetweenLR(fingerTable[p].first.getKey(), it->second.getKey())) {
00210                 nextHop->push_back(it->second);
00211             }
00212         }
00213     } else {
00214         nextHop->push_back(overlay->successorList->getSuccessor());
00215         return nextHop;
00216     }
00217 
00218     if (nextHop->size() == 0) {
00219         if (fingerTable[p].first.isUnspecified()) {
00220             //TODO use other finger
00221             nextHop->push_back(overlay->successorList->getSuccessor());
00222         } else {
00223             nextHop->push_back(fingerTable[p].first);
00224         }
00225     }
00226 
00227     return nextHop;
00228 }
00229 
00230 
00231 }; //namespace
00232 
00233 using namespace oversim;
00234 
00235 std::ostream& operator<<(std::ostream& os, const Successors& suc)
00236 {
00237     for (Successors::const_iterator i = suc.begin(); i != suc.end(); i++) {
00238         if (i != suc.begin()) {
00239             os << endl;
00240         }
00241 
00242         os << i->second;
00243 
00244         if (i->first == -1) {
00245             continue;
00246         } else if (i->first == MAXTIME) {
00247             os << "; RTT:  --- ";
00248         } else {
00249             os << "; RTT: " << i->first;
00250         }
00251     }
00252 
00253     return os;
00254 }
00255 
00256 std::ostream& operator<<(std::ostream& os, const FingerEntry& entry)
00257 {
00258     if (entry.second.size() > 0) {
00259         os << "[ " << entry.first << " ]\n" << entry.second;
00260     } else {
00261         os << entry.first;
00262     }
00263 
00264     return os;
00265 }
Generated on Wed May 26 16:21:13 2010 for OverSim by  doxygen 1.6.3