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 #include "simlpy/interpreter_defs.h"
00032 #include "simlpy/interpreter_hooks.h"
00033
00034 #include <iostream>
00035
00036 #include "WrapLink.h"
00037 #include "WrapNode.h"
00038 #include "parsers.h"
00039 #include "BundleEvent.h"
00040 #include "LinkUpDownEvent.h"
00041 #include "AliasLink.h"
00042 #include "Tracer.h"
00043
00044 #include "simlpy/Clock.h"
00045 #include "simlpy/SimulationException.h"
00046
00047 WrapLink::WrapLink() :
00048 m_source( 0 ),
00049 m_destination( 0 ),
00050 m_link( this )
00051 {
00052
00053 }
00054
00055 WrapLink::~WrapLink()
00056 {
00057 }
00058
00059 Entity*
00060 WrapLink::create() const
00061 {
00062 return new WrapLink;
00063 }
00064
00065 void
00066 WrapLink::configure( const ArgList& args )
00067 {
00068 unsigned int nargs = args.size();
00069 if ( 0 == nargs )
00070 {
00071 std::cerr << "no configuration options were passed" << std::endl;
00072 throw SimulationException( __FILE__ , __LINE__ );
00073 }
00074 std::string command = parse_string(args[0]);
00075 if ( "latency" == command )
00076 {
00077 if ( 2 != nargs )
00078 {
00079 std::cerr << "config('latency',dt) requires exactly 2 arguments ("
00080 << nargs << " given)"
00081 << std::endl;
00082 throw SimulationException( __FILE__ , __LINE__ );
00083 }
00084 double lat = parse_double( args[1] );
00085 m_link.setLatency(lat);
00086 }
00087 else if ( "bandwidth" == command )
00088 {
00089 if ( 2 != nargs )
00090 {
00091 std::cerr << "config('bandwidth',bw) requires exactly 2 arguments ("
00092 << nargs << " given)"
00093 << std::endl;
00094 throw SimulationException( __FILE__ , __LINE__ );
00095 }
00096 double dbw = parse_double(args[1]);
00097
00098 unsigned long int bw = (unsigned long int)(1000000 * dbw);
00099 m_link.setBandwidth(bw);
00100 }
00101 else if ( "connect" == command )
00102 {
00103 if ( 3 != nargs )
00104 {
00105 std::cerr
00106 << "config('connect',src,dest) requires exactly 3 arguments ("
00107 << nargs << " given)"
00108 << std::endl;
00109 throw SimulationException( __FILE__ , __LINE__ );
00110 }
00111 WrapNode* src = parse_node( args[1] );
00112 WrapNode* dest = parse_node( args[2] );
00113 if ( ( 0 == src ) || ( 0 == dest ) )
00114 {
00115 std::cerr << "The second and third arguments of "
00116 << "config('connect',src,dest) must be nodes"
00117 << std::endl;
00118 throw SimulationException( __FILE__ , __LINE__ );
00119 }
00120 m_source = src;
00121 m_destination = dest;
00122 if ( 0 != m_source )
00123 {
00124 m_source->addLink( new AliasLink( &m_link ) );
00125 }
00126 }
00127 else
00128 {
00129 std::cerr << "Unrecognized configuration for config(): "
00130 << command
00131 << std::endl;
00132 throw SimulationException( __FILE__ , __LINE__ );
00133 }
00134
00135
00136 GlobalTracer* gt = GlobalTracer::instance();
00137 if ( 0 != gt )
00138 {
00139 gt->link(*this);
00140 }
00141 }
00142
00143 void
00144 WrapLink::emit( const ArgList& args )
00145 {
00146 unsigned int nargs = args.size();
00147 if ( nargs < 2 )
00148 {
00149 std::cerr << "emit() requires at least 2 arguments ("
00150 << nargs << " given)"
00151 << std::endl;
00152 throw SimulationException( __FILE__ , __LINE__ );
00153 }
00154
00155 Time t = parse_time(args[0]);
00156
00157 std::string command = parse_string(args[1]);
00158 if ( "up" == command )
00159 {
00160 Clock::schedule( new LinkUpDownEvent(this,this,t,true) );
00161 }
00162 else if ( "down" == command )
00163 {
00164 Clock::schedule( new LinkUpDownEvent(this,this,t,false) );
00165 }
00166 else
00167 {
00168 std::cerr << "Unrecognized event: " << command << std::endl;
00169 throw SimulationException( __FILE__ , __LINE__ );
00170 }
00171 }
00172
00173 InterpreterItem
00174 WrapLink::get( const ArgList& args )
00175 {
00176 unsigned int nargs = args.size();
00177 if ( 0 == nargs )
00178 {
00179 std::cerr << "No attribute specified" << std::endl;
00180 throw SimulationException( __FILE__ , __LINE__ );
00181 }
00182
00183 std::string attr = parse_string(args[0]);
00184
00185 if ( "bandwidth" == attr )
00186 {
00187 double bw = 0.000001 * m_link.bandwidth();
00188 return construct_double( bw );
00189 }
00190 if ( "latency" == attr )
00191 {
00192 const Time& lat = m_link.latency();
00193 double t = lat.tv.tv_sec + 1.0 * lat.tv.tv_usec / Time::MILLION;
00194 return construct_double( t );
00195 }
00196 if ( "state" == attr )
00197 {
00198 return construct_string( m_link.up()? "up" : "down" );
00199 }
00200
00201
00202 return Entity::get(args);
00203 }
00204
00205 bool
00206 WrapLink::handler( BundleEvent& event )
00207 {
00208 if ( m_link.up() )
00209 {
00210 if ( event.sentAt() >= m_link.upSince() )
00211 {
00212 Clock::schedule( new BundleEvent( this,
00213 m_destination,
00214 event.sentAt(),
00215 Clock::time(),
00216 event.pData() ) );
00217 return true;
00218 }
00219 }
00220
00221 if ( 0 == m_source )
00222 {
00223 throw SimulationException( __FILE__ , __LINE__ );
00224 }
00225 m_source->drop( event.pData(), DTN::LinkFailureDrop::inst );
00226 return false;
00227 }
00228
00229 bool
00230 WrapLink::handler( LinkAvailEvent& event )
00231 {
00232 m_link.setBusy(false);
00233 if ( ! m_link.up() ) return true;
00234 if ( 0 != m_source )
00235 {
00236 m_source->forwardOn( m_link );
00237 }
00238 return true;
00239 }
00240
00241 bool
00242 WrapLink::handler( LinkUpDownEvent& event )
00243 {
00244 if ( event.state() )
00245 {
00246 m_link.setUp();
00247 }
00248 else
00249 {
00250 m_link.setDown();
00251 }
00252
00253 GlobalTracer* gt = GlobalTracer::instance();
00254 if ( 0 != gt )
00255 {
00256 gt->link(*this);
00257 }
00258
00259 return true;
00260 }