ChordFingerTable.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00039
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
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 };
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 }