SimContact.cc

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2004-2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
00015  */
00016 
00017 #include "SimContact.h"
00018 #include "Simulator.h"
00019 
00020 namespace dtnsim {
00021 
00022 
00023 SimContact::SimContact (int id, Node* src, Node* dst, 
00024 double bw, double latency, bool isup, int pup, int pdown) 
00025     : Logger ("/sim/simcontact") 
00026 {
00027     id_ = id;
00028     src_ = src;
00029     dst_ = dst;
00030     bw_ = bw;
00031     latency_ = latency;
00032     up_ = pup; // length of up period
00033     down_ = pdown; // length of down period
00034     ASSERT(bw > 0 && latency >= 0) ;
00035     
00036     log_info("C[%d]: CONTACT CREATED: N[%d]->N[%d]\n",
00037              id_,src_->id(),dst_->id());
00038     
00039     chewing_event_ = NULL;
00040     future_updown_event_ = NULL;
00041     // start state
00042     if (isup) {
00043         open_contact(false);
00044     } else  {
00045         close_contact(false);
00046     }
00047 }
00048 
00049 
00050 // This defines behavior of starting of eating of a message
00051 void 
00052 SimContact::chew_message(Message* msg) 
00053 {
00054     log_info("C[%d]: CH_ST id:%d src:%d size:%f",
00055         id(), msg->id(), msg->src(),msg->size());
00056     
00057     ASSERT(state_ == OPEN);
00058     state_ = BUSY;
00059     double tr = msg->size()/bw_;
00060     ASSERT(tr >0);
00061     double tmp = Simulator::time() + tr ; 
00062     Event_chew_fin* e2 =
00063         new Event_chew_fin(tmp,this,msg,Simulator::time());
00064     chewing_event_ = e2;
00065     log_debug("ChSt-ChEvent[%d]: event:%p",id(), e2);
00066     Simulator::post(e2);
00067 }
00068 
00069 
00070 bool
00071 SimContact::is_open() 
00072 {
00073     return state_ == OPEN ;
00074 }
00075 
00076 
00077 
00078 void 
00079 SimContact::chewing_complete(double size, Message* msg) 
00080 {
00081     log_info("C[%d]: CH_CMP id:%d src:%d size:%2f trans:%2f", 
00082              id(),msg->id(),msg->src(),msg->size(),size);
00083     if (size > msg->size()) {
00084         log_debug(" transmit size exceeding message (%d) size (%2f > %2f) "
00085                   ,msg->id(),size,msg->size());
00086         size = msg->size();
00087     }
00088     
00089     if (state_ == CLOSE)
00090         log_err("C[%d]: closed when chewing complete",id());
00091     
00092     if (size != 0) {
00093         Event_message_received* e = 
00094             new Event_message_received(Simulator::time()+latency_,dst_,size,this,msg);
00095         Simulator::post(e);
00096     }
00097     src_->chewing_complete(this,size,msg);
00098 }
00099 
00100 
00101 void 
00102 remove_event(Event* e) 
00103 {
00104     if (e != NULL)
00105         Simulator::remove_event(e);
00106 }
00107 
00108 
00109 void
00110 SimContact::open_contact(bool forever) 
00111 {
00112     remove_event(future_updown_event_);
00113     future_updown_event_ = NULL;
00114     
00115     // if it is a regular scheduled open, schedule a future down event
00116     if (!forever) {
00117         // schedule a link down event
00118         double next = up_;
00119         Event_contact_down* e = new Event_contact_down(Simulator::time()+next,this);
00120         Simulator::post(e);
00121         future_updown_event_ = e;
00122     }
00123     
00124     state_ = OPEN;
00125     // send message to src, telling about that the contact is available
00126     src_->open_contact(this);
00127 }
00128 
00129 
00130 
00131 void 
00132 SimContact::close_contact(bool forever) 
00133 {
00134 
00135     remove_event(future_updown_event_);
00136     future_updown_event_ = NULL;
00137     if (!forever) {
00138         // schedule a link up event
00139         double next = down_;
00140         Event_contact_up* e = new Event_contact_up(Simulator::time()+next,this);
00141         Simulator::post(e);
00142         future_updown_event_ = e;
00143     }
00144     
00145     
00146     if (state_ == BUSY) {
00147         log_info("C[%d]: state busy while closing",
00148                  id());
00149         // fragmentation has to occur
00150         ASSERT(chewing_event_ != NULL);
00151         // schedule partial chewing complete
00152         double transmit_time = Simulator::time() - chewing_event_->chew_starttime_;
00153         double size_transmit = (bw_*transmit_time);
00154         
00155         if (!SimContact::ALLOW_FRAGMENTATION) {
00156             size_transmit = 0;
00157         } else if (SimContact::DISALLOW_FRACTIONAL_TRANSFERS) {
00158             size_transmit = (int)(size_transmit);
00159         }
00160         chewing_complete(size_transmit,chewing_event_->msg_);
00161         remove_event(chewing_event_);
00162         chewing_event_ = NULL;
00163         
00164     }
00165     // tell the source that this contact is closed
00166     src_->close_contact(this);
00167     state_ = CLOSE;
00168 }
00169 
00170 
00171 void 
00172 SimContact::process(Event* e) 
00173 {
00174     switch (e->type()) {
00175     case CONTACT_UP : {
00176         log_info("C[%d]: N[%d]->N[%d] UP NOW",id(),src_->id(),dst_->id());
00177         open_contact(((Event_contact_up* )e)->forever_);
00178         break;
00179     }
00180     case CONTACT_DOWN : {
00181         log_info("C[%d]: N[%d]->N[%d] DOWN NOW",id(),src_->id(),dst_->id());
00182         close_contact(((Event_contact_down* )e)->forever_);
00183         break;
00184     }
00185     case CONTACT_CHEWING_FINISHED : {
00186         Event_chew_fin* e1 = (Event_chew_fin* )e;
00187         log_debug(
00188             "CChFin[%d] event:%p bundleid:%d chewing_event:%p start at:%f",
00189             id(),e,e1->msg_->id(),chewing_event_,e1->chew_starttime_);
00190         if (state_ == CLOSE)  {
00191             ASSERT(false);
00192             return;
00193         }
00194         state_ = OPEN;
00195         log_debug("chewing_event NULL:%p",chewing_event_);
00196             
00197         //we have to make sure that this event is set to NULL
00198         //before we call chewing_complete
00199         chewing_event_ = NULL;
00200         chewing_complete( e1->msg_->size(),e1->msg_);
00201         //src_->open_contact(this);
00202         break;
00203     } 
00204     default:
00205         PANIC("undefined event \n");
00206     }
00207 }
00208 
00209 
00210 
00211 
00212 
00213 
00214 } // namespace dtnsim

Generated on Thu Jun 7 12:54:29 2007 for DTN Reference Implementation by  doxygen 1.5.1