OverSim
DiscoveryMode.cc
Go to the documentation of this file.
1 /*
2  * DiscoveryMode.cc
3  *
4  * Created on: Sep 27, 2010
5  * Author: heep
6  */
7 
8 #include <BasePastry.h>
9 
10 #include <DiscoveryMode_m.h>
11 
12 #include "DiscoveryMode.h"
13 
14 
15 
16 void DiscoveryMode::init(NeighborCache* neighborCache)
17 {
18  this->neighborCache = neighborCache;
19  nearNodeRtt = MAXTIME;
20  nearNodeImproved = false;
21  firstRtt = SIMTIME_DBL(MAXTIME);
22  improvement = 0;
23  maxIndex = -1;
24  finished = false;
25 
26  basePastry = NULL;//dynamic_cast<BasePastry*>(neighborCache->overlay);
27 
28  numCloseNodes = neighborCache->par("discoveryModeNumCloseNodes");
29  numSpreadedNodes = neighborCache->par("discoveryModeNumSpreadedNodes");
30  maxSteps = neighborCache->par("discoveryModeMaxSteps");
31  spreadedSteps = (int)neighborCache->par("discoveryModeSpreadedSteps");
32 }
33 
34 void DiscoveryMode::start(const TransportAddress& bootstrapNode)
35 {
36  step = 0;
37  queries = 0;
38 
39  if (bootstrapNode.isUnspecified()) {
40  stop();
41  } else {
42 
43  EV << "[DiscoveryMode::start() @ " << neighborCache->getThisNode().getIp()
44  << " (" << neighborCache->getThisNode().getKey().toString(16) << ")]\n"
45  << " starting Discovery Mode (first asking "
46  << bootstrapNode.getIp() << " for "
47  << (basePastry ? "leafSet" : "spreaded nodes)") << ")"
48  << endl;
49 
50  // 1. ask bootstrap node for other nodes and his coordinates
51  DiscoveryCall* discoveryCall = new DiscoveryCall("DiscoveryCall");
52  discoveryCall->setNodesType(SPREADED_NODES);
53  discoveryCall->setNumberOfNodes(numSpreadedNodes);
54 
56  bootstrapNode, discoveryCall, NULL,
57  NO_OVERLAY_ROUTING, -1, 0, -1, this);
58  ++queries;
59 
60  // 2. probe other nodes and optionally ask them for more nodes
61  // (try to get close as well as distant nodes)
62  // sendReadyMessage();
63  }
64 }
65 
67 {
68  improvement = firstRtt - SIMTIME_DBL(nearNodeRtt);
69 
70  EV << "[DiscoveryMode::stop() @ " << neighborCache->getThisNode().getIp()
71  << " (" << neighborCache->getThisNode().getKey().toString(16) << ")]\n"
72  << " stopping Discovery mode with "
73  << nearNode.getIp() << " as closest node, which is "
74  << improvement << " s closer (RTT) than the original bootstrap node."
75  << endl;
76 
77  neighborCache->getParentModule()->bubble("Discovery Mode finished!");
78  finished = true;
79 
80  //RECORD_STATS(
82  neighborCache->globalStatistics->addStdDev("NeighborCache: Discovery Mode Improvement",
83  getImprovement());
84  if (dynamic_cast<const Vivaldi*>(&(neighborCache->getNcsAccess()))) {
85  neighborCache->globalStatistics->addStdDev("NeighborCache: Vivaldi-Error after Discovery Mode",
86  static_cast<const Vivaldi&>(neighborCache->getNcsAccess()).getOwnError());
87  }
88  }
89  //);
90  const SVivaldi& svivaldi = dynamic_cast<const SVivaldi&>(neighborCache->getNcsAccess());
91  std::cout << "step: " << step << ", e: " << svivaldi.getOwnError() << ", l: " << svivaldi.getLoss() << std::endl;
92 
93  const_cast<SVivaldi&>(svivaldi).stopAdaptation();
95 }
96 
98 {
99  if (dynamic_cast<DiscoveryCall*>(msg)) {
100  DiscoveryCall* discoveryCall = static_cast<DiscoveryCall*>(msg);
101 
102  std::vector<TransportAddress>* temp;
103 
104  DiscoveryResponse* discoveryResponse =
105  new DiscoveryResponse("DiscoveryResponse");
106 
107  if (discoveryCall->getNodesType() == SPREADED_NODES) {
108  if (basePastry) {
109  temp = basePastry->getLeafSet();
110  } else {
111  temp = neighborCache->getSpreadedNodes(discoveryCall->getNumberOfNodes());
112  }
113  } else {
114  if (basePastry) {
115  if (discoveryCall->getIndex() == 0) {
116  discoveryResponse->setMaxIndex(basePastry->getRTLastRow() - 1);
117  }
118  int16_t rowIndex = basePastry->getRTLastRow()
119  - discoveryCall->getIndex();
120  if (rowIndex < 1) rowIndex = 1;
121  temp = basePastry->getRTRow(rowIndex);
122  } else {
123  temp = neighborCache->getClosestNodes(discoveryCall->getNumberOfNodes());
124  }
125  }
126 
127  discoveryResponse->setNodesArraySize(temp->size());
128  for (uint16_t i = 0; i < temp->size(); ++i) {
129  discoveryResponse->setNodes(i, (*temp)[i]);
130  }
131  delete temp;
132 
133  neighborCache->sendRpcResponse(discoveryCall, discoveryResponse);
134 
135  return true;
136  }
137  return false;
138 }
139 
141  cPolymorphic* context,
142  int rpcId, simtime_t rtt)
143 {
144  if (dynamic_cast<DiscoveryResponse*>(msg)) {
145  DiscoveryResponse* discoveryResponse =
146  static_cast<DiscoveryResponse*>(msg);
147 
148  --queries;
149 
150  EV << "[DiscoveryMode::handleRpcResponse() @ " << neighborCache->getThisNode().getIp()
151  << " (" << neighborCache->getThisNode().getKey().toString(16) << ")]\n"
152  << " receiving DiscoveryResponse from "
153  << msg->getSrcNode().getIp()
154  << " (step = " << (int)step << ")"
155  << endl;
156 
157 
158  if (nearNodeRtt > rtt) {
159  if (nearNode.isUnspecified() || nearNode != discoveryResponse->getSrcNode()) {
160  EV << " , which is now the closest known neighbor."
161  << endl;
162  nearNodeImproved = true;
163  nearNode = discoveryResponse->getSrcNode();
164  }
165  nearNodeRtt = rtt;
166 
167  if (step == 0) firstRtt = SIMTIME_DBL(rtt);
168  }
169 
170  const TransportAddress* node;
171 
172  for (uint16_t i = 0; i < discoveryResponse->getNodesArraySize(); i++) {
173  node = &(discoveryResponse->getNodes(i));
174  // unspecified nodes not considered
175  if (!(node->isUnspecified() || *node == neighborCache->getThisNode())) {
177  -1, this, NULL);
178  if (temp == Prox::PROX_TIMEOUT
179  || temp == Prox::PROX_UNKNOWN
180  || temp == Prox::PROX_WAITING) {
181  ++queries;
182  } else if (nearNodeRtt > temp.proximity) {
183  nearNode = *node;
184  nearNodeRtt = temp.proximity;
185  nearNodeImproved = true;
186  }
187 
188 
189  }
190  }
191  int16_t ind = discoveryResponse->getMaxIndex();
192  if (ind != -1) maxIndex = ind;
193 
194  EV << "[DiscoveryMode::handleRpcResponse() @ " << neighborCache->getThisNode().getIp()
195  << " (" << neighborCache->getThisNode().getKey().toString(16) << ")]\n"
196  << " maxIndex of " << msg->getSrcNode().getIp()
197  << " is " << (int)maxIndex << "."
198  << endl;
199 
200  //if (--spreadedSteps >= 0) {
202  //} else {
203  //sendNewRequest(CLOSE_NODES, numCloseNodes);
204  //}
205  }
206 }
207 
209  const TransportAddress& dest,
210  cPolymorphic* context, int rpcId,
211  const OverlayKey& destKey)
212 {
213  --queries;
214 }
215 
216 
217 void DiscoveryMode::proxCallback(const TransportAddress& node, int rpcId,
218  cPolymorphic *contextPointer, Prox prox)
219 {
220  --queries;
221 
222  if (prox != Prox::PROX_TIMEOUT && prox != Prox::PROX_SELF &&
223  nearNodeRtt > prox.proximity) {
224  nearNode = node;
225  nearNodeRtt = prox.proximity;
226  nearNodeImproved = true;
227  }
228 
230  //sendNewRequest(CLOSE_NODES, numCloseNodes);
231 }
232 
234 {
235  const SVivaldi& svivaldi = dynamic_cast<const SVivaldi&>(neighborCache->getNcsAccess());
236 
237  if (queries == 0) {
238  if (/*(step < maxSteps || maxSteps == -1) && */svivaldi.getOwnError() > 0.02 && svivaldi.getLoss() < 0.95
239  /*(nearNodeImproved || step <= maxIndex)*/) {
240  //std::cout << (int)step << " " << (int)maxIndex << std::endl;
241  ++step;
242  nearNodeImproved = false;
243 
244  DiscoveryCall* discoveryCall1 = new DiscoveryCall("DiscoveryCall");
245  DiscoveryCall* discoveryCall2 = new DiscoveryCall("DiscoveryCall");
246  discoveryCall1->setNodesType(CLOSE_NODES);
247  discoveryCall2->setNodesType(SPREADED_NODES);
248  discoveryCall1->setNumberOfNodes(numCloseNodes);
249  discoveryCall2->setNumberOfNodes(numSpreadedNodes);
250  //discoveryCall->setIndex(step - 1);
251 
252  //std::vector<TransportAddress>* temp =
253  // neighborCache->getClosestNodes(1);
254  //if (temp->size() < 1) {
255  // throw cRuntimeError("no node for discovery available");
256  //}
257 
258  EV << "[DiscoveryMode::sendNewRequest() @ " << neighborCache->getThisNode().getIp()
259  << " (" << neighborCache->getThisNode().getKey().toString(16) << ")]\n"
260  << " sending new DiscoveryCall to "
261  << nearNode.getIp() << " for "
262  << (basePastry ? "routing table row" : "close nodes")
263  << ". (step = " << (int)step << ")"
264  << endl;
265 
267  nearNode/*(*temp)[0]*/, discoveryCall1, NULL,
268  NO_OVERLAY_ROUTING, -1, 0, -1,
269  this);
270 
272  nearNode/*(*temp)[0]*/, discoveryCall2, NULL,
273  NO_OVERLAY_ROUTING, -1, 0, -1,
274  this);
275  ++queries;
276  //delete temp;
277  } else {
278  stop();
279  }
280  }
281 }
282 
283 //DISCOVERY receive response
284 /*if (state == DISCOVERY) {
285  EV << "[Pastry::pingResponse() @ " << thisNode.getAddress()
286  << " (" << thisNode.getKey().toString(16) << ")]\n"
287  << " Pong (or Ping-context from NeighborCache) received (from "
288  << pingResponse->getSrcNode().getAddress() << ") in DISCOVERY mode"
289  << endl;
290 
291  if (nearNodeRtt > rtt) {
292  nearNode = pingResponse->getSrcNode();
293  nearNodeRtt = rtt;
294  nearNodeImproved = true;
295  }
296  }
297 
298  if (state == DISCOVERY) {
299  uint32_t lsSize = lmsg->getLeafSetArraySize();
300  const NodeHandle* node;
301  pingedNodes = 0;
302 
303  for (uint32_t i = 0; i < lsSize; i++) {
304  node = &(lmsg->getLeafSet(i));
305  // unspecified nodes not considered
306  if ( !(node->isUnspecified()) ) {
307  pingNode(*node, discoveryTimeoutAmount, 0,
308  NULL, "PING received leafs for nearest node",
309  NULL, -1, UDP_TRANSPORT);//TODO
310  pingedNodes++;
311  }
312  }
313 
314  EV << "[Pastry::handleUDPMessage() @ " << thisNode.getAddress()
315  << " (" << thisNode.getKey().toString(16) << ")]\n"
316  << " received leafset, waiting for pings"
317  << endl;
318 
319  if (discoveryTimeout->isScheduled()) cancelEvent(discoveryTimeout);
320  scheduleAt(simTime() + discoveryTimeoutAmount, discoveryTimeout);
321  delete lmsg;
322  }
323 
324 
325  if (state == DISCOVERY) {
326  uint32_t nodesPerRow = rtmsg->getRoutingTableArraySize();
327  const NodeHandle* node;
328  if (depth == -1) {
329  depth = rtmsg->getRow();
330  }
331  pingedNodes = 0;
332  nearNodeImproved = false;
333 
334  if (depth > 0) {
335  for (uint32_t i = 0; i < nodesPerRow; i++) {
336  node = &(rtmsg->getRoutingTable(i));
337  // unspecified nodes not considered
338  if ( !(node->isUnspecified()) ) {
339  // we look for best connection here, so Timeout is short and there are no retries
340  pingNode(*node, discoveryTimeoutAmount, 0, NULL,
341  "PING received routing table for nearest node",
342  NULL, -1, UDP_TRANSPORT); //TODO
343  pingedNodes++;
344  }
345  }
346  depth--;
347  }
348  */