SimLink.cc

00001 // Copyright 2008 Michael Marsh, University of Maryland.
00002 //
00003 // This file is part of pydtn.
00004 //
00005 // pydtn is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // pydtn is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with pydtn.  If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 // The views and conclusions contained in the software and documentation
00019 // are those of the authors and should not be interpreted as representing
00020 // official policies, either expressed or implied, of the University
00021 // of Maryland.
00022 //
00023 // pydtn extends and embeds the Python interpreter, which is
00024 // Copyright 2001-2006 Python Software Foundation, All Rights Reserved,
00025 // and is released under the PSF License Agreement.
00026 //
00027 // RANLUX random number generation uses the Boost library,
00028 // Copyright 1994-2006 by various authors (details in individual files),
00029 // which is released under the Boost Software License, Version 1.0.
00030 
00031 #include "simlpy/interpreter_defs.h"
00032 #include "simlpy/interpreter_hooks.h"
00033 
00034 #include <iostream>
00035 #include <math.h>
00036 
00037 #include "Globals.h"
00038 #include "SimLink.h"
00039 #include "WrapLink.h"
00040 #include "WrapNode.h"
00041 #include "BundleEvent.h"
00042 #include "LinkAvailEvent.h"
00043 
00044 #include "simlpy/Clock.h"
00045 #include "simlpy/SimulationException.h"
00046 
00047 SimLink::SimLink( WrapLink* owner, bool up ) :
00048    m_owner( owner ),
00049    m_latency( Globals::latency() ),
00050    m_bandwidth( Globals::bandwidth() ),
00051    m_busy( false ),
00052    m_up( up )
00053 {
00054    if ( m_up )
00055    {
00056       m_upSince = Clock::time();
00057    }
00058 }
00059 
00060 SimLink::~SimLink()
00061 {
00062    // DO NOT DELETE m_owner!
00063 }
00064 
00065 void
00066 SimLink::send( DTN::Bundle* b )
00067 {
00068    if ( 0 == b ) return;
00069    if ( ! m_up )
00070    {
00071       // This shouldn't happen, so we can silently drop the bundle.
00072       return;
00073    }
00074 
00075    if ( m_busy )
00076    {
00077       // This shouldn't happen, so we can silently drop the bundle.
00078       std::cerr << "We shouldn't be here!" << std::endl;
00079       return;
00080    }
00081 
00082    // the time at which the first byte of the bundle reaches the other end
00083    Time arrival_time = Clock::time() + m_latency;
00084 
00085    // did this bundle overtake an earlier one?
00086    if ( arrival_time < m_earliestDelivery )
00087    {
00088       arrival_time = m_earliestDelivery;
00089    }
00090 
00091    // number of bytes in the bundle
00092    unsigned int length = b->size();
00093 
00094    // the amount of time to fully inject the bundle into the link
00095    unsigned long int injection_time =
00096       (unsigned long int)( ceil( 1.0 * 1000000 * 8 * length / m_bandwidth ) );
00097    //                                    us/s   b/B    B          b/s
00098 
00099    // the time at which the last byte of the bundle reaches the other end
00100    Time t = arrival_time + Time(0,injection_time);
00101 
00102    // the time at which the bundle has been completely injected
00103    Time t0 = t - m_latency;
00104 
00105    // preserve non-interfering FIFO order
00106    m_earliestDelivery = t;
00107 
00108    BundleEvent* evt = new BundleEvent( m_owner, m_owner, Clock::time(), t, b );
00109    if ( 0 == evt )
00110    {
00111       std::cerr << "Could not allocate a new BundleEvent" << std::endl;
00112       throw SimulationException( __FILE__ , __LINE__ );
00113    }
00114 
00115    m_busy = true;
00116    m_busyUntil = t0;
00117    Clock::schedule( evt );
00118    Clock::schedule( new LinkAvailEvent( m_owner, m_owner, t0 ) );
00119 }
00120 
00121 const DTN::ByteString&
00122 SimLink::remoteAddr() const
00123 {
00124    if ( 0 == m_owner )
00125    {
00126       throw SimulationException( __FILE__ , __LINE__ );
00127    }
00128    if ( 0 == m_owner->destination() )
00129    {
00130       throw SimulationException( __FILE__ , __LINE__ );
00131    }
00132    return m_owner->destination()->addr();
00133 }
00134 
00135 void
00136 SimLink::setLatency( double lat )
00137 {
00138    unsigned long int s = ::floor(lat);
00139    unsigned long int us = Time::MILLION * ( lat - s );
00140    m_latency = Time(s,us);
00141 }
00142 
00143 void
00144 SimLink::setUp()
00145 {
00146    if ( ! m_up )
00147    {
00148       m_upSince = Clock::time();
00149    }
00150    m_up = true;
00151    if ( 0 == m_owner ) return;
00152    // If we're busy, then there's a LinkAvailEvent coming at some point.
00153    if ( ! m_busy )
00154    {
00155       m_owner->source()->forwardOn( *this );
00156    }
00157 }
00158 
00159 void
00160 SimLink::setDown()
00161 {
00162    m_up = false;
00163 }

Generated on Mon Mar 24 11:15:46 2008 for Pydtn Simulator by  doxygen 1.5.4