|
From: <bro...@us...> - 2008-02-19 02:38:20
|
Revision: 111
http://gridsim.svn.sourceforge.net/gridsim/?rev=111&view=rev
Author: brobergj
Date: 2008-02-18 18:38:19 -0800 (Mon, 18 Feb 2008)
Log Message:
-----------
*Re-coded to support FlowBuffer instead of FlowInput/FlowOutput
*Added registerFlow() and deregisterFlow() functionality
*Update flow duration code needs to be fixed still
*Added additional toString() information
Added Paths:
-----------
branches/gridsim4.0-branch2/source/gridsim/net/flow/FlowLink.java
Added: branches/gridsim4.0-branch2/source/gridsim/net/flow/FlowLink.java
===================================================================
--- branches/gridsim4.0-branch2/source/gridsim/net/flow/FlowLink.java (rev 0)
+++ branches/gridsim4.0-branch2/source/gridsim/net/flow/FlowLink.java 2008-02-19 02:38:19 UTC (rev 111)
@@ -0,0 +1,478 @@
+/*
+ * ** Network and Service Differentiation Extensions to GridSim 4.0 **
+ *
+ * Author: James Broberg
+ *
+ * August 2007
+ *
+ * Licence: GPL - http://www.gnu.org/copyleft/gpl.html
+ *
+ * FlowLink.java - Simulates a network link
+ *
+ */
+
+package gridsim.net.flow;
+
+import eduni.simjava.*;
+import gridsim.*;
+
+import java.util.*;
+import gridsim.net.Link;
+import gridsim.net.Packet;
+import gridsim.net.flow.FlowPacket;
+
+
+/**
+ * This class enables flow level networking over a shared link. It is based
+ * on SimpleLink.java by Gokul Poduval & Chen-Khong Tham
+ *
+ * @invariant $none
+ * @since GridSim Toolkit 4.0
+ * @author James Broberg, The University of Melbourne
+ */
+
+public class FlowLink extends Link
+{
+ private Vector q_;
+ private HashMap flows_;
+ private double lastUpdateTime_; // a timer to denote the last update time
+ private int inEnd1_;
+ private int outEnd1_;
+ private int inEnd2_;
+ private int outEnd2_;
+
+
+ /**
+ * Constructs a Link which simulates a physical link between two entities.
+ *
+ * @param name Name of this Link
+ * @param baudRate baud rate of this link (bits/s)
+ * @param propDelay Propogation delay of the Link in milli seconds
+ * @param MTU Maximum Transmission Unit of the Link in bytes.
+ * Packets which are larger than the MTU should be split
+ * up into MTU size units. <br>
+ * For e.g. a 1024 byte packet trying to cross a 576 byte
+ * MTU link should get split into 2 packets of 576 bytes
+ * and 448 bytes.
+ * @throws NullPointerException This happens when name is empty or null
+ * @throws ParameterException This happens for the following conditions:
+ * <ul>
+ * <li> name is null
+ * <li> baudRate <= 0
+ * <li> propDelay <= 0
+ * <li> MTU <= 0
+ * </ul>
+ *
+ * @pre name != null
+ * @pre baudRate > 0
+ * @pre propDelay > 0
+ * @pre MTU > 0
+ * @post $none
+ */
+ public FlowLink(String name, double baudRate, double propDelay, int MTU)
+ throws ParameterException, NullPointerException
+ {
+ super(name, baudRate, propDelay, MTU);
+ init();
+ }
+
+ /**
+ * Constructs a link with some default parameters. It simulates a link with
+ * a default value of baud rate, propagation delay and MTU.
+ *
+ * @param name Name of this Link
+ * @throws NullPointerException This happens when name is empty or null
+ * @throws ParameterException This happens when the given name is empty
+ * @see gridsim.net.Link#DEFAULT_BAUD_RATE
+ * @see gridsim.net.Link#DEFAULT_PROP_DELAY
+ * @see gridsim.net.Link#DEFAULT_MTU
+ * @pre name != null
+ * @post $none
+ */
+/* public FlowLink(String name) throws ParameterException,
+ NullPointerException
+ {
+ super(name, Link.DEFAULT_BAUD_RATE, Link.DEFAULT_PROP_DELAY,
+ Link.DEFAULT_MTU);
+
+ init();
+ }*/
+
+ /**
+ * Initialises all attributes
+ * @pre $none
+ * @post $none
+ */
+ private void init()
+ {
+ lastUpdateTime_ = 0.0;
+ q_ = new Vector();
+ flows_ = new HashMap();
+ inEnd1_ = -1;
+ outEnd1_ = -1;
+ inEnd2_ = -1;
+ outEnd2_ = -1;
+ }
+
+ /**
+ * Connects one entity to another via this link
+ * @param end1 an entity
+ * @param end2 an entity
+ * @pre end1 != null
+ * @pre end2 != null
+ * @post $none
+ */
+ public void attach(Sim_entity end1, Sim_entity end2)
+ {
+ if (end1 == null || end2 == null)
+ {
+ System.out.println(super.get_name() + ".attach(): Warning - " +
+ "one or both entities are null.");
+ return;
+ }
+
+ System.out.println(super.get_name() + ".attach(): " + end1.get_name() +
+ " " + end2.get_name());
+ inEnd1_ = GridSim.getEntityId( "Output_" + end1.get_name() );
+ outEnd1_ = GridSim.getEntityId( "Output_" + end1.get_name() );
+
+ System.out.println(super.get_name() + ".attach(): " + end1.get_id() + " " + end2.get_id());
+
+
+ // if end1 is a router/gateway with no Input and Output port
+ if (inEnd1_ == -1 || outEnd1_ == -1)
+ {
+ inEnd1_ = end1.get_id();
+ outEnd1_ = end1.get_id();
+ }
+
+ inEnd2_ = GridSim.getEntityId( "Output_" + end2.get_name() );
+ outEnd2_ = GridSim.getEntityId( "Output_" + end2.get_name() );
+
+ // if end2 is a router/gateway with no Input and Output port
+ if (inEnd2_ == -1 || outEnd2_ == -1)
+ {
+ inEnd2_ = end2.get_id();
+ outEnd2_ = end2.get_id();
+ }
+ }
+
+ /**
+ * Connects one entity to another via this link
+ * @param end1 an Entity name
+ * @param end2 an Entity name
+ * @pre end1 != null
+ * @pre end2 != null
+ * @post $none
+ */
+ public void attach(String end1, String end2)
+ {
+ if (end1 == null || end2 == null)
+ {
+ System.out.println(super.get_name() + ".attach(): Warning - " +
+ "can not connect since one or both entities are null.");
+ return;
+ }
+
+ if (end1.length() == 0 || end2.length() == 0)
+ {
+ System.out.println(super.get_name() + ".attach(): Warning - " +
+ "can not connect since one or both entities are null.");
+ return;
+ }
+
+ inEnd1_ = GridSim.getEntityId("Output_" + end1);
+ outEnd1_ = GridSim.getEntityId("Output_" + end1);
+
+ // if end1 is a router/gateway with no Input and Output port
+ if (inEnd1_ == -1 || outEnd1_ == -1)
+ {
+ inEnd1_ = GridSim.getEntityId(end1);
+ outEnd1_ = inEnd1_;
+ }
+
+ inEnd2_ = GridSim.getEntityId("Output_" + end2);
+ outEnd2_ = GridSim.getEntityId("Output_" + end2);
+
+ // if end1 is a router/gateway with no Input and Output port
+ if (inEnd2_ == -1 || outEnd2_ == -1)
+ {
+ inEnd2_ = GridSim.getEntityId(end1);
+ outEnd2_ = inEnd2_;
+ }
+ }
+
+ /**
+ * Handles external events that are coming to this link.
+ * @pre $none
+ * @post $none
+ */
+ public void body()
+ {
+ // register oneself to the system GIS
+ super.sim_schedule(GridSim.getGridInfoServiceEntityId(),
+ GridSimTags.SCHEDULE_NOW, GridSimTags.REGISTER_LINK,
+ new Integer(super.get_id()) );
+
+ Sim_event ev = new Sim_event();
+ while ( Sim_system.running() )
+ {
+ super.sim_get_next(ev);
+
+ // if the simulation finishes then exit the loop
+ if (ev.get_tag() == GridSimTags.END_OF_SIMULATION) {
+ break;
+ }
+
+ // process the received event
+ System.out.println(super.get_name() + ".body(): processEvent() + at time = " + GridSim.clock());
+ processEvent(ev);
+ sim_completed(ev);
+ }
+
+ while(sim_waiting() > 0)
+ {
+ // wait for event and ignore
+ System.out.println(super.get_name() + ".body(): Ignore !!");
+ sim_get_next(ev);
+ }
+
+ System.out.println(super.get_name() + ":%%%% Exiting body() at time " +
+ GridSim.clock() );
+ }
+
+ /**
+ * Processes incoming events
+ * @param ev a Sim_event object
+ * @pre ev != null
+ * @post $none
+ */
+ private void processEvent(Sim_event ev)
+ {
+ switch ( ev.get_tag() )
+ {
+ case GridSimTags.PKT_FORWARD: // for normal packets
+ case GridSimTags.JUNK_PKT: // for background traffic
+ System.out.println(super.get_name() + ".processEvent(): enque() + at time = " + GridSim.clock());
+ enque(ev);
+ break;
+
+ case GridSimTags.INSIGNIFICANT:
+ System.out.println(super.get_name() + ".processEvent(): processInternalEvent() + at time = " + GridSim.clock());
+ processInternalEvent();
+ break;
+
+ default:
+ System.out.println(super.get_name() + ".body(): Warning - " +
+ "unable to handle request from GridSimTags " +
+ "with constant number " + ev.get_tag());
+ break;
+ }
+ }
+
+ /**
+ * Sends an internal event to itself for a certain time period
+ * @param time the delay time
+ * @pre time >= 0
+ * @post $none
+ */
+ private synchronized boolean sendInternalEvent(double time)
+ {
+ System.out.println(super.get_name() + " sendInternalEvent(): called at time = " + GridSim.clock());
+
+ if (time < 0.0) {
+ System.out.println(super.get_name() + " sendInternalEvent(): false at time = " + GridSim.clock());
+ return false;
+ }
+
+ System.out.println(super.get_name() + " sendInternalEvent(): scheduled for = " + time + " from now");
+ super.sim_schedule(super.get_id(), time, GridSimTags.INSIGNIFICANT);
+ return true;
+ }
+
+ /**
+ * Processes internal events
+ * @pre $none
+ * @post $none
+ */
+ private synchronized void processInternalEvent()
+ {
+
+ System.out.println(super.get_name() + "processInternalEvent(): " + GridSim.clock());
+
+ // this is a constraint that prevents an infinite loop
+ // Compare between 2 floating point numbers. This might be incorrect
+ // for some hardware platform.
+ if ( lastUpdateTime_ == GridSim.clock() ) {
+ return;
+ }
+
+ lastUpdateTime_ = GridSim.clock();
+
+ if (q_.size() == 0) {
+ return;
+ }
+ else if (q_.size() == 1) {
+ deque( (Packet) q_.remove(0) );
+ }
+ else
+ {
+ deque( (Packet)q_.remove(0) );
+ sendInternalEvent(super.delay_ / super.MILLI_SEC); // delay in ms
+
+ }
+
+ System.out.println("Super.delay_ is " + super.delay_);
+ System.out.println(super.get_name() + " processInternalEvent(): done at time = " + GridSim.clock());
+ }
+
+ /**
+ * Puts an event into a queue and sends an internal event to itself
+ * @param ev a Sim_event object
+ * @pre ev != null
+ * @post $none
+ */
+ private synchronized void enque(Sim_event ev)
+ {
+ System.out.println(super.get_name() + " enque() + at time = " + GridSim.clock());
+ q_.add( ev.get_data() );
+ if (q_.size() == 1) {
+ sendInternalEvent(super.delay_ / super.MILLI_SEC); // delay in ms
+ }
+
+ if (((Packet)ev.get_data()).getTag() == GridSimTags.FLOW_SUBMIT) {
+ registerFlow((Packet)ev.get_data());
+ }
+ }
+
+ /**
+ * Sends a packet to the next destination
+ * @param np a packet
+ * @pre np != null
+ * @post $none
+ */
+ private synchronized void deque(Packet np)
+ {
+ int dest = getNextHop(np);
+ if (dest == -1) {
+ return;
+ }
+
+ // other side is a Sim_entity
+ int tag = 0;
+ if (dest == outEnd2_ || dest == outEnd1_)
+ {
+ // for junk packets only
+ if (np.getTag() == GridSimTags.JUNK_PKT) {
+ tag = GridSimTags.JUNK_PKT;
+ }
+ // for other packets
+ else {
+ tag = GridSimTags.PKT_FORWARD;
+ }
+ }
+ // other side is a GridSim entity
+ else {
+ tag = np.getTag();
+ }
+
+ if (np.getTag() == GridSimTags.FLOW_RETURN) {
+ System.out.println("Dereg flow # " + np.getID() +" here");
+ deregisterFlow(np);
+ }
+
+ // sends the packet
+ super.sim_schedule(dest, GridSimTags.SCHEDULE_NOW, tag, np);
+ System.out.println(super.get_name() + " deque() + at time = " + GridSim.clock());
+
+ }
+
+ /**
+ * Determines which end to send the event to
+ * since sending entities are of the form Output_entityName.
+ * We need to check whether the source name ends with either end1 or end2
+ * the other end is the destination
+ * @param np a packet
+ * @pre np != null
+ * @post $none
+ */
+ private synchronized int getNextHop(Packet np)
+ {
+ int dest = -1;
+ int src = np.getLast();
+
+ // check if source is from outEnd1_
+ if (src == outEnd1_) {
+ dest = inEnd2_;
+ }
+ // or source is from outEnd2_
+ else if (src == outEnd2_) {
+ dest = inEnd1_;
+ }
+
+ return dest;
+ }
+
+ /**
+ * Registers active flow to link, and link to flow
+ * active flows
+ * @pre $none
+ * @post $none
+ */
+ private synchronized void registerFlow(Packet np) {
+ System.out.println(super.get_name() + ".registerFlow(): registering flow #" + np.getID()
+ + " total of " + flows_.size() + " flows");
+
+ // Add flow to link
+ flows_.put(np.getID(), np );
+
+ // Register link to flow
+ ((FlowPacket)np).addLink(this);
+
+ // Check if this affects any existing flows
+ Iterator<Integer> flowsIter = flows_.keySet().iterator();
+ while(flowsIter.hasNext()) {
+ // If change in bandwidth affects an existing flow i.e. is < current bottleneck
+ if (this.getBaudRate() < ((FlowPacket) flows_.get(flowsIter.next())).getBandwidth_() &&
+ ((FlowPacket) flows_.get(flowsIter.next())).getID() != np.getID()) {
+ // Need to notify flow
+ System.out.println(super.get_name() + ".registerFlow(): flow #" + np.getID()
+ + " bottleneck now " + this.getBaudRate() + " at time " + GridSim.clock());
+ // I can notify directly as I have know the destId's!!!!
+ }
+ }
+
+
+
+ }
+
+ private synchronized void deregisterFlow(Packet np) {
+ FlowPacket fp = null;
+ if ((fp = (FlowPacket) flows_.remove(np.getID())) != null) {
+
+ System.out.println(super.get_name() + ".deregisterFlow() success flow # " + np.getID()
+ + " " + fp.getBandwidth_());
+ }
+ }
+
+ /**
+ * Returns available baudRate depending on number of
+ * active flows
+ * @pre $none
+ * @post $none
+ */
+ public synchronized double getBaudRate() {
+ if (flows_.size() != 0) {
+ System.out.println(super.get_name() + ".getBaudRate() Getting latest baud! " + (super.baudRate_)/(flows_.size()));
+ return (super.baudRate_)/(flows_.size());
+ } else {
+ System.out.println(super.get_name() + ".getBaudRate() Getting latest baud! " + (super.baudRate_));
+ return super.baudRate_;
+ }
+
+ }
+
+
+
+} // end class
+
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|