OverSim
ParetoChurn.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 
33 #include "ParetoChurn.h"
34 
35 #include "GlobalStatisticsAccess.h"
36 #include "Churn_m.h"
37 #include "GlobalStatistics.h"
38 #include <UnderlayConfigurator.h>
39 #include <algorithm>
40 #include <deque>
41 
43 
45 {
46  Enter_Method_Silent();
47 
48  initialMean = par("initPhaseCreationInterval");
50  lifetimeMean = par("lifetimeMean");
51  deadtimeMean = par("deadtimeMean");
52 
53  WATCH(lifetimeMean);
54  WATCH(deadtimeMean);
55 
56  lastCreatetime = 0;
57  lastDeletetime = 0;
58 
60 
61  double initFinishedTime = initialMean * targetOverlayTerminalNum;
62 
63  // try to create a stable equilibrium of nodes in init phase
64  //
65  // check for each node if he is present in initial state
66  // and roll individual mean life+dead times
67  int liveNodes = 0;
68  double sum_l_i = 0;
69  std::deque<node_stat> node_stats;
70 
71  for (int i = 0; liveNodes < (int)par("targetOverlayTerminalNum"); i++) {
72 
73  double nodeLifetimeMean = individualMeanTime(lifetimeMean);
74  globalStatistics->recordOutVector("ParetoChurn: Node individual "
75  "mean lifetime", nodeLifetimeMean);
76  double nodeDeadtimeMean = individualMeanTime(deadtimeMean);
77  globalStatistics->recordOutVector("ParetoChurn: Node individual "
78  "mean deadtime", nodeDeadtimeMean);
79  sum_l_i += 1.0/(nodeLifetimeMean + nodeDeadtimeMean);
80  node_stat nodeStat;
81  nodeStat.l = nodeLifetimeMean;
82  nodeStat.d = nodeDeadtimeMean;
83  double nodeAvailability = nodeLifetimeMean/(nodeLifetimeMean
84  + nodeDeadtimeMean);
85 
86  globalStatistics->recordOutVector("Node availability", nodeAvailability);
87 
88  nodeStat.alive = uniform(0, 1) < nodeAvailability;
89  if (nodeStat.alive) {
90  liveNodes++;
91  }
92  node_stats.push_back( nodeStat );
93  }
94 
95  // compute "stretch" factor to reach the configured average lifetime
96  // this is neccessary as "individual" lifetime mean has to be bigger than
97  // "global" lifetime mean, as short-lived nodes will factor in more often
98  double mean_life = 0;
99  int numNodes = node_stats.size();
100  for( int i = 0; i < numNodes; ++i ){
101  node_stat& stat = node_stats[i];
102  mean_life += stat.l/( (stat.l + stat.d) * sum_l_i );
103  }
104  double stretch = lifetimeMean/mean_life;
105  liveNodes = 0;
106 
107  // schedule creation for all (alive or dead) nodes
108  for( int i = 0; i < numNodes; ++i ){
109  node_stat& stat = node_stats.front();
110  stat.l *= stretch;
111  stat.d *= stretch;
112 
113  if( stat.alive ){
114  double scheduleTime = truncnormal(initialMean*liveNodes, initialDeviation);
115  scheduleCreateNodeAt(scheduleTime, initFinishedTime - scheduleTime
116  + residualLifetime(stat.l),
117  stat.l, stat.d);
118  liveNodes++;
119  } else {
120  scheduleCreateNodeAt(initFinishedTime
121  + residualLifetime(stat.d),
122  individualLifetime(stat.l),
123  stat.l, stat.d);
124  }
125  node_stats.pop_front();
126  }
127 
128  initFinishedTimer = new cMessage("initFinishTimer");
129  scheduleAt(initFinishedTime, initFinishedTimer);
130 }
131 
132 void ParetoChurn::handleMessage(cMessage* msg)
133 {
134  if (!msg->isSelfMessage()) {
135  delete msg;
136  return;
137  }
138 
139  // init phase finished
140  if (msg == initFinishedTimer) {
142  cancelEvent(initFinishedTimer);
143  delete initFinishedTimer;
144  initFinishedTimer = NULL;
145 
146  return;
147  }
148 
149  ParetoChurnMessage* churnMsg = check_and_cast<ParetoChurnMessage*>(msg);
150 
151  if (churnMsg->getCreateNode() == true) {
152  createNode(churnMsg->getLifetime(), churnMsg->getMeanLifetime(),
153  churnMsg->getMeanDeadtime(), false);
154  } else {
155  deleteNode(churnMsg->getAddr(), churnMsg->getMeanLifetime(),
156  churnMsg->getMeanDeadtime());
157  }
158 
159  delete msg;
160 }
161 
162 void ParetoChurn::createNode(double lifetime, double meanLifetime,
163  double meanDeadtime, bool initialize)
164 {
165  ParetoChurnMessage* churnMsg = new ParetoChurnMessage("DeleteNode");
167  churnMsg->setAddr(*ta);
168  delete ta;
169  churnMsg->setCreateNode(false);
170  churnMsg->setMeanLifetime(meanLifetime);
171  churnMsg->setMeanDeadtime(meanDeadtime);
172  scheduleAt(std::max(simTime(), simTime() + lifetime
174 
175  RECORD_STATS(globalStatistics->recordOutVector("ParetoChurn: Session Time",
176  lifetime));
177 
179  "Time between creates", SIMTIME_DBL(simTime() - lastCreatetime)));
180 
181  lastCreatetime = simTime();
182 }
183 
184 void ParetoChurn::deleteNode(TransportAddress& addr, double meanLifetime,
185  double meanDeadtime)
186 {
187  // Kill node
189 
191  "Time between deletes", SIMTIME_DBL(simTime() - lastDeletetime)));
192  lastDeletetime = simTime();
193  scheduleCreateNodeAt(SIMTIME_DBL(simTime()+individualLifetime(meanDeadtime)),
194  individualLifetime(meanLifetime), meanLifetime,
195  meanDeadtime);
196 }
197 
198 void ParetoChurn::scheduleCreateNodeAt(double creationTime, double lifetime,
199  double meanLifetime, double meanDeadtime)
200 {
201  ParetoChurnMessage* churnMsg = new ParetoChurnMessage("CreateNode");
202  churnMsg->setCreateNode(true);
203  churnMsg->setLifetime(lifetime);
204  churnMsg->setMeanLifetime(meanLifetime);
205  churnMsg->setMeanDeadtime(meanDeadtime);
206  scheduleAt(creationTime, churnMsg);
207 }
208 
209 double ParetoChurn::betaByMean(double mean, double alpha)
210 {
211  return 1/(mean*(alpha -1));
212 }
213 
214 double ParetoChurn::shiftedPareto(double a, double b, int rng)
215 {
216  // What OMNET calles "pareto_shifted" in reality is a gerneralized pareto,
217  // not a shifted pareto...
218  return (pareto_shifted(a, b, 0, rng)/b - 1) / b;
219 }
220 
222 {
223 // return shiftedPareto(3, betaByMean(mean*exp(1)));
224  return shiftedPareto(3, betaByMean(mean));
225 }
226 
228 {
229  return shiftedPareto(3, betaByMean(mean));
230 }
231 
232 // Residual lifetime is shifted pareto with the same beta, but
233 // decreased alpha i.e. beta calculation is based on "old alpha" (in
234 // this case 3), while "actual alpha" is 2
235 double ParetoChurn::residualLifetime(double mean)
236 {
237  return shiftedPareto(2, betaByMean(mean));
238 }
239 
241 {
242  char buf[80];
243  sprintf(buf, "pareto churn");
244  getDisplayString().setTagArg("t", 0, buf);
245 }
246 
248  // destroy self timer messages
249  cancelAndDelete(initFinishedTimer);
250 }