00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <stdarg.h>
00040 #include <float.h>
00041
00042 #include "random.h"
00043 #include "energy-model.h"
00044 #include "mobilenode.h"
00045 #include "god.h"
00046
00047 static class EnergyModelClass : public TclClass
00048 {
00049 public:
00050 EnergyModelClass ():TclClass ("EnergyModel") {}
00051 TclObject *create (int argc, const char *const *argv) {
00052 if (argc == 8) {
00053 MobileNode *n=(MobileNode*)TclObject::lookup(argv[4]);
00054 return (new EnergyModel(n, atof(argv[5]),
00055 atof(argv[6]), atof(argv[7])));
00056 } else {
00057 Tcl::instance().add_error("Wrong arguments to ErrorModel");
00058 return 0;
00059 }
00060 }
00061 } class_energy_model;
00062
00063 void EnergyModel::DecrTxEnergy(double txtime, double P_tx)
00064 {
00065 double dEng = P_tx * txtime;
00066 if (energy_ <= dEng)
00067 energy_ = 0.0;
00068 else
00069 energy_ = energy_ - dEng;
00070 if (energy_ <= 0.0)
00071 God::instance()->ComputeRoute();
00072
00073
00074 et_=et_+dEng;
00075
00076 }
00077
00078
00079 void EnergyModel::DecrRcvEnergy(double rcvtime, double P_rcv)
00080 {
00081 double dEng = P_rcv * rcvtime;
00082 if (energy_ <= dEng)
00083 energy_ = 0.0;
00084 else
00085 energy_ = energy_ - dEng;
00086 if (energy_ <= 0.0)
00087 God::instance()->ComputeRoute();
00088
00089
00090 er_=er_+dEng;
00091
00092 }
00093
00094 void EnergyModel::DecrIdleEnergy(double idletime, double P_idle)
00095 {
00096 double dEng = P_idle * idletime;
00097 if (energy_ <= dEng)
00098 energy_ = 0.0;
00099 else
00100 energy_ = energy_ - dEng;
00101 if (energy_ <= 0.0)
00102 God::instance()->ComputeRoute();
00103
00104
00105 ei_=ei_+dEng;
00106
00107 }
00108
00109
00110 void EnergyModel::DecrSleepEnergy(double sleeptime, double P_sleep)
00111 {
00112 double dEng = P_sleep * sleeptime;
00113 if (energy_ <= dEng)
00114 energy_ = 0.0;
00115 else
00116 energy_ = energy_ - dEng;
00117 if (energy_ <= 0.0)
00118 God::instance()->ComputeRoute();
00119
00120
00121 es_=es_+dEng;
00122 }
00123
00124 void EnergyModel::DecrTransitionEnergy(double transitiontime, double P_transition)
00125 {
00126 double dEng = P_transition * transitiontime;
00127 if (energy_ <= dEng)
00128 energy_ = 0.0;
00129 else
00130 energy_ = energy_ - dEng;
00131 if (energy_ <= 0.0)
00132 God::instance()->ComputeRoute();
00133 }
00134
00135
00136
00137
00138 void EnergyModel::start_powersaving()
00139 {
00140 snh_ = new SoftNeighborHandler(this);
00141 snh_->start();
00142
00143 afe_ = new AdaptiveFidelityEntity(this);
00144 afe_->start();
00145
00146 state_ = EnergyModel::POWERSAVING;
00147 state_start_time_ = Scheduler::instance().clock();
00148 }
00149
00150 void EnergyModel::set_node_sleep(int status)
00151 {
00152 Tcl& tcl=Tcl::instance();
00153
00154
00155
00156
00157
00158 if (status) {
00159 last_time_gosleep = Scheduler::instance().clock();
00160
00161
00162 sleep_mode_ = status;
00163 if (node_->exist_namchan())
00164 tcl.evalf("%s add-mark m1 blue hexagon",node_->name());
00165 } else {
00166 sleep_mode_ = status;
00167 if (node_->exist_namchan())
00168 tcl.evalf("%s delete-mark m1", node_->name());
00169
00170
00171 if (last_time_gosleep) {
00172 total_sleeptime_ += Scheduler::instance().clock() -
00173 last_time_gosleep;
00174 last_time_gosleep = 0;
00175 }
00176 }
00177 }
00178
00179 void EnergyModel::set_node_state(int state)
00180 {
00181 switch (state_) {
00182 case POWERSAVING:
00183 case WAITING:
00184 state_ = state;
00185 state_start_time_ = Scheduler::instance().clock();
00186 break;
00187 case INROUTE:
00188 if (state == POWERSAVING) {
00189 state_ = state;
00190 } else if (state == INROUTE) {
00191
00192
00193 state_start_time_= Scheduler::instance().clock();
00194 }
00195 break;
00196 default:
00197 printf("Wrong state, quit...\n");
00198 abort();
00199 }
00200 }
00201
00202 void EnergyModel::add_neighbor(u_int32_t nodeid)
00203 {
00204 neighbor_list_item *np;
00205 np = neighbor_list.head;
00206 for (; np; np = np->next) {
00207 if (np->id == nodeid) {
00208 np->ttl = maxttl_;
00209 break;
00210 }
00211 }
00212 if (!np) {
00213 np = new neighbor_list_item;
00214 np->id = nodeid;
00215 np->ttl = maxttl_;
00216 np->next = neighbor_list.head;
00217 neighbor_list.head = np;
00218 neighbor_list.neighbor_cnt_++;
00219 }
00220 }
00221
00222 void EnergyModel::scan_neighbor()
00223 {
00224 neighbor_list_item *np, *lp;
00225 if (neighbor_list.neighbor_cnt_ > 0) {
00226 lp = neighbor_list.head;
00227 np = lp->next;
00228 for (; np; np = np->next) {
00229 np->ttl--;
00230 if (np->ttl <= 0){
00231 lp->next = np->next;
00232 delete np;
00233 np = lp;
00234 neighbor_list.neighbor_cnt_--;
00235 }
00236 lp = np;
00237 }
00238
00239 np = neighbor_list.head;
00240 np->ttl--;
00241 if (np->ttl <= 0) {
00242 neighbor_list.head = np->next;
00243 delete np;
00244 neighbor_list.neighbor_cnt_--;
00245 }
00246 }
00247 }
00248
00249
00250 void SoftNeighborHandler::start()
00251 {
00252 Scheduler::instance().schedule(this, &intr, CHECKFREQ);
00253 }
00254
00255 void SoftNeighborHandler::handle(Event *)
00256 {
00257 Scheduler &s = Scheduler::instance();
00258 nid_->scan_neighbor();
00259 s.schedule(this, &intr, CHECKFREQ);
00260 }
00261
00262 void AdaptiveFidelityEntity::start()
00263 {
00264 sleep_time_ = 2;
00265 sleep_seed_ = 2;
00266 idle_time_ = 10;
00267 nid_->set_node_sleep(0);
00268 Scheduler::instance().schedule(this, &intr,
00269 Random::uniform(0, idle_time_));
00270 }
00271
00272 void AdaptiveFidelityEntity::handle(Event *)
00273 {
00274 Scheduler &s = Scheduler::instance();
00275 int node_state = nid_->state();
00276 switch (node_state) {
00277 case EnergyModel::POWERSAVING:
00278 if (nid_->sleep()) {
00279
00280 nid_->set_node_sleep(0);
00281 adapt_it();
00282 s.schedule(this, &intr, idle_time_);
00283 } else {
00284
00285 nid_->set_node_sleep(1);
00286 adapt_it();
00287 s.schedule(this, &intr, sleep_time_);
00288 }
00289 break;
00290 case EnergyModel::INROUTE:
00291
00292 if (s.clock()-(nid_->state_start_time()) <
00293 nid_->max_inroute_time()) {
00294 s.schedule(this, &intr, idle_time_);
00295 } else {
00296 nid_->set_node_state(EnergyModel::POWERSAVING);
00297 adapt_it();
00298 nid_->set_node_sleep(1);
00299 s.schedule(this, &intr, sleep_time_);
00300 }
00301 break;
00302 case EnergyModel::WAITING:
00303
00304 if (s.clock()-(nid_->state_start_time()) < MAX_WAITING_TIME) {
00305 s.schedule(this, &intr, idle_time_);
00306 } else {
00307 nid_->set_node_state(EnergyModel::POWERSAVING);
00308 adapt_it();
00309 nid_->set_node_sleep(1);
00310 s.schedule(this, &intr, sleep_time_);
00311 }
00312 break;
00313 default:
00314 fprintf(stderr, "Illegal Node State!");
00315 abort();
00316 }
00317 }
00318
00319 void AdaptiveFidelityEntity::adapt_it()
00320 {
00321 float delay;
00322
00323 if (nid_->adaptivefidelity()) {
00324 int neighbors = nid_->getneighbors();
00325 if (!neighbors)
00326 neighbors = 1;
00327 delay = sleep_seed_ * Random::uniform(1,neighbors);
00328 set_sleeptime(delay);
00329 }
00330 }
00331