import java.util.Scanner; import java.io.IOException; import java.util.ArrayList; public class WFQ { public static double compute_VT_Rate(ArrayList[] Q, double[] w) { double r = 0.0; for (int i = 0; i < Q.length; i++) if ( Q[i].size() > 0 ) r += w[i]; return(1/r); } public static void printArrivals(double [] arrTime, int[] flowID, double[] packetLen) { for (int i = 0; i < arrTime.length; i++) System.out.println(" T = " + arrTime[i] + ", flow " + flowID[i] + ", length " + packetLen[i]); } public static void main(String[] args) throws IOException { Scanner in = new Scanner(System.in); int i, j, k; int nFlows; // # Flows double[] w; // w[i] = weight of flow i ArrayList Q[]; // Queue[i] = packet queue of flow i int nArrs; // # Arrivals double [] arrTime; // arrTime[i] = arrival time of packet i int[] flowID; // flowID[i] = ID of the flow of packet i double[] packetLen; // packetLen[i] = Norm. length of packet i double nextClockValue = 0.0; System.out.print("# flows = "); nFlows = in.nextInt(); w = new double[nFlows]; Q = new ArrayList[nFlows]; for (i = 0; i < nFlows; i++) { System.out.print("Weight of flow " + i + " = "); w[i] = in.nextDouble(); Q[i] = new ArrayList(); } System.out.print("# Arrivals = "); nArrs = in.nextInt(); arrTime = new double[nArrs]; flowID = new int[nArrs]; packetLen = new double[nArrs]; for (i = 0; i < nArrs; i++) { System.out.print("Arrival time " + i + " = "); arrTime[i] = in.nextDouble(); System.out.print("Flow ID " + i + " = "); flowID[i] = in.nextInt(); System.out.print("Packet len " + i + " = "); packetLen[i] = in.nextDouble(); } printArrivals(arrTime, flowID, packetLen); System.out.println("Begin WFQ computation"); /* *********************************************** WFQ Begins here *********************************************** */ double t = 0.0; // = Now, real time clock double vt = 0.0; // = Now, virtual time clock double vt_rate = 0.0; // = speed of virtual time clock QueueElem PacketQ = null; // ---------------------------------------- // Variables for packet Arrival // ---------------------------------------- int nextArrIndex = 0; double nextArrTime = -1.0; int nextFlowID = -1; double nextPacketLen = -1.0; QueueElem q; // ---------------------------------------- // Variables for Flow's virtual clocks // ---------------------------------------- double[] VT_flow = new double[nFlows]; // Max flow TS double next_FFS_service_end_time; double last_update_time; // Last real time rem len updated for (i = 0; i < nFlows; i++) VT_flow[i] = 0.0; next_FFS_service_end_time = -1.0; // ------------------------ // Help variables // ------------------------ // ---------------------------- // First packet arrival // ---------------------------- nextArrTime = arrTime[nextArrIndex]; nextFlowID = flowID[nextArrIndex]; nextPacketLen = packetLen[nextArrIndex]; q = new QueueElem(); q.flowID = nextFlowID; q.packetLen = nextPacketLen; q.remaining_TransTime = q.packetLen; q.remaining_Virt_len = q.packetLen; q.last_update_time = t; // xxxx System.out.println(" ******* q.remaining_Virt_len = " + q.remaining_Virt_len); q.virtualFinTime = ( (VT_flow[nextFlowID] > vt) ? VT_flow[nextFlowID] : vt ) + q.remaining_Virt_len/w[nextFlowID]; VT_flow[nextFlowID] = q.virtualFinTime; Q[nextFlowID].add(q); // ********************************* // Insert in Packet Q // ********************************* PacketQ = List.insert(PacketQ, q); last_update_time = t; vt_rate = compute_VT_Rate(Q, w); // ---------------------------- // Next packet departure // ---------------------------- int currTransPacket_FlowID = nextFlowID; double currTransPacket_VirFinTime = q.virtualFinTime; double currTransPacket_RealFinTime; nextArrIndex++; nextArrTime = arrTime[nextArrIndex]; System.out.println("DEBUG: nextArrIndex = " + nextArrIndex); System.out.println("DEBUG: nextArrTime = " + nextArrTime); /* --------------------------------------------------------------- --------------------------------------------------------------- */ while (true) { System.out.println("=========================================="); System.out.println("last_update_time = " + last_update_time); List.print(PacketQ); System.out.println("\n\n\nt = " + t + " , vt = " + vt); if ( t - last_update_time > 0.0001 ) { // ******************* // Virtual progress // ******************* System.out.println("***************************"); System.out.println("Processing VIRTUAL progress\n"); System.out.println("vt_rate= " + vt_rate); for (i = 0; i < nFlows; i++) { if ( Q[i].size() > 0 ) { System.out.println("w[" + i + "] = " + w[i]); QueueElem x = Q[i].get(0); x.remaining_Virt_len -= w[i] * vt_rate * (t - x.last_update_time); x.last_update_time = t; System.out.println("Flow " + i + " remaining_Virt_len = " + x.remaining_Virt_len); System.out.println("Flow " + i + " remaining_Virt_len/w = " + x.remaining_Virt_len/w[i]); /* if ( x.remaining_Virt_len < 0.0001 ) Q[i].remove(0); */ } } System.out.println("====================================="); // ******************* // Real progress // ******************* System.out.println("Processing REAL progress\n"); PacketQ.remaining_TransTime -= (t - last_update_time); System.out.println("!!!! Packet Q, remaining trans time = " + PacketQ.remaining_TransTime); /* if ( PacketQ.remaining_TransTime < 0.0001 ) { PacketQ = List.delete(PacketQ); if ( PacketQ != null ) { PacketQ.remaining_TransTime = PacketQ.packetLen; PacketQ.last_update_time = t; } } */ // ******************************** // Remember the current time and compute curret VT rate // ******************************** last_update_time = t; vt_rate = compute_VT_Rate(Q, w); } System.out.println("--------------------------------"); // ---------------------------------------------------------- // Get next transmitted packet // ---------------------------------------------------------- List.print(PacketQ); /* if ( PacketQ != null && PacketQ.remaining_TransTime < 0.0001 ) { PacketQ = List.delete(PacketQ); if ( PacketQ != null ) { PacketQ.remaining_TransTime = PacketQ.packetLen; PacketQ.last_update_time = t; } } */ if ( PacketQ != null ) currTransPacket_RealFinTime = t + PacketQ.remaining_TransTime; else currTransPacket_RealFinTime = 999999999.0; // System.out.println("+++ Next packet departure time = " // + currTransPacket_RealFinTime); // ---------------------------------------------------------- // Get next FFS finish time // ---------------------------------------------------------- vt_rate = compute_VT_Rate(Q, w); // System.out.println("vt_rate = " + vt_rate ); next_FFS_service_end_time = 9999999.0; // Cheap trick for ( i = 0; i < nFlows; i++ ) { double h; double transmit_rate; if ( Q[i].size() > 0 ) { h = Q[i].get(0).remaining_Virt_len; System.out.println("Flow " + i + " Rem. virt len = " + h); h = h / w[i]; System.out.println("Flow " + i + " Rem. virtual transmit time = " + h); if ( h < next_FFS_service_end_time ) next_FFS_service_end_time = h; } } next_FFS_service_end_time += t; // System.out.println("+++ Next FFS service end time = " // + next_FFS_service_end_time); // ****************************************************************** if ( nextArrTime > 0 ) { System.out.println("+++ Next arrival time = " + nextArrTime + " (flow ID = " + nextFlowID + ", packet len = " + nextPacketLen + ")"); } System.out.println("+++ Next packet departure time = " + currTransPacket_RealFinTime); System.out.println("+++ Next FFS service end time = " + next_FFS_service_end_time); // ****************************************************************** System.out.println("--------------------------------"); // ************************************** // Test first !!! // ************************************** boolean Arrival, Departure, FFS_fin; Arrival = Departure = FFS_fin = false; if ((nextArrTime >= 0 && nextArrTime <= currTransPacket_RealFinTime) && (nextArrTime >= 0 && nextArrTime <= next_FFS_service_end_time) && nextFlowID < nArrs ) { Arrival = true; } if ((nextArrTime <-1.0|| currTransPacket_RealFinTime <= nextArrTime) && currTransPacket_RealFinTime <= next_FFS_service_end_time ) { Departure = true; } if ((nextArrTime <-1.0|| next_FFS_service_end_time <= nextArrTime) && next_FFS_service_end_time <= currTransPacket_RealFinTime ) { FFS_fin = true; } // ************************************** // Check if next event = packet arrival // ************************************** if ( Arrival ) { System.out.println("***** Processing packet arrival"); // Packet arrival System.out.println("nextArrIndex = " + nextArrIndex); System.out.println("nextArrTime = " + nextArrTime); nextFlowID = flowID[nextArrIndex]; nextPacketLen = packetLen[nextArrIndex]; q = new QueueElem(); q.flowID = nextFlowID; q.packetLen = nextPacketLen; q.remaining_TransTime = q.packetLen; q.remaining_Virt_len = q.packetLen; q.last_update_time = nextArrTime; q.virtualFinTime = ( (VT_flow[nextFlowID] > vt) ? VT_flow[nextFlowID] : vt ) + q.remaining_Virt_len/w[nextFlowID]; VT_flow[nextFlowID] = q.virtualFinTime; Q[nextFlowID].add(q); // ********************************* // Insert in Packet Q // ********************************* PacketQ = List.insert(PacketQ, q); nextClockValue = nextArrTime; nextArrIndex++; if ( nextArrIndex < nArrs ) nextArrTime = arrTime[nextArrIndex]; else nextArrTime = 9999999.0; } System.out.println("Queue before processing:"); List.print(PacketQ); // ************************************** // Check if next event = packet departure // ************************************** if ( Departure ) { System.out.println("***** Processing packet departure"); PacketQ = List.delete(PacketQ); if ( PacketQ != null ) { PacketQ.remaining_TransTime = PacketQ.packetLen; PacketQ.last_update_time = t; } System.out.println("--- After Processing packet departure"); List.print(PacketQ); System.out.println("-------------------------------------"); nextClockValue = currTransPacket_RealFinTime; } // ************************************** // Check if next event = FFS fin packet // ************************************** if ( FFS_fin ) { System.out.println("***** Processing FFS Finish"); nextClockValue = currTransPacket_RealFinTime; for ( i = 0; i < nFlows; i++ ) { double h; if ( Q[i].size() > 0 ) { if ( Q[i].get(0).virtualFinTime >= vt ) Q[i].remove(0); } } } vt = vt_rate * (nextClockValue - t); t = nextClockValue; if (PacketQ == null ) { System.out.println("t = " + t + " ----- END"); break; } } } }