RealtimeScheduler Class Reference

#include <realtimescheduler.h>

Inheritance diagram for RealtimeScheduler:

TunOutScheduler List of all members.

Detailed Description

This class implements a event scheduler for omnet It makes the simulation run in realtime (i.e.

1 simsec == 1 sec) It must be subclassed; its subclasses must handle network traffic from/to the simulation


Public Types

typedef std::list< PacketBufferEntryPacketBuffer

Public Member Functions

 RealtimeScheduler ()
 Constructor.
virtual ~RealtimeScheduler ()
 Destructor.
virtual void startRun ()
 Called at the beginning of a simulation run.
virtual void endRun ()
 Called at the end of a simulation run.
virtual void executionResumed ()
 Recalculates "base time" from current wall clock time.
virtual void setInterfaceModule (cModule *module, cMessage *notificationMsg, PacketBuffer *buffer, int mtu, bool isApp=false)
 To be called from the module which wishes to receive data from the tun device.
virtual cMessage * getNextEvent ()
 Scheduler function -- it comes from cScheduler interface.
virtual void sendBytes (const char *buf, size_t numBytes, bool isApp=false)
 Send data to network.

Protected Member Functions

virtual int initializeNetwork ()=0
 Initialize the network.
virtual bool receiveWithTimeout (long usec)
 Waits for incoming data on the tun device.
virtual int receiveUntil (const timeval &targetTime)
 Tries to read data until the given time is up.

Protected Attributes

int netw_fd
cModule * module
cMessage * notificationMsg
PacketBufferpacketBuffer
size_t buffersize
int app_fd
cModule * appModule
cMessage * appNotificationMsg
PacketBufferappPacketBuffer
size_t appBuffersize
timeval baseTime

Classes

class  PacketBufferEntry


Member Typedef Documentation

typedef std::list<PacketBufferEntry> RealtimeScheduler::PacketBuffer


Constructor & Destructor Documentation

RealtimeScheduler::RealtimeScheduler (  ) 

Constructor.

00010                                      : cScheduler()
00011 {
00012     netw_fd = -1;
00013     app_fd = -1;
00014 }

RealtimeScheduler::~RealtimeScheduler (  )  [virtual]

Destructor.

00016 { }


Member Function Documentation

void RealtimeScheduler::endRun (  )  [virtual]

Called at the end of a simulation run.

00035 {}

void RealtimeScheduler::executionResumed (  )  [virtual]

Recalculates "base time" from current wall clock time.

00038 {
00039     gettimeofday(&baseTime, NULL);
00040     baseTime = timeval_substract(baseTime, sim->simTime());
00041 }

cMessage * RealtimeScheduler::getNextEvent (  )  [virtual]

Scheduler function -- it comes from cScheduler interface.

00158 {
00159     // assert that we've been configured
00160     if (!module)
00161         throw new cRuntimeError("RealtimeScheduler: setInterfaceModule() not called: it must be called from a module's initialize() function");
00162     if (app_fd >= 0 && !appModule)
00163         throw new cRuntimeError("RealtimeScheduler: setInterfaceModule() not called from application: it must be called from a module's initialize() function");
00164 
00165     // calculate target time
00166     timeval targetTime;
00167     cMessage *msg = sim->msgQueue.peekFirst();
00168     if (!msg) {
00169         // if there are no events, wait until something comes from outside
00170         // TBD: obey simtimelimit, cpu-time-limit
00171         targetTime.tv_sec = LONG_MAX;
00172         targetTime.tv_usec = 0;
00173     } else {
00174         // use time of next event
00175         simtime_t eventSimtime = msg->arrivalTime();
00176         targetTime = timeval_add(baseTime, eventSimtime);
00177     }
00178 
00179     // if needed, wait until that time arrives
00180     timeval curTime;
00181     gettimeofday(&curTime, NULL);
00182     if (timeval_greater(targetTime, curTime)) {
00183         int status = receiveUntil(targetTime);
00184         if (status == -1) {
00185             printf("WARNING: receiveUntil returned -1 (user interrupt)\n");
00186             return NULL; // interrupted by user
00187         } else if (status == 1) {
00188             msg = sim->msgQueue.peekFirst(); // received something
00189         }
00190     } else {
00191         //    printf("WARNING: Lagging behind realtime!\n");
00192         // we're behind -- customized versions of this class may
00193         // alert if we're too much behind, whatever that means
00194     }
00195     // ok, return the message
00196     return msg;
00197 }

virtual int RealtimeScheduler::initializeNetwork (  )  [protected, pure virtual]

Initialize the network.

Implemented in TunOutScheduler.

int RealtimeScheduler::receiveUntil ( const timeval &  targetTime  )  [protected, virtual]

Tries to read data until the given time is up.

Parameters:
targetTime stop waiting after this time is up
Returns:
1 if data is read, -1 if there is an error, 0 if no data is read
00131 {
00132     // if there's more than 200ms to wait, wait in 100ms chunks
00133     // in order to keep UI responsiveness by invoking ev.idle()
00134     timeval curTime;
00135     gettimeofday(&curTime, NULL);
00136     while (targetTime.tv_sec-curTime.tv_sec >=2 ||
00137             timeval_diff_usec(targetTime, curTime) >= 200000) {
00138         if (receiveWithTimeout(100000)) { // 100ms
00139             if (ev.idle()) return -1;
00140             return 1;
00141         }
00142         if (ev.idle()) return -1;
00143         gettimeofday(&curTime, NULL);
00144     }
00145 
00146     // difference is now at most 100ms, do it at once
00147     long usec = timeval_diff_usec(targetTime, curTime);
00148     if (usec>0)
00149         if (receiveWithTimeout(usec)) {
00150             if (ev.idle()) return -1;
00151             return 1;
00152         }
00153         if (ev.idle()) return -1;
00154     return 0;
00155 }

bool RealtimeScheduler::receiveWithTimeout ( long  usec  )  [protected, virtual]

Waits for incoming data on the tun device.

Parameters:
usec Timeout after which to quit waiting (in µsec)
Returns:
true if data was read, false otherwise
00066 {
00067     bool newData = false;
00068     // prepare sets for select()
00069     fd_set readFD;
00070     FD_ZERO(&readFD);
00071 
00072     FD_SET(netw_fd, &readFD);
00073     if ( app_fd >= 0 ) FD_SET(app_fd, &readFD);
00074 
00075     timeval timeout;
00076     timeout.tv_sec = 0;
00077     timeout.tv_usec = usec;
00078 
00079     if (select(FD_SETSIZE, &readFD, NULL, NULL, &timeout) > 0) {
00080         // Incoming data
00081         if (FD_ISSET(netw_fd, &readFD)) {
00082             char* buf = new char[buffersize];
00083             int nBytes = read(netw_fd, buf, buffersize);
00084             if (nBytes < 0) {
00085                 opp_error("Read from network device returned an error");
00086             } else if (nBytes == 0) {
00087                 opp_error("network device closed...");
00088             } else {
00089                 // write data to buffer
00090                 ev << "RealtimeScheduler: received " << nBytes << " bytes\n";
00091                 packetBuffer->push_back(PacketBufferEntry(buf, nBytes));
00092 
00093                 // schedule notificationMsg for the interface module
00094                 timeval curTime;
00095                 gettimeofday(&curTime, NULL);
00096                 curTime = timeval_substract(curTime, baseTime);
00097                 simtime_t t = curTime.tv_sec + curTime.tv_usec*1e-6;
00098                 // TBD assert that it's somehow not smaller than previous event's time
00099                 notificationMsg->setArrival(module,-1,t);
00100                 simulation.msgQueue.insert(notificationMsg);
00101                 newData = true;
00102             }
00103         } else if ( (app_fd >= 0) && (FD_ISSET(app_fd, &readFD)) ) {
00104             char* buf = new char[appBuffersize];
00105             int nBytes = read(app_fd, buf, appBuffersize);
00106             if (nBytes < 0) {
00107                 opp_error("Read from network device returned an error");
00108             } else if (nBytes == 0) {
00109                 opp_error("network device closed...");
00110             } else {
00111                 // write data to buffer
00112                 ev << "RealtimeScheduler: received " << nBytes << " bytes\n";
00113                 appPacketBuffer->push_back(PacketBufferEntry(buf, nBytes));
00114 
00115                 // schedule notificationMsg for the interface module
00116                 timeval curTime;
00117                 gettimeofday(&curTime, NULL);
00118                 curTime = timeval_substract(curTime, baseTime);
00119                 simtime_t t = curTime.tv_sec + curTime.tv_usec*1e-6;
00120                 // TBD assert that it's somehow not smaller than previous event's time
00121                 appNotificationMsg->setArrival(appModule,-1,t);
00122                 simulation.msgQueue.insert(appNotificationMsg);
00123                 newData = true;
00124             }
00125         }
00126     }
00127     return newData;
00128 }

void RealtimeScheduler::sendBytes ( const char *  buf,
size_t  numBytes,
bool  isApp = false 
) [virtual]

Send data to network.

Parameters:
buf A pointer to the data to be send
numBytes the length of the data
isApp set to "true" if called from a realworldApp
00200 {
00201     if (!buf) {
00202         ev << "Error sending packet: buf = NULL!\n";
00203         return;
00204     }
00205     if (!isApp) {
00206         if( numBytes > buffersize ) {
00207             ev << "trying to send oversizd packet: size " << numBytes << " mtu " << buffersize << "\n";
00208             opp_error("Can't send packet: too large"); //FIXME: Throw exception instead
00209         }
00210         write(netw_fd, buf, numBytes);
00211     } else {
00212         if( numBytes > appBuffersize ) {
00213             ev << "trying to send oversizd packet: size " << numBytes << " mtu " << appBuffersize << "\n";
00214             opp_error("Can't send packet: too large"); //FIXME: Throw exception instead
00215         }
00216         if ( app_fd < 0 ) opp_error ("Can't send packet to Application: no socket");
00217         write(app_fd, buf, numBytes);
00218     }
00219     // TBD check for errors
00220 }

void RealtimeScheduler::setInterfaceModule ( cModule *  module,
cMessage *  notificationMsg,
PacketBuffer buffer,
int  mtu,
bool  isApp = false 
) [virtual]

To be called from the module which wishes to receive data from the tun device.

The method must be called from the module's initialize() function.

Parameters:
module Pointer to the module that whishes to receive the data
notificationMsg A pointer to a message that will be sheduled if there is data to read
buffer A pointer to the buffer the data will be written into
mtu Max allowed packet size
isApp set to "true" if called from a realworldApp
00044 {
00045     if (!mod || !notifMsg || !buffer)
00046         throw new cRuntimeError("RealtimeScheduler: setInterfaceModule(): arguments must be non-NULL");
00047 
00048     if (!isApp) {
00049         if (module)
00050             throw new cRuntimeError("RealtimeScheduler: setInterfaceModule() already called");
00051         module = mod;
00052         notificationMsg = notifMsg;
00053         packetBuffer = buffer;
00054         buffersize = mtu;
00055     } else {
00056         if (appModule)
00057             throw new cRuntimeError("RealtimeScheduler: setInterfaceModule() already called");
00058         appModule = mod;
00059         appNotificationMsg = notifMsg;
00060         appPacketBuffer = buffer;
00061         appBuffersize = mtu;
00062     }
00063 }

void RealtimeScheduler::startRun (  )  [virtual]

Called at the beginning of a simulation run.

00019 {
00020     if (initsocketlibonce()!=0)
00021         throw new cRuntimeError("RealtimeScheduler: Cannot initialize socket library");
00022 
00023     gettimeofday(&baseTime, NULL);
00024 
00025     appModule = NULL;
00026     appNotificationMsg = NULL;
00027     module = NULL;
00028     notificationMsg = NULL;
00029 
00030     if (initializeNetwork()) {
00031         opp_error("realtimeScheduler error: initializeNetwork failed\n");
00032     }
00033 }


Member Data Documentation

int RealtimeScheduler::app_fd [protected]

size_t RealtimeScheduler::appBuffersize [protected]

cModule* RealtimeScheduler::appModule [protected]

cMessage* RealtimeScheduler::appNotificationMsg [protected]

PacketBuffer* RealtimeScheduler::appPacketBuffer [protected]

timeval RealtimeScheduler::baseTime [protected]

size_t RealtimeScheduler::buffersize [protected]

cModule* RealtimeScheduler::module [protected]

int RealtimeScheduler::netw_fd [protected]

cMessage* RealtimeScheduler::notificationMsg [protected]

PacketBuffer* RealtimeScheduler::packetBuffer [protected]


The documentation for this class was generated from the following files:
Generated on Wed Apr 4 13:37:06 2007 for ITM OverSim by  doxygen 1.4.7