|
From: <bro...@us...> - 2008-02-19 02:40:47
|
Revision: 112
http://gridsim.svn.sourceforge.net/gridsim/?rev=112&view=rev
Author: brobergj
Date: 2008-02-18 18:40:39 -0800 (Mon, 18 Feb 2008)
Log Message:
-----------
*FlowBuffer replaces FlowInput/FlowOutput approach
*FlowBuffer acts as both a input and output port for simulation entities and as such it is a central point of control
Added Paths:
-----------
branches/gridsim4.0-branch2/source/gridsim/net/flow/FlowBuffer.java
Added: branches/gridsim4.0-branch2/source/gridsim/net/flow/FlowBuffer.java
===================================================================
--- branches/gridsim4.0-branch2/source/gridsim/net/flow/FlowBuffer.java (rev 0)
+++ branches/gridsim4.0-branch2/source/gridsim/net/flow/FlowBuffer.java 2008-02-19 02:40:39 UTC (rev 112)
@@ -0,0 +1,895 @@
+/*
+ * Title: GridSim Toolkit
+ * Description: GridSim (Grid Simulation) Toolkit for Modeling and Simulation
+ * of Parallel and Distributed Systems such as Clusters and Grids
+ * Licence: GPL - http://www.gnu.org/copyleft/gpl.html
+ *
+ * Author: James Broberg & Anthony Sulistio (Adapted from original Output.java)
+ */
+
+package gridsim.net.flow;
+
+import gridsim.*;
+import gridsim.net.*;
+import gridsim.util.*;
+
+import eduni.simjava.*;
+
+import java.util.*;
+
+
+/**
+ * GridSim Output defines a port through which a simulation entity sends
+ * data to the simulated network.
+ * <p>
+ * It maintains an event queue to serialize
+ * the data-out-flow and delivers to the destination entity.
+ * It works along with Input entity to simulate network
+ * communication delay. Simultaneous outputs can be modeled by using multiple
+ * instances of this class
+ *
+ * @author Manzur Murshed and Rajkumar Buyya
+ * @since GridSim Toolkit 1.0
+ * @invariant $none
+ */
+public class FlowBuffer extends Sim_entity implements NetIO
+{
+ private Sim_port outPort_; // output port
+ private Link link_; // a link to this output entity
+ private double baudRate_; // baud rate of this entity
+ private final int SIZE = 8; // 1 byte in bits
+ private int pktID_; // packet ID counter
+ private Vector outPacketList_; // store a list of packets
+ private HashMap<Integer, Packet> activeFlows_; // stores a list of active Flows
+ private Random random_; // selects to which junk packets go to
+ private TrafficGenerator gen_; // background traffic generator
+ private ArrayList list_; // list of resources + user entities
+ private boolean hasStarted_; // a flag for background traffic has started
+ private static final int BITS = 8; // 1 byte = 8 bits
+
+
+ /**
+ * Allocates a new Output object
+ * @param name the name of this object
+ * @param baudRate the communication speed
+ * @throws NullPointerException This happens when creating this entity
+ * before initializing GridSim package or this entity name
+ * is <tt>null</tt> or empty
+ * @pre name != null
+ * @pre baudRate >= 0.0
+ * @post $none
+ */
+ public FlowBuffer(String name, double baudRate) throws NullPointerException
+ {
+ super(name);
+ this.baudRate_ = baudRate;
+ link_ = null;
+ outPacketList_ = null;
+ activeFlows_ = null;
+ pktID_ = 0;
+
+ outPort_ = new Sim_port("output_buffer");
+ super.add_port(outPort_);
+
+ // for sending background traffic
+ gen_ = null;
+ list_ = null;
+ random_ = null;
+ hasStarted_ = false;
+ }
+
+ /**
+ * Sets the background traffic generator for this entity.
+ * <p>
+ * When simulation starts, this entity will automatically sends junk
+ * packets to resource entities.
+ * @param gen a background traffic generator
+ * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
+ * @pre gen != null
+ * @post $none
+ */
+ public boolean setBackgroundTraffic(TrafficGenerator gen)
+ {
+ if (gen == null) {
+ return false;
+ }
+
+ gen_ = gen;
+ if (list_ == null) {
+ list_ = new ArrayList();
+ }
+
+ return true;
+ }
+
+ /**
+ * Sets the background traffic generator for this entity.
+ * <p>
+ * When simulation starts, this entity will automatically sends junk
+ * packets to resource entities and other entities. <br>
+ * NOTE: Sending background traffic to itself is not supported.
+ *
+ * @param gen a background traffic generator
+ * @param userName a collection of user entity name (in String object).
+ * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
+ * @pre gen != null
+ * @pre userName != null
+ * @post $none
+ */
+ public boolean setBackgroundTraffic(TrafficGenerator gen,
+ Collection userName)
+ {
+ if (gen == null || userName == null) {
+ return false;
+ }
+
+ boolean flag = true;
+ try
+ {
+ gen_ = gen;
+ if (list_ == null) {
+ list_ = new ArrayList();
+ }
+
+ // iterates through each list to check whether it is a valid
+ // entity name or not
+ Iterator it = userName.iterator();
+ int id = -1;
+ while( it.hasNext() )
+ {
+ String name = (String) it.next();
+
+ // check whether it is sending to itself
+ id = GridSim.getEntityId("Output_" + name);
+ if (id == super.get_id())
+ {
+ System.out.println(super.get_name() +
+ ".setBackgroundTraffic(): Warning - can not send " +
+ "junk packets to itself.");
+ continue;
+ }
+
+ // get the ID of other entity
+ id = GridSim.getEntityId(name);
+ if (id > 0)
+ {
+ Integer obj = new Integer(id);
+ list_.add(obj);
+ }
+ // ignore for invalid entity
+ else
+ {
+ System.out.println(super.get_name() +
+ ".setBackgroundTraffic(): Warning - invalid entity " +
+ "name for \"" + name + "\".");
+ }
+ }
+ }
+ catch(Exception e) {
+ flag = false;
+ }
+
+ return flag;
+ }
+
+ /**
+ * Sets this entity's link. This should be used only if the network
+ * extensions are being used.
+ *
+ * @param link the link to which this Output entity should send data
+ * @pre link != null
+ * @post $none
+ */
+ public void addLink(Link link)
+ {
+ this.link_ = link;
+ baudRate_ = link_.getBaudRate();
+ outPacketList_ = new Vector();
+ activeFlows_ = new HashMap();
+ }
+
+ /**
+ * Gets the baud rate
+ * @return the baud rate
+ * @deprecated As of GridSim 2.1, replaced by {@link #getBaudRate()}
+ * @pre $none
+ * @post $result >= 0.0
+ */
+ public double GetBaudRate() {
+ return this.getBaudRate();
+ }
+
+ /**
+ * Gets the baud rate
+ * @return the baud rate
+ * @pre $none
+ * @post $result >= 0.0
+ */
+ public double getBaudRate() {
+ return baudRate_;
+ }
+
+ /**
+ * Gets the I/O real number based on a given value
+ * @param value the specified value
+ * @return real number
+ * @deprecated As of GridSim 2.1, replaced by {@link #realIO(double)}
+ * @pre $none
+ * @post $result >= 0.0
+ */
+ public double real_io(double value) {
+ return this.realIO(value);
+ }
+
+ /**
+ * Gets the I/O real number based on a given value
+ * @param value the specified value
+ * @return real number
+ * @pre $none
+ * @post $result >= 0.0
+ */
+ public double realIO(double value) {
+ return GridSimRandom.realIO(value);
+ }
+
+ /**
+ * A method that gets one process event at one time until the end
+ * of a simulation, then delivers an event to the entity (its parent)
+ * @pre $none
+ * @post $none
+ */
+ public void body()
+ {
+
+ //System.out.println("Hello FlowOutput");
+
+ // find out ids for entities that are not part of simulation network
+ // topology, such as GIS, GridSimShutdown and GridStatistics
+ int gisID = GridSim.getGridInfoServiceEntityId();
+ int statID = GridSim.getGridStatisticsEntityId();
+ int shutdownID = GridSim.getGridSimShutdownEntityId();
+
+ // start generating some junk packets or background traffic
+ startBackgroundTraffic();
+
+ // Process incoming events
+ while ( Sim_system.running() )
+ {
+ Sim_event ev = new Sim_event();
+ super.sim_get_next(ev); // get the next event in the queue
+
+ // if the simulation finishes then exit the loop
+ if (ev.get_tag() == GridSimTags.END_OF_SIMULATION) {
+ break;
+ }
+
+ System.out.println(super.get_name() + ".body(): ev.get_tag() is " + ev.get_tag());
+
+ // handle different types of incoming events
+ switch ( ev.get_tag() )
+ {
+ case GridSimTags.SEND_PACKET:
+ System.out.println(super.get_name() + ".body(): sendPacket() + at time = " + GridSim.clock());
+ sendPacket();
+ break;
+
+ // submit ping() request
+ case GridSimTags.INFOPKT_SUBMIT:
+ System.out.println(super.get_name() + ".body(): sendInfoPacket() + at time = " + GridSim.clock());
+ sendInfoPacket(ev);
+ break;
+
+ // replying ping() request from another entity
+ case GridSimTags.INFOPKT_RETURN:
+ System.out.println(super.get_name() + ".body(): returnInfoPacket() + at time = " + GridSim.clock());
+ returnInfoPacket(ev);
+ break;
+
+ // activate background traffic
+ case GridSimTags.JUNK_PKT:
+ generateBackgroundTraffic();
+ break;
+
+ case GridSimTags.PKT_FORWARD:
+ System.out.println(super.get_name() + ".body(): getDataFromLink() + at time = " + GridSim.clock());
+ getDataFromLink(ev);
+ break;
+
+ // Check if initial flow duration estimation was accurate
+ case GridSimTags.FLOW_HOLD:
+ System.out.println(super.get_name() + ".body(): checkForecast() + at time = " + GridSim.clock());
+ checkForecast(ev);
+ break;
+
+ default:
+ defaultSend(ev, gisID, statID, shutdownID);
+ break;
+ }
+ }
+
+ System.out.println(super.get_name() + ":%%%% Exiting body() at time " +
+ GridSim.clock() );
+ }
+
+ private void checkForecast(Sim_event ev) {
+ int pktID = (Integer) ev.get_data();
+ FlowPacket fp = null;
+
+ System.out.println(super.get_name() + ".checkForecast(): checking pkt id # " + pktID);
+
+ // If flow hasn't already finished
+ if ((fp = (FlowPacket) activeFlows_.get(pktID)) != null) {
+ Object data = fp.getData();
+ IO_data io = new IO_data( data, fp.getSize(),
+ outPort_.get_src());
+ super.sim_schedule(outPort_, GridSimTags.SCHEDULE_NOW, fp.getTag() , io.getData());
+ } else {
+ System.out.println(super.get_name() + ".checkForecast(): pkt id # " + pktID + " already removed");
+
+ }
+
+ }
+
+ /**
+ * Generates few junk packets at the given interval
+ * @pre $none
+ * @post $none
+ */
+ private synchronized void generateBackgroundTraffic()
+ {
+ // get the next inter-arrival time for these junk packets
+ long time = gen_.getNextPacketTime();
+
+ // get the sending pattern
+ int pattern = gen_.getPattern();
+
+ // for initial start-up, get the list of all resources first
+ if (hasStarted_ == false)
+ {
+ // get list of resource IDs from GIS
+ LinkedList resList = GridSim.getGridResourceList();
+
+ // if the list is empty then schedule the next time
+ if (resList == null && list_.size() == 0)
+ {
+ super.sim_schedule(super.get_id(), time, GridSimTags.JUNK_PKT);
+ return;
+ }
+
+ hasStarted_ = true;
+ list_.addAll(resList); // add resource IDs into the current list
+
+ // sets the sending pattern
+ if (pattern == TrafficGenerator.SEND_ONE_ONLY && random_ == null) {
+ random_ = new Random();
+ }
+ }
+
+ // get the required info for generating this background traffic
+ long size = gen_.getNextPacketSize(); // packet size
+ long freq = gen_.getNextPacketFreq(); // packet freq
+ int type = gen_.getServiceType(); // packet type
+ int tag = GridSimTags.JUNK_PKT; // packet tag
+
+ // we need to packetsize the data, all packets are sent with size MTU.
+ // only the last packet contains the data, the receiver should
+ // throw away all other packets
+ int MTU = link_.getMTU();
+ int numPackets = (int) Math.ceil( size / (MTU * 1.0) );
+
+ /********* // DEBUG info
+ System.out.println();
+ System.out.println(super.get_name() +
+ ": START GENERATE BG traffic... at time "+ GridSim.clock());
+ System.out.println(super.get_name() +
+ ": NEXT background traffic will start at " + time);
+ System.out.println(super.get_name() +
+ " num PACKETS = " + numPackets + ", freq = " + freq);
+ *********/
+
+ int i = 0;
+ int destId = -1;
+
+ // send to one of the entity using uniform distribution
+ if (pattern == TrafficGenerator.SEND_ONE_ONLY)
+ {
+ int index = random_.nextInt( list_.size() );
+ destId = ((Integer) list_.get(index)).intValue();
+
+ /********* // DEBUG info
+ System.out.println(super.get_name() + ": Destination id = " +
+ destId + " = " + GridSim.getEntityName(destId) );
+ *********/
+
+ // create junk packets or empty FlowPacket.
+ for (i = 0; i < freq; i++) {
+ convertIntoPacket(MTU, numPackets+1, tag, destId, type);
+ }
+ }
+ // send to all resources + other entities
+ else if (pattern == TrafficGenerator.SEND_ALL)
+ {
+ // send to all resources and user entities
+ for (int k = 0; k < list_.size(); k++)
+ {
+ destId = ((Integer) list_.get(k)).intValue();
+
+ /********* // DEBUG info
+ System.out.println(super.get_name() + ": Destination id = " +
+ destId + " = " + GridSim.getEntityName(destId) );
+ *********/
+
+ // create junk packets or empty FlowPacket.
+ for (i = 0; i < freq; i++) {
+ convertIntoPacket(MTU, numPackets+1, tag, destId, type);
+ }
+ }
+ }
+
+ // sends the next junk packets
+ super.sim_schedule(super.get_id(), time, GridSimTags.JUNK_PKT);
+ }
+
+ /**
+ * Initial start for the background traffic
+ * @pre $none
+ * @post $none
+ */
+ private synchronized void startBackgroundTraffic()
+ {
+ // if no background traffic generator, then skip the rest
+ if (gen_ == null) {
+ return;
+ }
+
+ // get the next inter-arrival time
+ long time = gen_.getNextPacketTime();
+ System.out.println(super.get_name() +
+ ": background traffic will start at time " + time);
+
+ // starts background traffic if the inter-arrival time is valid
+ if (time == -1) {
+ return;
+ }
+
+ super.sim_schedule(super.get_id(), time, GridSimTags.JUNK_PKT);
+ }
+
+ /**
+ * This method processes outgoing data without a network extension.
+ * @param ev a Sim_event object
+ * @param gisID the central/default GIS entity ID
+ * @param statID the GridStatistic entity ID
+ * @param shutdownID the GridSimShutdown entity ID
+ * @pre ev != null
+ * @post $none
+ */
+ private synchronized void defaultSend(Sim_event ev, int gisID, int statID,
+ int shutdownID)
+ {
+ IO_data io = (IO_data) ev.get_data();
+ int destId = io.getDestID();
+
+ /***** // DEBUG info*/
+ System.out.println(super.get_name() + ".defaultSend(): Send to " +
+ GridSim.getEntityName(destId) + " tag = " + ev.get_tag() + " at time = " + GridSim.clock());
+ /*****/
+
+ // if this entity uses a network extension
+ if (link_ != null && destId != gisID && destId != statID &&
+ destId != shutdownID)
+ {
+ System.out.println(super.get_name() + ".defaultSend(): submitToLink() + at time = " + GridSim.clock());
+ submitToLink(ev);
+ return;
+ }
+
+ // Identify ID of an entity which acts as Input/Buffer
+ // entity of destination entity
+ int id = GridSim.getEntityId( "Input_" +
+ Sim_system.get_entity(destId).get_name() );
+
+ // Send first and then hold
+ super.sim_schedule(id, GridSimTags.SCHEDULE_NOW, ev.get_tag(), io);
+
+ double receiverBaudRate = ( (FlowBuffer)
+ Sim_system.get_entity(id) ).getBaudRate();
+
+ // NOTE: io is in byte and baud rate is in bits. 1 byte = 8 bits
+ // So, convert io into bits
+ double minBaudRate = Math.min(baudRate_, receiverBaudRate);
+ double communicationDelay = GridSimRandom.realIO(
+ (io.getByteSize() * BITS) / minBaudRate);
+
+ // NOTE: Below is a deprecated method for SimJava 2
+ //super.sim_hold(communicationDelay);
+ super.sim_process(communicationDelay);
+ }
+
+ /**
+ * This method takes data from an entity. If the size of the data is larger
+ * than the MTU of the link, then the packet is split into mutiple size
+ * units. After this it calls outEnque() to queue these packets into its
+ * buffer.
+ *
+ * @param ev A Sim_event data that contains all the data for this method
+ * to do its task.
+ * @pre ev != null
+ * @post $none
+ */
+ private synchronized void submitToLink(Sim_event ev)
+ {
+ IO_data data = (IO_data) ev.get_data();
+ Object obj = data.getData();
+ long size = data.getByteSize();
+ int tag = ev.get_tag();
+ int destId = data.getDestID();
+ int netServiceType = data.getNetServiceLevel();
+
+ // we need to packetsize the data, all packets are sent with size MTU.
+ // only the last packet contains the data, the receiver should
+ // throw away all other packets
+ //int MTU = link_.getMTU();
+ //int numPackets = (int) Math.ceil( size / (MTU * 1.0) );
+
+ // make dummy packets with null data
+ //System.out.println("Packetizing data, creating " + numPackets + " dummy packets at time = " + GridSim.clock());
+ //convertIntoPacket(MTU, numPackets, tag, destId, netServiceType);
+
+ // last packet contains the actual data
+ FlowPacket np = null;
+ np = new FlowPacket(obj,pktID_,size,tag,super.get_id(),
+ destId, netServiceType, 1, 1);
+
+ System.out.println("Sending flow packet to link at time = " + GridSim.clock() + " id is " + pktID_);
+ pktID_++; // increments packet ID
+ outEnque(np, GridSimTags.SCHEDULE_NOW);
+ }
+
+ /**
+ * Creates many dummy or null packets
+ * @param size packet size (in bytes)
+ * @param numPackets total number of packets to be created
+ * @param tag packet tag
+ * @param destId destination ID for sending the packet
+ * @param netServiceType level type of service for the packet
+ * @pre $none
+ * @post $none
+ */
+ private synchronized void convertIntoPacket(long size, int numPackets,
+ int tag, int destId, int netServiceType)
+ {
+ FlowPacket np = null;
+ for (int i = 0; i < numPackets - 1; i++)
+ {
+ // change the tag name for dummy packets, apart from junk packets
+ if (tag != GridSimTags.JUNK_PKT) {
+ tag = GridSimTags.EMPTY_PKT;
+ }
+
+ np = new FlowPacket(null, pktID_, size, tag, super.get_id(), destId,
+ netServiceType, i+1, numPackets);
+
+ pktID_++; // increments packet ID
+ outEnque(np, GridSimTags.SCHEDULE_NOW);
+ }
+ }
+
+ /**
+ * Sends an InfoPacket for ping request
+ * @param ev a Sim_Event object
+ * @pre ev != null
+ * @post $none
+ */
+ private synchronized void sendInfoPacket(Sim_event ev)
+ {
+ IO_data data = (IO_data) ev.get_data();
+
+ // gets all the relevant info
+ long size = data.getByteSize();
+ int destId = data.getDestID();
+ int netServiceType = data.getNetServiceLevel();
+ int tag = ev.get_tag();
+ String name = GridSim.getEntityName( outPort_.get_dest() );
+
+ // we need to packetsize the data, all packets are sent with size MTU
+ // only the last packet contains the ping data, the receiver should
+ // throw away all other data
+ int MTU = link_.getMTU();
+ int numPackets = (int) Math.ceil( size / (MTU * 1.0) );
+
+ // break ping size into smaller pieces
+ // Also, make sure that it is not for pinging itself
+ if (size > MTU && outPort_.get_dest() != destId)
+ {
+ // make dummy packets with null data
+ convertIntoPacket(MTU, numPackets, tag, destId, netServiceType);
+ }
+
+ // get the remaining ping size
+ size = data.getByteSize() - MTU*(numPackets-1);
+
+ // create the real InfoPacket
+ InfoPacket pkt = new InfoPacket(name,pktID_,size,outPort_.get_dest(),
+ destId,netServiceType);
+
+ // set the required info
+ pkt.setLast( super.get_id() );
+ pkt.addHop( outPort_.get_dest() );
+ pkt.addEntryTime( GridSim.clock() );
+ pkt.setOriginalPingSize( data.getByteSize() );
+
+ pktID_++; // increments packet ID
+ outEnque(pkt, GridSimTags.SCHEDULE_NOW);
+ }
+
+ private synchronized void sendInfoPacket(int dest)
+ {
+ // IO_data data = (IO_data) ev.get_data();
+
+ // gets all the relevant info
+ long size = 1500;
+ int destId = dest;
+// / int netServiceType = data.getNetServiceLevel();
+ // int tag = ev.get_tag();
+ String name = GridSim.getEntityName( outPort_.get_dest() );
+
+ // we need to packetsize the data, all packets are sent with size MTU
+ // only the last packet contains the ping data, the receiver should
+ // throw away all other data
+ // int MTU = link_.getMTU();
+ // int numPackets = (int) Math.ceil( size / (MTU * 1.0) );
+
+ // break ping size into smaller pieces
+ // Also, make sure that it is not for pinging itself
+ //if (size > MTU && outPort_.get_dest() != destId)
+ //{
+ // // make dummy packets with null data
+ // convertIntoPacket(MTU, numPackets, tag, destId, netServiceType);
+ //}
+
+ // get the remaining ping size
+ //size = data.getByteSize() - MTU*(numPackets-1);
+
+ // create the real InfoPacket
+ InfoPacket pkt = new InfoPacket(name,pktID_,size,outPort_.get_dest(),
+ destId,0);
+
+ // set the required info
+ pkt.setLast( super.get_id() );
+ pkt.addHop( outPort_.get_dest() );
+ pkt.addEntryTime( GridSim.clock() );
+ pkt.setOriginalPingSize( 1500 );
+ pkt.setTag(GridSimTags.INFOPKT_SUBMIT);
+
+ pktID_++; // increments packet ID
+ outEnque(pkt, GridSimTags.SCHEDULE_NOW);
+ }
+
+ /**
+ * Sends back the ping() request to the next hop or destination
+ * @param ev a Sim_event object
+ * @pre ev != null
+ * @post $none
+ */
+ private void returnInfoPacket(Sim_event ev)
+ {
+ IO_data data = (IO_data) ev.get_data();
+
+ // use the original ping size rather than IO_data or InfoPacket size
+ // since the latter is restricted to MTU
+ InfoPacket pkt = (InfoPacket) data.getData();
+ long size = pkt.getOriginalPingSize();
+
+ // get other relevant info
+ int tag = ev.get_tag();
+ int destId = pkt.getSrcID();
+ int netServiceType = data.getNetServiceLevel();
+
+ // we need to packetsize the data, all packets are sent with size MTU.
+ // only the last packet contains the data, the receiver should
+ // throw away all other packets
+ int MTU = link_.getMTU();
+ int numPackets = (int) Math.ceil( size / (MTU * 1.0) );
+
+ // make dummy packets with null data
+ convertIntoPacket(MTU, numPackets, tag, destId, netServiceType);
+
+ // set the original packet of last hop into this entity id
+ pkt.setLast( super.get_id() );
+ outEnque(pkt, GridSimTags.SCHEDULE_NOW);
+ }
+
+ /**
+ * Takes a packet, adds it into a buffer and schedules it to be sent out at
+ * an appropriate time.
+ *
+ * @param pkt The packet to be buffered
+ * @param delay The length of time this packet should be delayed (exclusive
+ * of the transmission time)
+ * @pre pkt != null
+ * @pre delay > 0
+ * @post $none
+ */
+ private synchronized void outEnque(Packet pkt, double delay)
+ {
+
+ //if ((pkt instanceof InfoPacket) != true) {
+ // sendInfoPacket(pkt.getDestID());
+ //}
+
+ outPacketList_.add(pkt);
+ if (outPacketList_.size() == 1)
+ {
+ System.out.println(super.get_name() + ".outEnque() Size is " + pkt.getSize() + " baud " + link_.getBaudRate());
+ // Compute expected duration of flow using bottleneck baudRate
+ // double total = delay + (pkt.getSize()*SIZE / link_.getBaudRate());
+ double total = 0.0;
+
+ System.out.println(super.get_name() + ".outEnque() Time now " + GridSim.clock() + " delay is " + total);
+ super.sim_schedule(super.get_id(), total, GridSimTags.SEND_PACKET);
+ }
+
+
+
+
+ }
+
+
+ /**
+ * Removes a single packet from the buffer and sends it down the link.
+ * Then, schedules the next packet in the list.
+ * @pre $none
+ * @post $none
+ */
+ private synchronized void sendPacket()
+ {
+ if (outPacketList_ == null || outPacketList_.isEmpty() == true) {
+ return;
+ }
+
+ // submits the first packet in the list
+ Packet np = (Packet) outPacketList_.remove(0);
+
+ boolean ping = false; // a flag to determine ping packet or not
+ int tag = -1; // event tag ID
+ int dest = -1; // destination ID
+
+ // if a packet belongs to a ping packet
+ if (np instanceof InfoPacket)
+ {
+ ((InfoPacket)np).addExitTime( GridSim.clock() );
+ ((InfoPacket)np).addBaudRate( link_.getBaudRate() );
+ ping = true;
+ tag = GridSimTags.INFOPKT_SUBMIT;
+ }
+
+ if (np instanceof FlowPacket && np.getTag() == GridSimTags.FLOW_SUBMIT ) {
+ ((FlowPacket)np).addBaudRate( link_.getBaudRate() );
+ ((FlowPacket)np).addLatency( link_.getDelay() );
+ }
+
+
+ // if an entity tries to send a packet to itself
+ if ( np.getDestID() == outPort_.get_dest() )
+ {
+ // then change the destination name and id
+ String destName = super.get_name();
+ destName = destName.replaceFirst("Output", "Input");
+ dest = Sim_system.get_entity_id(destName);
+
+ // for a ping packet, change the tag
+ if (ping == true)
+ {
+ // don't forget to change the packet tag
+ tag = GridSimTags.INFOPKT_RETURN;
+ ((InfoPacket) np).setTag(tag);
+ }
+ else {
+ tag = np.getTag();
+ }
+ }
+ else // if an entity tries to send to other entity
+ {
+ // change or keep the event tag
+ tag = GridSimTags.PKT_FORWARD;
+ if (np.getTag() == GridSimTags.JUNK_PKT) {
+ tag = GridSimTags.JUNK_PKT;
+ }
+
+ // sends the packet into the link
+ dest = link_.get_id();
+ }
+
+ // send the packet
+ super.sim_schedule(dest, GridSimTags.SCHEDULE_NOW, tag, np);
+
+ /***** // DEBUG info **/
+ System.out.println(super.get_name() + " send to " +
+ GridSim.getEntityName(dest) + " tag = " + tag + " time " + GridSim.clock());
+ /****/
+
+ // if the list is not empty, then schedule the next packet in the list
+ if (outPacketList_.isEmpty() != true)
+ {
+ //double delay = np.getSize() * SIZE / link_.getBaudRate();
+ double delay = 0.0;
+ super.sim_schedule(super.get_id(), delay, GridSimTags.SEND_PACKET);
+ }
+ }
+
+ private void getDataFromLink(Sim_event ev)
+ {
+ Object obj = ev.get_data();
+ double duration = 0.0;
+
+ if (obj instanceof Packet)
+ {
+ // decrypt the packet into original format
+ Packet pkt = (Packet) ev.get_data();
+
+ if (pkt instanceof InfoPacket)
+ {
+ processPingRequest( (InfoPacket) pkt);
+ return;
+ }
+
+ // all except last packet in a data session are null packets
+ if (pkt instanceof FlowPacket)
+ {
+ FlowPacket np = (FlowPacket) pkt;
+ int tag = np.getTag();
+ System.out.println("Packet id is " + np.getID());
+
+ // ignore incoming junk packets
+ if (tag == GridSimTags.JUNK_PKT) {
+ return;
+ }
+
+ // ignore incoming null dummy packets
+ if (tag == GridSimTags.EMPTY_PKT && np.getData() == null) {
+ return;
+ }
+
+ // convert the packets into IO_data
+ Object data = np.getData();
+ IO_data io = new IO_data( data, np.getSize(),
+ outPort_.get_src());
+ System.out.println(super.get_name() + ".getDataFromLink() Time now " + GridSim.clock()
+ + " bottleneck was " + np.getBandwidth_() + " sum lat is " + np.getLatency() );
+
+ // if flow terminates at next entity, add to active flows
+ // & hold for appropriate duration
+ if (pkt.getTag() == GridSimTags.FLOW_SUBMIT) {
+ duration = np.getSize()*SIZE / np.getBandwidth_();
+ activeFlows_.put(pkt.getID(), pkt);
+ super.sim_schedule(super.get_id(), duration, GridSimTags.FLOW_HOLD, new Integer(pkt.getID()));
+
+ // if flow is just an ACK of a finished flow do not hold
+ } else if (pkt.getTag() == GridSimTags.FLOW_RETURN){
+ duration = 0.0;
+ // send the data into entity input port
+ super.sim_schedule(outPort_, duration, tag,
+ io.getData() );
+ }
+
+
+ }
+ }
+ }
+
+ private void processPingRequest(InfoPacket pkt)
+ {
+ // add more information to ping() packet
+ pkt.addHop( outPort_.get_dest() );
+ pkt.addEntryTime( GridSim.clock() );
+
+ IO_data io = new IO_data( pkt, pkt.getSize(), outPort_.get_dest() );
+
+ // send this ping() packet to the entity
+ super.sim_schedule(outPort_, GridSimTags.SCHEDULE_NOW,
+ pkt.getTag(), io.getData());
+ }
+
+} // end class
+
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|