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
00075 void EnergyModel::DecrRcvEnergy(double rcvtime, double P_rcv)
00076 {
00077 double dEng = P_rcv * rcvtime;
00078 if (energy_ <= dEng)
00079 energy_ = 0.0;
00080 else
00081 energy_ = energy_ - dEng;
00082 if (energy_ <= 0.0)
00083 God::instance()->ComputeRoute();
00084 }
00085
00086 void EnergyModel::DecrIdleEnergy(double idletime, double P_idle)
00087 {
00088 double dEng = P_idle * idletime;
00089 if (energy_ <= dEng)
00090 energy_ = 0.0;
00091 else
00092 energy_ = energy_ - dEng;
00093 if (energy_ <= 0.0)
00094 God::instance()->ComputeRoute();
00095 }
00096
00097
00098
00099 void EnergyModel::start_powersaving()
00100 {
00101 snh_ = new SoftNeighborHandler(this);
00102 snh_->start();
00103
00104 afe_ = new AdaptiveFidelityEntity(this);
00105 afe_->start();
00106
00107 state_ = EnergyModel::POWERSAVING;
00108 state_start_time_ = Scheduler::instance().clock();
00109 }
00110
00111 void EnergyModel::set_node_sleep(int status)
00112 {
00113 Tcl& tcl=Tcl::instance();
00114
00115
00116
00117
00118
00119 if (status) {
00120 last_time_gosleep = Scheduler::instance().clock();
00121
00122
00123 sleep_mode_ = status;
00124 if (node_->exist_namchan())
00125 tcl.evalf("%s add-mark m1 blue hexagon",node_->name());
00126 } else {
00127 sleep_mode_ = status;
00128 if (node_->exist_namchan())
00129 tcl.evalf("%s delete-mark m1", node_->name());
00130
00131
00132 if (last_time_gosleep) {
00133 total_sleeptime_ += Scheduler::instance().clock() -
00134 last_time_gosleep;
00135 last_time_gosleep = 0;
00136 }
00137 }
00138 }
00139
00140 void EnergyModel::set_node_state(int state)
00141 {
00142 switch (state_) {
00143 case POWERSAVING:
00144 case WAITING:
00145 state_ = state;
00146 state_start_time_ = Scheduler::instance().clock();
00147 break;
00148 case INROUTE:
00149 if (state == POWERSAVING) {
00150 state_ = state;
00151 } else if (state == INROUTE) {
00152
00153
00154 state_start_time_= Scheduler::instance().clock();
00155 }
00156 break;
00157 default:
00158 printf("Wrong state, quit...\n");
00159 abort();
00160 }
00161 }
00162
00163 void EnergyModel::add_neighbor(u_int32_t nodeid)
00164 {
00165 neighbor_list_item *np;
00166 np = neighbor_list.head;
00167 for (; np; np = np->next) {
00168 if (np->id == nodeid) {
00169 np->ttl = maxttl_;
00170 break;
00171 }
00172 }
00173 if (!np) {
00174 np = new neighbor_list_item;
00175 np->id = nodeid;
00176 np->ttl = maxttl_;
00177 np->next = neighbor_list.head;
00178 neighbor_list.head = np;
00179 neighbor_list.neighbor_cnt_++;
00180 }
00181 }
00182
00183 void EnergyModel::scan_neighbor()
00184 {
00185 neighbor_list_item *np, *lp;
00186 if (neighbor_list.neighbor_cnt_ > 0) {
00187 lp = neighbor_list.head;
00188 np = lp->next;
00189 for (; np; np = np->next) {
00190 np->ttl--;
00191 if (np->ttl <= 0){
00192 lp->next = np->next;
00193 delete np;
00194 np = lp;
00195 neighbor_list.neighbor_cnt_--;
00196 }
00197 lp = np;
00198 }
00199
00200 np = neighbor_list.head;
00201 np->ttl--;
00202 if (np->ttl <= 0) {
00203 neighbor_list.head = np->next;
00204 delete np;
00205 neighbor_list.neighbor_cnt_--;
00206 }
00207 }
00208 }
00209
00210
00211 void SoftNeighborHandler::start()
00212 {
00213 Scheduler::instance().schedule(this, &intr, CHECKFREQ);
00214 }
00215
00216 void SoftNeighborHandler::handle(Event *)
00217 {
00218 Scheduler &s = Scheduler::instance();
00219 nid_->scan_neighbor();
00220 s.schedule(this, &intr, CHECKFREQ);
00221 }
00222
00223 void AdaptiveFidelityEntity::start()
00224 {
00225 sleep_time_ = 2;
00226 sleep_seed_ = 2;
00227 idle_time_ = 10;
00228 nid_->set_node_sleep(0);
00229 Scheduler::instance().schedule(this, &intr,
00230 Random::uniform(0, idle_time_));
00231 }
00232
00233 void AdaptiveFidelityEntity::handle(Event *)
00234 {
00235 Scheduler &s = Scheduler::instance();
00236 int node_state = nid_->state();
00237 switch (node_state) {
00238 case EnergyModel::POWERSAVING:
00239 if (nid_->sleep()) {
00240
00241 nid_->set_node_sleep(0);
00242 adapt_it();
00243 s.schedule(this, &intr, idle_time_);
00244 } else {
00245
00246 nid_->set_node_sleep(1);
00247 adapt_it();
00248 s.schedule(this, &intr, sleep_time_);
00249 }
00250 break;
00251 case EnergyModel::INROUTE:
00252
00253 if (s.clock()-(nid_->state_start_time()) <
00254 nid_->max_inroute_time()) {
00255 s.schedule(this, &intr, idle_time_);
00256 } else {
00257 nid_->set_node_state(EnergyModel::POWERSAVING);
00258 adapt_it();
00259 nid_->set_node_sleep(1);
00260 s.schedule(this, &intr, sleep_time_);
00261 }
00262 break;
00263 case EnergyModel::WAITING:
00264
00265 if (s.clock()-(nid_->state_start_time()) < MAX_WAITING_TIME) {
00266 s.schedule(this, &intr, idle_time_);
00267 } else {
00268 nid_->set_node_state(EnergyModel::POWERSAVING);
00269 adapt_it();
00270 nid_->set_node_sleep(1);
00271 s.schedule(this, &intr, sleep_time_);
00272 }
00273 break;
00274 default:
00275 fprintf(stderr, "Illegal Node State!");
00276 abort();
00277 }
00278 }
00279
00280 void AdaptiveFidelityEntity::adapt_it()
00281 {
00282 float delay;
00283
00284 if (nid_->adaptivefidelity()) {
00285 int neighbors = nid_->getneighbors();
00286 if (!neighbors)
00287 neighbors = 1;
00288 delay = sleep_seed_ * Random::uniform(1,neighbors);
00289 set_sleeptime(delay);
00290 }
00291 }
00292