From: <sul...@us...> - 2008-08-03 05:56:20
|
Revision: 193 http://gridsim.svn.sourceforge.net/gridsim/?rev=193&view=rev Author: sulistio Date: 2008-08-03 05:56:30 +0000 (Sun, 03 Aug 2008) Log Message: ----------- add a new package about the network flow functionality (initially was done in $SVN/branches/gridsim4.0-branch2). Note that this was done by James Broberg. Added Paths: ----------- trunk/source/gridsim/net/flow/ trunk/source/gridsim/net/flow/FilterFlow.java trunk/source/gridsim/net/flow/Flow.java trunk/source/gridsim/net/flow/FlowInput.java trunk/source/gridsim/net/flow/FlowLink.java trunk/source/gridsim/net/flow/FlowOutput.java trunk/source/gridsim/net/flow/FlowPacket.java trunk/source/gridsim/net/flow/FlowRouter.java Added: trunk/source/gridsim/net/flow/FilterFlow.java =================================================================== --- trunk/source/gridsim/net/flow/FilterFlow.java (rev 0) +++ trunk/source/gridsim/net/flow/FilterFlow.java 2008-08-03 05:56:30 UTC (rev 193) @@ -0,0 +1,99 @@ +/* + * 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 + * + */ + +package gridsim.net.flow; + +import eduni.simjava.Sim_predicate; +import eduni.simjava.Sim_event; + + +/** + * Look for a specific incoming event that matches a given event tag name and a + * flow id. Incoming events with a matching tag name <b>must</b> + * contain a data object of type + * <tt>Integer</tt>, where <tt>Integer</tt> stores the flow id. + * <br><br> + * + * This class is used by {@link eduni.simjava.Sim_system} + * to select or filter an event already present in the entity's deferred queue + * (incoming buffer), or used to selectively wait for a future event. + * <br> <br> + * + * + * + * @author James Broberg + * @since GridSim Toolkit 5.0 + * @invariant $none + */ +public class FilterFlow extends Sim_predicate +{ + private int tag_; // event tag to be matched + private int flowID_; // event or flow ID + + + /** + * Finds an incoming events that matches with the given flow ID and + * event tag name + * @param flowID a unique flow ID to differentiate + * itself among other events with the same tag name + * @param tag a matching event tag name + * @pre $none + * @post $none + */ + public FilterFlow(int flowID, int tag) + { + tag_ = tag; + flowID_ = flowID; + } + + /** + * Checks whether an event matches the required constraints or not.<br> + * NOTE: This method is not used directly by the user. Instead, it is + * called by {@link eduni.simjava.Sim_system}. + * + * @param ev an incoming event to compare with + * @return <tt>true</tt> if an event matches, <tt>false</tt> otherwise + * @pre ev != null + * @post $none + */ + public boolean match(Sim_event ev) + { + if (ev == null) { + return false; + } + + boolean result = false; + try + { + // find an event with a matching tag first + if ( tag_ == ev.get_tag() ) + { + Object obj = ev.get_data(); + + // if the event's data contains the correct data + if (obj instanceof Integer) + { + int id = (Integer)obj; + + // if the data contains the correct ID or value + if (id == flowID_) { + result = true; + } + } + } + } + catch (Exception e) { + result = false; + } + + return result; + } + +} // end class Added: trunk/source/gridsim/net/flow/Flow.java =================================================================== --- trunk/source/gridsim/net/flow/Flow.java (rev 0) +++ trunk/source/gridsim/net/flow/Flow.java 2008-08-03 05:56:30 UTC (rev 193) @@ -0,0 +1,118 @@ +/* + * ** Network and Service Differentiation Extensions to GridSim 4.0 ** + * + * James Broberg + * + * August 2007 + * + * Licence: GPL - http://www.gnu.org/copyleft/gpl.html + * + * Flow.java - Interface of a Network Flow. + * + */ + +package gridsim.net.flow; + + +/** + * This the structure for network flows. + * + * @since GridSim Toolkit 4.0 + * @author James Broberg, The University of Melbourne + */ +public interface Flow +{ + /** + * Returns a string describing this flow in detail. + * @return description of this flow + * @pre $none + * @post $none + */ + String toString(); + + /** + * Returns the size of this flow + * @return size of the flow + * @pre $none + * @post $none + */ + long getSize(); + + /** + * Sets the size of this flow + * @param size size of the flow + * @return <tt>true</tt> if it is successful, <tt>false</tt> otherwise + * @pre size >= 0 + * @post $none + */ + boolean setSize(long size); + + /** + * Returns the destination id of this flow. + * @return destination id + * @pre $none + * @post $none + */ + int getDestID(); + + /** + * Returns the ID of this flow + * @return flow ID + * @pre $none + * @post $none + */ + int getID(); + + /** + * Returns the ID of the source of this flow. + * @return source id + * @pre $none + * @post $none + */ + int getSrcID(); + + /** + * Gets the network service type of this flow + * @return the network service type + * @pre $none + * @post $none + */ + int getNetServiceType(); + + /** + * Sets the network service type of this flow. + * <p> + * By default, the service type is 0 (zero). It is depends on the packet + * scheduler to determine the priority of this service level. + * @param serviceType this flow's service type + * @pre serviceType >= 0 + * @post $none + */ + void setNetServiceType(int serviceType); + + /** + * Gets an entity ID from the last hop that this packet has traversed. + * @return an entity ID + * @pre $none + * @post $none + */ + int getLast(); + + /** + * Sets an entity ID from the last hop that this packet has traversed. + * @param last an entity ID from the last hop + * @pre last > 0 + * @post $none + */ + void setLast(int last); + + /** + * Gets this flow tag + * @return this flow tag + * @pre $none + * @post $none + */ + int getTag(); + +} // end interface + Added: trunk/source/gridsim/net/flow/FlowInput.java =================================================================== --- trunk/source/gridsim/net/flow/FlowInput.java (rev 0) +++ trunk/source/gridsim/net/flow/FlowInput.java 2008-08-03 05:56:30 UTC (rev 193) @@ -0,0 +1,478 @@ +/* + * ** Network and Service Differentiation Extensions to GridSim 4.0 ** + * + * Author: James Broberg (based on Input.java) + * + * March 2007 + * + * Licence: GPL - http://www.gnu.org/copyleft/gpl.html + * + * FlowInput.java - Simulates a network input port + * + */ + +package gridsim.net.flow; + +import gridsim.*; +import gridsim.net.*; +import gridsim.util.TrafficGenerator; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; + +import eduni.simjava.*; + +/** + * GridSim FlowInput class defines a port through which a simulation entity + * receives data from the simulated network. + * <p> + * It maintains an event queue + * to serialize the data-in-flow and delivers to its parent entity. + * It accepts messages that comes from GridSim entities 'FlowOutput' entity + * and passes the same to the GridSim entity. + * It simulates Network communication delay depending on current bottleneck Baud rate + * and data length. Simultaneous inputs can be modeled using multiple + * instances of this class. + * + * @author James Broberg + * @since GridSim Toolkit 5.0 + * @invariant $none + */ +public class FlowInput extends Sim_entity implements NetIO +{ + private Sim_port inPort_; + private Link link_; + private double baudRate_; + private static final int BITS = 8; // 1 byte = 8 bits + private final int SIZE = 8; // 1 byte in bits + + + private HashMap<Integer, Packet> activeFlows_; // stores a list of active Flows + + + /** + * Allocates a new FlowInput 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 FlowInput(String name, double baudRate) throws NullPointerException + { + super(name); + this.baudRate_ = baudRate; + link_= null; + + inPort_ = new Sim_port("input_buffer"); + super.add_port(inPort_); + + activeFlows_ = null; + + } + + /** + * Sets the FlowInput entities link. This should be used only if the network + * extensions are being used. + * @param link the link to which this FlowInput entity should send data + * @pre link != null + * @post $none + */ + public void addLink(Link link) + { + this.link_ = link; + baudRate_ = link_.getBaudRate(); + 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 value >= 0.0 + * @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 value >= 0.0 + * @post $result >= 0.0 + */ + public double realIO(double value) { + return GridSimRandom.realIO(value); + } + + /** + * This is an empty method and only applicable to + * {@link gridsim.net.FlowOutput} class. + * @param gen a background traffic generator + * @param userName a collection of user entity name (in String object). + * @return <tt>false</tt> since this method is not used by this class. + * @pre gen != null + * @pre userName != null + * @post $none + * @see gridsim.net.Output + */ + public boolean setBackgroundTraffic(TrafficGenerator gen, + Collection userName) + { + return false; + } + + /** + * This is an empty method and only applicable to + * {@link gridsim.net.Output} class. + * @param gen a background traffic generator + * @return <tt>false</tt> since this method is not used by this class. + * @pre gen != null + * @post $none + * @see gridsim.net.Output + */ + public boolean setBackgroundTraffic(TrafficGenerator gen) + { + return false; + } + + /** + * 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() + { + // Process events + Object obj = null; + while ( Sim_system.running() ) + { + Sim_event ev = new Sim_event(); + super.sim_get_next(ev); // get the next event in the queue + obj = ev.get_data(); // get the incoming data + + System.out.println(super.get_name() + ".body(): ev.get_tag() is " + ev.get_tag()); + System.out.println(super.get_name() + ".body(): ev.get_src() is " + ev.get_src()); + + // if the simulation finishes then exit the loop + if (ev.get_tag() == GridSimTags.END_OF_SIMULATION) { + break; + // Check forecast of active flow and pass it onto Entity if still active + } else if(ev.get_tag() == GridSimTags.FLOW_HOLD) { + System.out.println(super.get_name() + ".body(): checkForecast() + at time = " + GridSim.clock()); + checkForecast(ev); + // Update flow duration forecast as a flow's bottleneck bandwidth has changed + } else if (ev.get_tag() == GridSimTags.FLOW_UPDATE) { + System.out.println(super.get_name() + ".body(): updateForecast() + at time = " + GridSim.clock()); + updateForecast(ev); + // if this entity is not connected in a network topology + } else if (obj != null && obj instanceof IO_data) { + System.out.println(super.get_name() + ".body(): getDataFromEvent() + at time = " + GridSim.clock()); + getDataFromEvent(ev); + // if this entity belongs to a network topology + } else if (obj != null && link_ != null) { + System.out.println(super.get_name() + ".body(): getDataFromLink() + at time = " + GridSim.clock()); + getDataFromLink(ev); + } + + ev = null; // reset to null for gc to collect + } + + System.out.println(super.get_name() + ":%%%% Exiting body() at time " + + GridSim.clock() ); + } + + /** + * Check the forecast of a flow, and send data to output port if flow still exists + * + * @param ev the flow hold notification event + * @pre ev != null + * @post $none + */ + private void checkForecast(Sim_event ev) { + int pktID = (Integer) ev.get_data(); // ID of flow to be checked + FlowPacket fp = null; // Reference to flow packet that needs forecast update + + System.out.println(super.get_name() + ".checkForecast(): checking pkt id # " + pktID); + + // If flow hasn't already finished, send it to inPort + if ((fp = (FlowPacket) activeFlows_.get(pktID)) != null) { + Object data = fp.getData(); + IO_data io = new IO_data( data, fp.getSize(), + inPort_.get_src()); + super.sim_schedule(inPort_, GridSimTags.SCHEDULE_NOW, fp.getTag() , io.getData()); + activeFlows_.remove(pktID); + + System.out.println(super.get_name() + ".checkForecast(): flow came from " + GridSim.getEntityName(fp.getSrcID()) + + " heading to " + GridSim.getEntityName(fp.getDestID())); + + // Deregister flow on all active links + Iterator it = (fp.getLinks_()).iterator(); + while (it.hasNext()) { + FlowLink fl = (FlowLink) it.next(); + fl.deregisterFlow(fp); + } + + } else { + System.out.println(super.get_name() + ".checkForecast(): pkt id # " + pktID + " already removed"); + + } + + } + + /** + * Update the forecast of a flow by deleting the old forecast and scheduling a new flow hold + * event in the future with the corrected forecast (based on new bottleneck bandwidth and + * the amount of flow already sent) + * + * @param ev the flow update notification event + * @pre ev != null + * @post $none + */ + private void updateForecast(Sim_event ev) { + int pktID = (Integer) ev.get_data(); // ID of flow to be updated + FlowPacket fp = null; // Reference to flow packet that needs forecast update + double duration = 0.0; // New forecast duration from current Gridsim.clock() + long remSizeOld = 0; // Previous remaining size + double bandwidthOld = 0.0; // Previous bottleneck BW + int sourceID = ev.get_src(); // ID of source of notification (FlowLink) + int cancelledFlow = 0; // Count of canceled future events that match old forecast + + System.out.println(super.get_name() + ".updateForecast(): updating pkt id # " + pktID); + + // If flow hasn't already finished and been cleared... + if ((fp = (FlowPacket) activeFlows_.get(pktID)) != null) { + remSizeOld = fp.getRemSize(); + bandwidthOld = fp.getBandwidth_(); + System.out.println(super.get_name() + "updateForecast(): rem size is " + remSizeOld + + "BW old is " + bandwidthOld + " last update " + fp.getUpdateTime()); + Iterator it = (fp.getLinks_()).iterator(); + + // Find the source link of this notification and the associated bottleneck bandwidth + while (it.hasNext()) { + FlowLink fl = (FlowLink) it.next(); + if (fl.get_id() == sourceID) { + fp.setBandwidth_(fl.getBaudRate()); + fp.setBottleneckID(sourceID); + } + } + + fp.setRemSize((long)((remSizeOld) - ((GridSim.clock()-fp.getUpdateTime())*(bandwidthOld/BITS)))); + duration = (fp.getRemSize()*BITS)/fp.getBandwidth_(); + System.out.println(super.get_name() + " new forecast end time is " + (GridSim.clock() + duration)); + + // Find old forecast and delete it! + FilterFlow filter = new FilterFlow(fp.getID(), GridSimTags.FLOW_HOLD); + cancelledFlow = this.sim_cancel(filter, null); + + if (cancelledFlow != 0) { + System.out.println(super.get_name() + ".updateForecast(): old forecast cancelled #matches " + + cancelledFlow); + } + + System.out.println(super.get_name() + " setting updated forecast for packet #" + fp.getID()); + // Make a note of the time when this forecast update was performed + fp.setUpdateTime(GridSim.clock()); + // Set new future event with the correct finish time + super.sim_schedule(super.get_id(), duration, GridSimTags.FLOW_HOLD , new Integer(fp.getID())); + + } + } + + /** + * Process incoming event for data without using the network extension + * @param ev a Sim_event object + * @pre ev != null + * @post $none + */ + private void getDataFromEvent(Sim_event ev) + { + IO_data io = (IO_data) ev.get_data(); + + // if the sender is not part of the overall network topology + // whereas this entity is, then need to return back the data, + // since it is not compatible. + if (link_ != null) + { + // outName = "Output_xxx", where xxx = sender entity name + String outName = GridSim.getEntityName( ev.get_src() ); + + // NOTE: this is a HACK job. "Output_" has 7 chars. So, + // the idea is to get only the entity name by removing + // "Output_" word in the outName string. + String name = outName.substring(7); + + // if the sender is not system GIS then ignore the message + if (GridSim.getEntityId(name) != GridSim.getGridInfoServiceEntityId()) + { + // sends back the data to "Input_xxx", where + // xxx = sender entity name. If not sent, then the sender + // will wait forever to receive this data. As a result, + // the whole simulation program will be hanged or does not + // terminate successfully. + int id = GridSim.getEntityId("Input_" + name); + super.sim_schedule(id, 0.0, ev.get_tag(), io); + + // print an error message + System.out.println(super.get_name() + ".body(): Error - " + + "incompatible message protocol."); + System.out.println(" Sender: " + name + " is not part " + + "of this entity's network topology."); + System.out.println(" Hence, sending back the received data."); + System.out.println(); + return; + } + } + + // NOTE: need to have a try-catch statement. This is because, + // if the above if statement holds, then Input_receiver will send + // back to Input_sender without going through Output_receiver entity. + // Hence, a try-catch is needed to prevent exception of wrong casting. + try + { + // Simulate Transmission Time after Receiving + // Hold first then dispatch + double senderBaudRate = ( (FlowOutput) + Sim_system.get_entity(ev.get_src()) ).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_, senderBaudRate); + 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); // receiving time + } + catch (Exception e) { + // .... empty + } + + // Deliver Event to the entity (its parent) to which + // it is acting as buffer + super.sim_schedule( inPort_, GridSimTags.SCHEDULE_NOW, + ev.get_tag(), io.getData() ); + } + + /** + * Process incoming events from senders that are using the network + * extension + * @param ev a Sim_event object + * @pre ev != null + * @post $none + */ + 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; + } + + 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; + } + + System.out.println(super.get_name() + ".getDataFromLink() Time now " + GridSim.clock() + + " bottleneck is " + 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 || pkt.getTag() == GridSimTags.GRIDLET_SUBMIT || + pkt.getTag() == GridSimTags.GRIDLET_SUBMIT_ACK || pkt.getTag() == GridSimTags.GRIDLET_RETURN + || pkt.getTag() == GridSimTags.JUNK_PKT) { + np.setStartTime(GridSim.clock()); + np.setUpdateTime(GridSim.clock()); + 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())); + System.out.println(super.get_name() + ".getDataFromLink() initial forecast flow end at " + (GridSim.clock() + + duration)); + return; + } + + // convert the packets into IO_data + Object data = np.getData(); + IO_data io = new IO_data( data, np.getSize(), + inPort_.get_dest() ); + + // send the data into entity input port + super.sim_schedule(inPort_, GridSimTags.SCHEDULE_NOW, tag, + io.getData() ); + + + } + } + } + + /** + * Processes a ping request + * @param pkt a packet for pinging + * @pre pkt != null + * @post $none + */ + private void processPingRequest(InfoPacket pkt) + { + // add more information to ping() packet + pkt.addHop( inPort_.get_dest() ); + pkt.addEntryTime( GridSim.clock() ); + + IO_data io = new IO_data( pkt, pkt.getSize(), inPort_.get_dest() ); + + // send this ping() packet to the entity + super.sim_schedule(inPort_, GridSimTags.SCHEDULE_NOW, + pkt.getTag(), io.getData()); + } + +} // end class + Added: trunk/source/gridsim/net/flow/FlowLink.java =================================================================== --- trunk/source/gridsim/net/flow/FlowLink.java (rev 0) +++ trunk/source/gridsim/net/flow/FlowLink.java 2008-08-03 05:56:30 UTC (rev 193) @@ -0,0 +1,525 @@ +/* + * ** Network and Service Differentiation Extensions to GridSim 4.0 ** + * + * Author: James Broberg + * + * March 2007 + * + * Licence: GPL - http://www.gnu.org/copyleft/gpl.html + * + * FlowLink.java - Simulates a network link with active flows (based on SimpleLink.java) + * + */ + +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 partially based + * on SimpleLink.java by Gokul Poduval & Chen-Khong Tham + * + * @invariant $none + * @since GridSim Toolkit 5.0 + * @author James Broberg, The University of Melbourne + */ + +public class FlowLink extends Link +{ + private Vector q_; + private HashMap activeFlows_; // Stores references to flows that are currently active on this link + 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(); + activeFlows_ = 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; + } + + inEnd1_ = GridSim.getEntityId( "Input_" + end1.get_name() ); + outEnd1_ = GridSim.getEntityId( "Output_" + end1.get_name() ); + + // 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( "Input_" + end2.get_name() ); + outEnd2_ = GridSim.getEntityId( "Output_" + end2.get_name() ); + + // if end1 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("Input_" + 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("Input_" + 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); + + System.out.println(super.get_name() + ".body(): ev.get_tag() is " + ev.get_tag()); + System.out.println(super.get_name() + ".body(): ev.get_src() is " + ev.get_src()); + + // 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, sends an internal event to itself and registers the flow + * @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()); + int tag = ((Packet)ev.get_data()).getTag(); + // Register passing flow, gridlet or junk as active on this link + if (tag == GridSimTags.FLOW_SUBMIT || tag == GridSimTags.GRIDLET_SUBMIT || + tag == GridSimTags.GRIDLET_SUBMIT_ACK || tag == GridSimTags.GRIDLET_RETURN || + tag == GridSimTags.JUNK_PKT) { + registerFlow((Packet)ev.get_data()); + } + + q_.add( ev.get_data() ); + if (q_.size() == 1) { + sendInternalEvent(super.delay_ / super.MILLI_SEC); // delay in ms + } + + + } + + /** + * Sends a packet to the next destination + * @param np a packet + * @pre np != null + * @post $none + */ + private synchronized void deque(Packet np) + { + + System.out.println(super.get_name() + ".deque() for packet " + np.getID() +" here"); + System.out.println(super.get_name() + ".deque() packet " + np.toString()); + + + int dest = getNextHop(np); + if (dest == -1) { + System.out.println(super.get_name() + ".deque() here3"); + return; + } + + // other side is a Sim_entity + int tag = 0; + if (dest == outEnd2_ || dest == outEnd1_) + { + System.out.println(super.get_name() + ".deque() here1"); + + // 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 { + System.out.println(super.get_name() + ".deque() here2"); + + tag = np.getTag(); + } + + // 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 the link, and the link to flow. + * Notifies the destination of any active flows if the bottleneck + * bandwidth is changed. + * @param np a packet + * @pre $none + * @post $none + */ + private synchronized void registerFlow(Packet np) { + + FlowPacket tempFlow = null; + + // Add flow to link + activeFlows_.put(np.getID(), np ); + + System.out.println(super.get_name() + ".registerFlow(): registering flow #" + np.getID() + + " total of " + activeFlows_.size() + " flows"); + + // Register link to flow + ((FlowPacket)np).addLink(this); + + // Check if this affects any existing flows + Iterator<Integer> flowsIter = activeFlows_.keySet().iterator(); + while(flowsIter.hasNext()) { + tempFlow = (FlowPacket) activeFlows_.get(flowsIter.next()); + // If change in bandwidth affects an existing flow i.e. is < current bottleneck + if (this.getBaudRate() < tempFlow.getBandwidth_() && tempFlow.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 know the destId's!!!! + System.out.println(super.get_name() + ".registerFlow(): updating flow #" + tempFlow.getID() + + " destination " + tempFlow.getDestID()); + super.sim_schedule(GridSim.getEntityId("Input_" + + GridSim.getEntityName(tempFlow.getDestID())), GridSimTags.SCHEDULE_NOW, + GridSimTags.FLOW_UPDATE, new Integer(tempFlow.getID())); + } + } + } + + /** + * Deregisters active flow on link. Notifies the destination of any active + * flows if the bottleneck bandwidth is changed. + * @param np a packet + * @pre $none + * @post $none + */ + public synchronized void deregisterFlow(Packet np) { + FlowPacket fp = null; + FlowPacket tempFlow; + + // If the flow hasn't been removed already, remove from active flow list + if ((fp = (FlowPacket) activeFlows_.remove(np.getID())) != null) { + + System.out.println(super.get_name() + ".deregisterFlow() success flow # " + np.getID() + + " " + fp.getBandwidth_()); + + // Check if this affects any existing flows + Iterator<Integer> flowsIter = activeFlows_.keySet().iterator(); + while(flowsIter.hasNext()) { + tempFlow = (FlowPacket) activeFlows_.get(flowsIter.next()); + // If change in bandwidth affects an existing flow i.e. is > current bottleneck + // AND this link is the particular flow's bottleneck + if (this.getBaudRate() > tempFlow.getBandwidth_() && tempFlow.getID() != np.getID() && + tempFlow.getBottleneckID() == this.get_id()) { + // Need to notify flow + System.out.println(super.get_name() + ".deregisterFlow(): flow #" + np.getID() + + " bottleneck now " + this.getBaudRate() + " at time " + GridSim.clock()); + // I can notify directly as I know the destId's!!!! + System.out.println(super.get_name() + ".deregisterFlow(): updating flow #" + tempFlow.getID() + + " destination " + tempFlow.getDestID()); + super.sim_schedule(GridSim.getEntityId("Input_" + + GridSim.getEntityName(tempFlow.getDestID())), GridSimTags.SCHEDULE_NOW, + GridSimTags.FLOW_UPDATE, new Integer(tempFlow.getID())); + } + + } + } + } + + /** + * Returns available baudRate depending on number of + * active flows (MIN_MAX bandwidth sharing model) + * @pre $none + * @post $none + */ + public synchronized double getBaudRate() { + if (activeFlows_.size() != 0) { + System.out.println(super.get_name() + ".getBaudRate() Getting latest baud! " + (super.baudRate_)/(activeFlows_.size())); + return (super.baudRate_)/(activeFlows_.size()); + } else { + System.out.println(super.get_name() + ".getBaudRate() Getting latest baud! " + (super.baudRate_)); + return super.baudRate_; + } + + } + + + +} // end class + Added: trunk/source/gridsim/net/flow/FlowOutput.java =================================================================== --- trunk/source/gridsim/net/flow/FlowOutput.java (rev 0) +++ trunk/source/gridsim/net/flow/FlowOutput.java 2008-08-03 05:56:30 UTC (rev 193) @@ -0,0 +1,714 @@ +/* + * ** Network and Service Differentiation Extensions to GridSim 4.0 ** + * + * Author: James Broberg + * + * March 2007 + * + * Licence: GPL - http://www.gnu.org/copyleft/gpl.html + * + * FlowOutput.java - Simulates a network output port + * + */ + +package gridsim.net.flow; + +import gridsim.*; +import gridsim.net.*; +import gridsim.util.*; + +import eduni.simjava.*; + +import java.util.*; +import java.util.Random; + + +/** + * GridSim FlowOutput 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 FlowInput entity to simulate network + * communication delay. Simultaneous outputs can be modeled by using multiple + * instances of this class + * + * @author James Broberg + * @since GridSim Toolkit 5.0 + * @invariant $none + */ +public class FlowOutput 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 static int pktID_ = 0; // packet ID counter + private Vector flowList_; // store a list of packets + 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 + + private Random rnd; // Random number generator to generate unique + // flow ID's + + + /** + * Allocates a new FlowOutput 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 FlowOutput(String name, double baudRate) throws NullPointerException + { + super(name); + this.baudRate_ = baudRate; + link_ = null; + flowList_ = 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; + + rnd = new Random(); + } + + /** + * 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(); + flowList_ = new Vector(); + } + + /** + * 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() + { + // 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()); + System.out.println(super.get_name() + ".body(): ev.get_src() is " + ev.get_src()); + + // handle different types of incoming events + switch ( ev.get_tag() ) + { + case GridSimTags.SEND_PACKET: + sendPacket(); + break; + + // submit ping() request + case GridSimTags.INFOPKT_SUBMIT: + sendInfoPacket(ev); + break; + + // replying ping() request from another entity + case GridSimTags.INFOPKT_RETURN: + returnInfoPacket(ev); + break; + + // activate background traffic + case GridSimTags.JUNK_PKT: + generateBackgroundTraffic(); + break; + + default: + defaultSend(ev, gisID, statID, shutdownID); + break; + } + } + } + + /** + * Generates few junk flows 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 + + + /********* // 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) ); + *********/ + + convertIntoPacket(size, 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) ); + *********/ + + convertIntoPacket(size, 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 = ( (FlowInput) + 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. The data is encapsulated in a single FlowPacket. + * After this it calls enque() to queue these flows 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(); + + // last packet contains the actual data + FlowPacket np = null; + np = new FlowPacket(obj,rnd.nextInt(Integer.MAX_VALUE),size,tag,super.get_id... [truncated message content] |