00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00033 #include "ParetoChurn.h"
00034
00035 #include "GlobalStatisticsAccess.h"
00036 #include "Churn_m.h"
00037 #include "GlobalStatistics.h"
00038 #include <UnderlayConfigurator.h>
00039 #include <algorithm>
00040 #include <deque>
00041
00042 Define_Module(ParetoChurn);
00043
00044 void ParetoChurn::initializeChurn()
00045 {
00046 Enter_Method_Silent();
00047
00048 initialMean = par("initPhaseCreationInterval");
00049 initialDeviation = initialMean / 3;
00050 lifetimeMean = par("lifetimeMean");
00051 deadtimeMean = par("deadtimeMean");
00052
00053 WATCH(lifetimeMean);
00054 WATCH(deadtimeMean);
00055
00056 lastCreatetime = 0;
00057 lastDeletetime = 0;
00058
00059 globalStatistics = GlobalStatisticsAccess().get();
00060
00061 double initFinishedTime = initialMean * targetOverlayTerminalNum;
00062
00063
00064
00065
00066
00067 int liveNodes = 0;
00068 double sum_l_i = 0;
00069 std::deque<node_stat> node_stats;
00070
00071 for (int i = 0; liveNodes < (int)par("targetOverlayTerminalNum"); i++) {
00072
00073 double nodeLifetimeMean = individualMeanTime(lifetimeMean);
00074 globalStatistics->recordOutVector("ParetoChurn: Node individual "
00075 "mean lifetime", nodeLifetimeMean);
00076 double nodeDeadtimeMean = individualMeanTime(deadtimeMean);
00077 globalStatistics->recordOutVector("ParetoChurn: Node individual "
00078 "mean deadtime", nodeDeadtimeMean);
00079 sum_l_i += 1.0/(nodeLifetimeMean + nodeDeadtimeMean);
00080 node_stat nodeStat;
00081 nodeStat.l = nodeLifetimeMean;
00082 nodeStat.d = nodeDeadtimeMean;
00083 double nodeAvailability = nodeLifetimeMean/(nodeLifetimeMean
00084 + nodeDeadtimeMean);
00085
00086 globalStatistics->recordOutVector("Node availability", nodeAvailability);
00087
00088 nodeStat.alive = uniform(0, 1) < nodeAvailability;
00089 if (nodeStat.alive) {
00090 liveNodes++;
00091 }
00092 node_stats.push_back( nodeStat );
00093 }
00094
00095
00096
00097
00098 double mean_life = 0;
00099 int numNodes = node_stats.size();
00100 for( int i = 0; i < numNodes; ++i ){
00101 node_stat& stat = node_stats[i];
00102 mean_life += stat.l/( (stat.l + stat.d) * sum_l_i );
00103 }
00104 double stretch = lifetimeMean/mean_life;
00105 liveNodes = 0;
00106
00107
00108 for( int i = 0; i < numNodes; ++i ){
00109 node_stat& stat = node_stats.front();
00110 stat.l *= stretch;
00111 stat.d *= stretch;
00112
00113 if( stat.alive ){
00114 double scheduleTime = truncnormal(initialMean*liveNodes, initialDeviation);
00115 scheduleCreateNodeAt(scheduleTime, initFinishedTime - scheduleTime
00116 + residualLifetime(stat.l),
00117 stat.l, stat.d);
00118 liveNodes++;
00119 } else {
00120 scheduleCreateNodeAt(initFinishedTime
00121 + residualLifetime(stat.d),
00122 individualLifetime(stat.l),
00123 stat.l, stat.d);
00124 }
00125 node_stats.pop_front();
00126 }
00127
00128 initFinishedTimer = new cMessage("initFinishTimer");
00129 scheduleAt(initFinishedTime, initFinishedTimer);
00130 }
00131
00132 void ParetoChurn::handleMessage(cMessage* msg)
00133 {
00134 if (!msg->isSelfMessage()) {
00135 delete msg;
00136 return;
00137 }
00138
00139
00140 if (msg == initFinishedTimer) {
00141 underlayConfigurator->initFinished();
00142 cancelEvent(initFinishedTimer);
00143 delete initFinishedTimer;
00144 initFinishedTimer = NULL;
00145
00146 return;
00147 }
00148
00149 ParetoChurnMessage* churnMsg = check_and_cast<ParetoChurnMessage*>(msg);
00150
00151 if (churnMsg->getCreateNode() == true) {
00152 createNode(churnMsg->getLifetime(), churnMsg->getMeanLifetime(),
00153 churnMsg->getMeanDeadtime(), false);
00154 } else {
00155 deleteNode(churnMsg->getAddr(), churnMsg->getMeanLifetime(),
00156 churnMsg->getMeanDeadtime());
00157 }
00158
00159 delete msg;
00160 }
00161
00162 void ParetoChurn::createNode(double lifetime, double meanLifetime,
00163 double meanDeadtime, bool initialize)
00164 {
00165 ParetoChurnMessage* churnMsg = new ParetoChurnMessage("DeleteNode");
00166 TransportAddress* ta = underlayConfigurator->createNode(type, initialize);
00167 churnMsg->setAddr(*ta);
00168 delete ta;
00169 churnMsg->setCreateNode(false);
00170 churnMsg->setMeanLifetime(meanLifetime);
00171 churnMsg->setMeanDeadtime(meanDeadtime);
00172 scheduleAt(std::max(simTime(), simTime() + lifetime
00173 - underlayConfigurator->getGracefulLeaveDelay()), churnMsg);
00174
00175 RECORD_STATS(globalStatistics->recordOutVector("ParetoChurn: Session Time",
00176 lifetime));
00177
00178 RECORD_STATS(globalStatistics->recordOutVector("ParetoChurn: "
00179 "Time between creates", SIMTIME_DBL(simTime() - lastCreatetime)));
00180
00181 lastCreatetime = simTime();
00182 }
00183
00184 void ParetoChurn::deleteNode(TransportAddress& addr, double meanLifetime,
00185 double meanDeadtime)
00186 {
00187
00188 underlayConfigurator->preKillNode(NodeType(), &addr);
00189
00190 RECORD_STATS(globalStatistics->recordOutVector("ParetoChurn: "
00191 "Time between deletes", SIMTIME_DBL(simTime() - lastDeletetime)));
00192 lastDeletetime = simTime();
00193 scheduleCreateNodeAt(SIMTIME_DBL(simTime()+individualLifetime(meanDeadtime)),
00194 individualLifetime(meanLifetime), meanLifetime,
00195 meanDeadtime);
00196 }
00197
00198 void ParetoChurn::scheduleCreateNodeAt(double creationTime, double lifetime,
00199 double meanLifetime, double meanDeadtime)
00200 {
00201 ParetoChurnMessage* churnMsg = new ParetoChurnMessage("CreateNode");
00202 churnMsg->setCreateNode(true);
00203 churnMsg->setLifetime(lifetime);
00204 churnMsg->setMeanLifetime(meanLifetime);
00205 churnMsg->setMeanDeadtime(meanDeadtime);
00206 scheduleAt(creationTime, churnMsg);
00207 }
00208
00209 double ParetoChurn::betaByMean(double mean, double alpha)
00210 {
00211 return 1/(mean*(alpha -1));
00212 }
00213
00214 double ParetoChurn::shiftedPareto(double a, double b, int rng)
00215 {
00216
00217
00218 return (pareto_shifted(a, b, 0, rng)/b - 1) / b;
00219 }
00220
00221 double ParetoChurn::individualMeanTime(double mean)
00222 {
00223
00224 return shiftedPareto(3, betaByMean(mean));
00225 }
00226
00227 double ParetoChurn::individualLifetime(double mean)
00228 {
00229 return shiftedPareto(3, betaByMean(mean));
00230 }
00231
00232
00233
00234
00235 double ParetoChurn::residualLifetime(double mean)
00236 {
00237 return shiftedPareto(2, betaByMean(mean));
00238 }
00239
00240 void ParetoChurn::updateDisplayString()
00241 {
00242 char buf[80];
00243 sprintf(buf, "pareto churn");
00244 getDisplayString().setTagArg("t", 0, buf);
00245 }
00246
00247 ParetoChurn::~ParetoChurn() {
00248
00249 cancelAndDelete(initFinishedTimer);
00250 }