OverSim
ChordFingerTable.cc
Go to the documentation of this file.
1 //
2 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 //
18 
24 #include <cfloat>
25 
26 #include "hashWatch.h"
27 
28 #include "Chord.h"
29 #include "ChordSuccessorList.h"
30 #include "ChordFingerTable.h"
31 
32 namespace oversim {
33 
34 using namespace std;
35 
37 
39 {
40  // because of IPAddressResolver, we need to wait until interfaces
41  // are registered, address auto-assignment takes place etc.
42  if(stage != MIN_STAGE_OVERLAY)
43  return;
44 
45  maxSize = 0;
46 
47  WATCH_DEQUE(fingerTable);
48 }
49 
51 {
52  error("this module doesn't handle messages, it runs only in initialize()");
53 }
54 
55 void ChordFingerTable::initializeTable(uint32_t size, const NodeHandle& owner,
56  Chord* overlay)
57 {
58  maxSize = size;
59  this->overlay = overlay;
60  fingerTable.clear();
61 }
62 
64 {
65  return maxSize;
66 }
67 
68 void ChordFingerTable::setFinger(uint32_t pos, const NodeHandle& node,
69  Successors const* sucNodes)
70 {
71  if (pos >= maxSize) {
72  throw new cRuntimeError("ChordFingerTable::setFinger(): "
73  "Index out of bound");
74  }
75 
76  uint32_t p = maxSize - pos - 1;
77  Successors tempSuccessors;
78 
79  while (fingerTable.size() <= p) {
80  fingerTable.push_back(FingerEntry(NodeHandle::UNSPECIFIED_NODE,
81  tempSuccessors));
82  }
83 
84  if (sucNodes != NULL) {
85  fingerTable[p] = FingerEntry(node, *sucNodes);
86  } else {
87  fingerTable[p] = FingerEntry(node, tempSuccessors);
88  }
89 }
90 
91 void ChordFingerTable::setFinger(uint32_t pos, const Successors& nodes)
92 {
93  setFinger(pos, nodes.begin()->second, &nodes);
94 }
95 
96 bool ChordFingerTable::updateFinger(uint32_t pos, const NodeHandle& node,
97  simtime_t rtt)
98 {
99  if (rtt < 0)
100  return false;
101 
102  if (pos >= maxSize) {
103  throw new cRuntimeError("ChordFingerTable::updateFinger(): "
104  "Index out of bound");
105  }
106 
107  uint32_t p = maxSize - pos - 1;
108 
109  while (fingerTable.size() <= p) {
110  Successors tempSuccessors;
111  fingerTable.push_back(FingerEntry(NodeHandle::UNSPECIFIED_NODE,
112  tempSuccessors));
113  }
114 
115  Successors::iterator it;
116  for (it = fingerTable[p].second.begin(); it != fingerTable[p].second.end();
117  it++) {
118 
119  if (it->second == node) {
120  break;
121  }
122  }
123 
124  if (it == fingerTable[p].second.end()) {
125  return false;
126  }
127 
128  fingerTable[p].second.erase(it);
129  fingerTable[p].second.insert(std::make_pair(rtt, node));
130 
131  return true;
132 }
133 
135 {
136  bool ret = false;
137  for (int p = fingerTable.size() - 1; p >= 0; p--) {
138  if (!fingerTable[p].first.isUnspecified() &&
139  failed == fingerTable[p].first) {
140  fingerTable[p].first = NodeHandle::UNSPECIFIED_NODE;
141  ret = true;
142  }
143  for (std::multimap<simtime_t, NodeHandle>::iterator it =
144  fingerTable[p].second.begin(); it != fingerTable[p].second.end();
145  ++it) {
146  if (failed == it->second) {
147  fingerTable[p].second.erase(it);
148  break;
149  }
150  }
151  }
152 
153  return ret;
154 }
155 
157 {
158  if (pos >= maxSize) {
159  throw new cRuntimeError("ChordFingerTable::removeFinger(): "
160  "Index out of bound");
161  }
162 
163  uint32_t p = maxSize - pos - 1;
164 
165  if (p >= fingerTable.size()) {
166  return;
167  } else if (p == (fingerTable.size() - 1)) {
168  fingerTable.pop_back();
169  } else {
170  Successors tempSuccessors;
171  fingerTable[p] = FingerEntry(NodeHandle::UNSPECIFIED_NODE,
172  tempSuccessors);
173  }
174 }
175 
177 {
178  if (pos >= maxSize) {
179  throw new cRuntimeError("ChordFingerTable::getFinger(): "
180  "Index out of bound");
181  }
182 
183  uint32_t p = maxSize - pos - 1;
184 
185  if (p >= fingerTable.size()) {
186  return overlay->successorList->getSuccessor();
187  }
188  while (fingerTable[p].first.isUnspecified() &&
189  (p < (fingerTable.size() - 1))) {
190  ++p;
191  }
192  if (fingerTable[p].first.isUnspecified())
193  return overlay->successorList->getSuccessor();
194  return fingerTable[p].first;
195 }
196 
198 {
199  if (pos >= maxSize) {
200  throw new cRuntimeError("ChordFingerTable::getFinger(): "
201  "Index out of bound");
202  }
203 
204  NodeVector* nextHop = new NodeVector();
205  uint32_t p = maxSize - pos - 1;
206 
207  if (p < fingerTable.size()) {
208  for (Successors::const_iterator it = fingerTable[p].second.begin();
209  it != fingerTable[p].second.end(); it++) {
210 
211  if(!key.isBetweenLR(fingerTable[p].first.getKey(), it->second.getKey())) {
212  nextHop->push_back(it->second);
213  }
214  }
215  } else {
216  nextHop->push_back(overlay->successorList->getSuccessor());
217  return nextHop;
218  }
219 
220  if (nextHop->size() == 0) {
221  if (fingerTable[p].first.isUnspecified()) {
222  //TODO use other finger
223  nextHop->push_back(overlay->successorList->getSuccessor());
224  } else {
225  nextHop->push_back(fingerTable[p].first);
226  }
227  }
228 
229  return nextHop;
230 }
231 
232 
233 }; //namespace
234 
235 using namespace oversim;
236 
237 std::ostream& operator<<(std::ostream& os, const Successors& suc)
238 {
239  for (Successors::const_iterator i = suc.begin(); i != suc.end(); i++) {
240  if (i != suc.begin()) {
241  os << endl;
242  }
243 
244  os << i->second;
245 
246  if (i->first == -1) {
247  continue;
248  } else if (i->first == MAXTIME) {
249  os << "; RTT: --- ";
250  } else {
251  os << "; RTT: " << i->first;
252  }
253  }
254 
255  return os;
256 }
257 
258 std::ostream& operator<<(std::ostream& os, const FingerEntry& entry)
259 {
260  if (entry.second.size() > 0) {
261  os << "[ " << entry.first << " ]\n" << entry.second;
262  } else {
263  os << entry.first;
264  }
265 
266  return os;
267 }