|
From: <mar...@us...> - 2008-02-14 12:00:17
|
Revision: 102
http://gridsim.svn.sourceforge.net/gridsim/?rev=102&view=rev
Author: marcos_dias
Date: 2008-02-14 04:00:22 -0800 (Thu, 14 Feb 2008)
Log Message:
-----------
This update includes a bug fix in the easy backfilling policy and a preliminary version of a multiple queue backfilling policy.
Modified Paths:
--------------
branches/gridsim4.0-branch3/examples/examples/workload/parallel/TurboExampleEasy01.java
branches/gridsim4.0-branch3/examples/examples/workload/parallel/TurboExampleMultiEBQueues01.java
branches/gridsim4.0-branch3/source/gridsim/GridResource.java
branches/gridsim4.0-branch3/source/gridsim/gui/ResourceWindow.java
branches/gridsim4.0-branch3/source/gridsim/turbo/AvailabilityProfile.java
branches/gridsim4.0-branch3/source/gridsim/turbo/CBParallelSpaceShared.java
branches/gridsim4.0-branch3/source/gridsim/turbo/EBParallelSpaceShared.java
branches/gridsim4.0-branch3/source/gridsim/turbo/MultipleEasyBackfillingQueues.java
branches/gridsim4.0-branch3/source/gridsim/turbo/PERangeList.java
branches/gridsim4.0-branch3/source/gridsim/turbo/SSGridlet.java
branches/gridsim4.0-branch3/source/gridsim/turbo/TAllocPolicy.java
branches/gridsim4.0-branch3/source/gridsim/turbo/TResourceCharacteristics.java
Added Paths:
-----------
branches/gridsim4.0-branch3/examples/examples/workload/parallel/TurboExampleMultiEBQueues02.java
branches/gridsim4.0-branch3/source/gridsim/turbo/QueuePredicate.java
Modified: branches/gridsim4.0-branch3/examples/examples/workload/parallel/TurboExampleEasy01.java
===================================================================
--- branches/gridsim4.0-branch3/examples/examples/workload/parallel/TurboExampleEasy01.java 2008-02-12 05:46:26 UTC (rev 101)
+++ branches/gridsim4.0-branch3/examples/examples/workload/parallel/TurboExampleEasy01.java 2008-02-14 12:00:22 UTC (rev 102)
@@ -85,10 +85,10 @@
//////////////////////////////////////////
// Starts the simulation in debug mode
- GridSim.startGridSimulation(true);
+// GridSim.startGridSimulation(true);
// Start the simulation in normal mode
-// GridSim.startGridSimulation();
+ GridSim.startGridSimulation();
//////////////////////////////////////////
// Final step: Prints the Gridlets when simulation is over
Modified: branches/gridsim4.0-branch3/examples/examples/workload/parallel/TurboExampleMultiEBQueues01.java
===================================================================
--- branches/gridsim4.0-branch3/examples/examples/workload/parallel/TurboExampleMultiEBQueues01.java 2008-02-12 05:46:26 UTC (rev 101)
+++ branches/gridsim4.0-branch3/examples/examples/workload/parallel/TurboExampleMultiEBQueues01.java 2008-02-14 12:00:22 UTC (rev 102)
@@ -1,10 +1,14 @@
package examples.workload.parallel;
+import gridsim.AllocPolicy;
import gridsim.GridResource;
import gridsim.GridSim;
import gridsim.Machine;
import gridsim.MachineList;
+import gridsim.ResourceCalendar;
+import gridsim.ResourceCharacteristics;
+import gridsim.turbo.MultipleEasyBackfillingQueues;
import gridsim.turbo.TResourceCharacteristics;
import gridsim.util.Workload;
@@ -85,10 +89,10 @@
//////////////////////////////////////////
// Starts the simulation in debug mode
- GridSim.startGridSimulation(true);
+// GridSim.startGridSimulation(true);
// Start the simulation in normal mode
-// GridSim.startGridSimulation();
+ GridSim.startGridSimulation();
//////////////////////////////////////////
// Final step: Prints the Gridlets when simulation is over
@@ -143,6 +147,13 @@
TResourceCharacteristics resConfig = new TResourceCharacteristics(
arch, os, mList, TResourceCharacteristics.EB_PARALLEL_SPACE_SHARED,
time_zone, cost);
+
+ MultipleEasyBackfillingQueues policy = null;
+ try {
+ policy = new MultipleEasyBackfillingQueues(name, "Policy", 1);
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
//////////////////////////////////////////
// 6. Finally, we need to create a GridResource object.
@@ -160,10 +171,14 @@
// incorporates holidays. However, no holidays are set in this example
LinkedList holidays = new LinkedList();
GridResource gridRes = null;
+
+ ResourceCalendar resCalendar = new ResourceCalendar(time_zone,
+ peakLoad, offPeakLoad, holidayLoad, weekends,
+ holidays, seed);
+
try {
- gridRes = new GridResource(name, baud_rate, seed,
- resConfig, peakLoad, offPeakLoad, holidayLoad, weekends,
- holidays);
+ gridRes = new GridResource(name, baud_rate, resConfig,
+ resCalendar, policy);
}
catch (Exception e) {
e.printStackTrace();
Added: branches/gridsim4.0-branch3/examples/examples/workload/parallel/TurboExampleMultiEBQueues02.java
===================================================================
--- branches/gridsim4.0-branch3/examples/examples/workload/parallel/TurboExampleMultiEBQueues02.java (rev 0)
+++ branches/gridsim4.0-branch3/examples/examples/workload/parallel/TurboExampleMultiEBQueues02.java 2008-02-14 12:00:22 UTC (rev 102)
@@ -0,0 +1,247 @@
+
+package examples.workload.parallel;
+
+import gridsim.GridResource;
+import gridsim.GridSim;
+import gridsim.Machine;
+import gridsim.MachineList;
+import gridsim.ResourceCalendar;
+import gridsim.turbo.MultipleEasyBackfillingQueues;
+import gridsim.turbo.QueuePredicate;
+import gridsim.turbo.SSGridlet;
+import gridsim.turbo.TResourceCharacteristics;
+import gridsim.util.Workload;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.LinkedList;
+import java.util.Random;
+
+
+/**
+ * Test Driver class for this example
+ */
+public class TurboExampleMultiEBQueues02
+{
+ /**
+ * Creates main() to run this example
+ */
+ public static void main(String[] args)
+ {
+ long startTime = System.currentTimeMillis();
+ if(args.length == 0){
+ System.out.println("Please provide the location of the workload file!");
+ System.exit(1);
+ }
+
+ try {
+
+ //////////////////////////////////////////
+ // Get the workload to be used The format should be:
+ // ASCII text, gzip or zip.
+
+ String fileName = args[0];
+ // /Users/marcosd/Documents/workspace/intergrid/workloads/sdsc_blue_2000_400.swf
+
+ ArrayList<GridResource> resources = new ArrayList<GridResource>();
+
+ //////////////////////////////////////////
+ // Initialize the GridSim package. It should be called
+ // before creating any entities. We can't run this example without
+ // initializing GridSim first. We will get run-time exception
+ // error.
+
+ // number of grid user entities + any Workload entities.
+ int num_user = 1;
+ Calendar calendar = Calendar.getInstance();
+ boolean trace_flag = false; // mean trace GridSim events
+
+ // Initialize the GridSim package without any statistical
+ // functionalities. Hence, no GridSim_stat.txt file is created.
+ System.out.println("Initializing GridSim package");
+ GridSim.init(num_user, calendar, trace_flag);
+
+ //////////////////////////////////////////
+ // Creates one or more GridResource entities
+ int totalResource = 1; // total number of Grid resources
+ int rating = 377; // rating of each PE in MIPS
+ int totalPE = 9; // total number of PEs for each Machine
+ int totalMachine = 128; // total number of Machines
+ int i = 0;
+
+ String[] resArray = new String[totalResource];
+ for (i = 0; i < totalResource; i++) {
+ String resName = "Res_" + i;
+ GridResource resource = createGridResource(resName, rating, totalMachine, totalPE);
+ resources.add(resource);
+
+ // add a resource name into an array
+ resArray[i] = resName;
+ }
+
+ //////////////////////////////////////////
+ // Creates one Workload trace entity.
+
+ int resID = 0;
+ Random r = new Random();
+ resID = r.nextInt(totalResource);
+ Workload workload = new Workload("Load_1", fileName, resArray[resID], rating);
+
+ //////////////////////////////////////////
+ // Starts the simulation in debug mode
+ GridSim.startGridSimulation(true);
+
+ // Start the simulation in normal mode
+// GridSim.startGridSimulation();
+
+ //////////////////////////////////////////
+ // Final step: Prints the Gridlets when simulation is over
+ long finishTime = System.currentTimeMillis();
+ System.out.println("The simulation took " + (finishTime - startTime) + " milliseconds");
+
+ // prints the Gridlets inside a Workload entity
+ // workload.printGridletList(trace_flag);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Creates one Grid resource. A Grid resource contains one or more
+ * Machines. Similarly, a Machine contains one or more PEs (Processing
+ * Elements or CPUs).
+ * @param name a Grid Resource name
+ * @param peRating rating of each PE
+ * @param totalMachine total number of Machines
+ * @param totalPE total number of PEs for each Machine
+ */
+ private static GridResource createGridResource(String name, int peRating,
+ int totalMachine, int totalPE)
+ {
+
+ //////////////////////////////////////////
+ // Here are the steps needed to create a Grid resource:
+ // 1. We need to create an object of MachineList to store one or more
+ // Machines
+ MachineList mList = new MachineList();
+
+ for (int i = 0; i < totalMachine; i++)
+ {
+ //////////////////////////////////////////
+ // 4. Create one Machine with its id and list of PEs or CPUs
+ mList.add( new Machine(i, totalPE, peRating) );
+ }
+
+ //////////////////////////////////////////
+ // 5. Create a ResourceCharacteristics object that stores the
+ // properties of a Grid resource: architecture, OS, list of
+ // Machines, allocation policy: time- or space-shared, time zone
+ // and its price (G$/PE time unit).
+ String arch = "Sun Ultra"; // system architecture
+ String os = "Solaris"; // operating system
+ double time_zone = 0.0; // time zone this resource located
+ double cost = 3.0; // the cost of using this resource
+
+ // this resource will use an aggressive backfilling policy (EASY)
+ TResourceCharacteristics resConfig = new TResourceCharacteristics(
+ arch, os, mList, TResourceCharacteristics.EB_PARALLEL_SPACE_SHARED,
+ time_zone, cost);
+
+ MultipleEasyBackfillingQueues policy = null;
+ try {
+ policy = new MultipleEasyBackfillingQueues(name, "Policy", 2);
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+
+ // creates two partitions, one for small jobs and another for long jobs
+ // assign the same number of PEs to both
+ QueuePredicateExample pred1 = new QueuePredicateExample(0, 10000, peRating);
+ QueuePredicateExample pred2 = new QueuePredicateExample(10000, Integer.MAX_VALUE, peRating);
+
+ policy.createQueue(0, resConfig.getNumPE() / 2, pred1);
+ policy.createQueue(1, resConfig.getNumPE() / 2, pred2);
+
+ //////////////////////////////////////////
+ // 6. Finally, we need to create a GridResource object.
+ double baud_rate = 10000.0; // communication speed
+ long seed = 11L*13*17*19*23+1;
+ double peakLoad = 0.0; // the resource load during peak hour
+ double offPeakLoad = 0.0; // the resource load during off-peak hr
+ double holidayLoad = 0.0; // the resource load during holiday
+
+ // incorporates weekends so the grid resource is on 7 days a week
+ LinkedList weekends = new LinkedList();
+ weekends.add(new Integer(Calendar.SATURDAY));
+ weekends.add(new Integer(Calendar.SUNDAY));
+
+ // incorporates holidays. However, no holidays are set in this example
+ LinkedList holidays = new LinkedList();
+ GridResource gridRes = null;
+
+ ResourceCalendar resCalendar = new ResourceCalendar(time_zone,
+ peakLoad, offPeakLoad, holidayLoad, weekends,
+ holidays, seed);
+
+ try {
+ gridRes = new GridResource(name, baud_rate, resConfig,
+ resCalendar, policy);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ System.out.println("Creates one Grid resource with name = " + name);
+ return gridRes;
+ }
+} // end class
+
+class QueuePredicateExample implements QueuePredicate {
+ int minRuntime_;
+ int maxRuntime_;
+ int resRating_;
+
+ /*
+ * Default constructor
+ */
+ public QueuePredicateExample(int minRuntime,
+ int maxRuntime, int rating) {
+ this.minRuntime_ = minRuntime;
+ this.maxRuntime_ = maxRuntime;
+ this.resRating_ = rating;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see gridsim.turbo.QueuePredicate#match(gridsim.turbo.SSGridlet)
+ */
+ public boolean match(SSGridlet gridlet) {
+ double runtime = forecastExecutionTime(gridlet);
+ if(runtime < minRuntime_ || runtime >= maxRuntime_)
+ return false;
+
+ return true;
+ }
+
+ /*
+ * Forecast execution time of a Gridlet.
+ * <tt>execution time = length / available rating</tt>
+ * @param gridlet the gridlet to be considered
+ * @return Gridlet's execution time.
+ */
+ private double forecastExecutionTime(SSGridlet gridlet) {
+ double executionTime = (gridlet.getLength() / resRating_);
+
+ // This is as a safeguard since the finish time can be extremely
+ // small close to 0.0, such as 4.5474735088646414E-14. Hence causing
+ // some Gridlets never to be finished and consequently hang the program
+ if (executionTime < 1.0) {
+ executionTime = 1.0;
+ }
+ return executionTime;
+ }
+}
+
+
+
Modified: branches/gridsim4.0-branch3/source/gridsim/GridResource.java
===================================================================
--- branches/gridsim4.0-branch3/source/gridsim/GridResource.java 2008-02-12 05:46:26 UTC (rev 101)
+++ branches/gridsim4.0-branch3/source/gridsim/GridResource.java 2008-02-14 12:00:22 UTC (rev 102)
@@ -14,7 +14,6 @@
import gridsim.turbo.EBParallelSpaceShared;
import gridsim.turbo.CBParallelSpaceShared;
import gridsim.turbo.MultipleEasyBackfillingQueues;
-import gridsim.turbo.TAllocPolicy;
import gridsim.turbo.TResourceCharacteristics;
import gridsim.index.*;
@@ -646,10 +645,11 @@
case TResourceCharacteristics.AR_PARALLEL_SPACE_SHARED:
policy_ = new ARParallelSpaceShared(super.get_name(), "ARParallelSpaceShared");
break;
-
+
+ // creates the scheduler with only one queue
case TResourceCharacteristics.MULTIPLE_EASY_BACKFILLING_QUEUES:
policy_ = new MultipleEasyBackfillingQueues(super.get_name(),
- "MultipleEasyBackfillingQueues");
+ "MultipleEasyBackfillingQueues", 1);
break;
default:
Modified: branches/gridsim4.0-branch3/source/gridsim/gui/ResourceWindow.java
===================================================================
--- branches/gridsim4.0-branch3/source/gridsim/gui/ResourceWindow.java 2008-02-12 05:46:26 UTC (rev 101)
+++ branches/gridsim4.0-branch3/source/gridsim/gui/ResourceWindow.java 2008-02-14 12:00:22 UTC (rev 102)
@@ -694,7 +694,7 @@
for(int i=0; i<size; i++) {
ScheduleItem item = (ScheduleItem)scheduledItems_.get(i);
- if(item == null)
+ if(item == null || item.getStartTime() < 0)
continue;
int itemId = item.getID();
Modified: branches/gridsim4.0-branch3/source/gridsim/turbo/AvailabilityProfile.java
===================================================================
--- branches/gridsim4.0-branch3/source/gridsim/turbo/AvailabilityProfile.java 2008-02-12 05:46:26 UTC (rev 101)
+++ branches/gridsim4.0-branch3/source/gridsim/turbo/AvailabilityProfile.java 2008-02-14 12:00:22 UTC (rev 102)
@@ -70,19 +70,25 @@
* entries whose date is smaller or equals to refTime will
* be removed.
* @param refTime the reference time to be used for entry removal.
+ * @return the last entry removed or <tt>null</tt> if no entry
+ * has been removed.
*/
- public void removePastEntries(double refTime) {
+ public AvailabilityProfileEntry removePastEntries(double refTime) {
+ AvailabilityProfileEntry lastRemoved = null;
// Update the availability profile
Iterator<AvailabilityProfileEntry> iterProfile = super.iterator();
while(iterProfile.hasNext()) {
AvailabilityProfileEntry entry = iterProfile.next();
if(entry.getTime() <= refTime){
+ lastRemoved = entry;
iterProfile.remove();
}
else{
break;
}
}
+
+ return lastRemoved;
}
/**
Modified: branches/gridsim4.0-branch3/source/gridsim/turbo/CBParallelSpaceShared.java
===================================================================
--- branches/gridsim4.0-branch3/source/gridsim/turbo/CBParallelSpaceShared.java 2008-02-12 05:46:26 UTC (rev 101)
+++ branches/gridsim4.0-branch3/source/gridsim/turbo/CBParallelSpaceShared.java 2008-02-14 12:00:22 UTC (rev 102)
@@ -239,7 +239,7 @@
// If there are no jobs in the queue list, then check if
// there are enough PEs to process the job immediately
boolean success = false;
- int freePE = super.resource_.getNumFreePE();
+ int freePE = resource_.getNumFreePE();
if( reqPE <= freePE ){
success = startGridlet(sgl);
@@ -908,7 +908,6 @@
break;
}
else {
- // Sep. 29, 2007 - Changed by Marcos
// if the finish time is equals to the entry time, so there
// is no need to check the intersection
if(entryTime < finishTime) {
@@ -1116,7 +1115,7 @@
* start time or the place where the new anchor (if needed) will be placed
* @param tailIndex the index of the entry closest to the finish time but
* whose time is smaller or equals to the finish time
- * @param selected the lsit of PE ranges selected
+ * @param selected the list of PE ranges selected
* @param startTime the start time of the Gridlet
* @param finishTime the finish time of the Gridlet
*/
Modified: branches/gridsim4.0-branch3/source/gridsim/turbo/EBParallelSpaceShared.java
===================================================================
--- branches/gridsim4.0-branch3/source/gridsim/turbo/EBParallelSpaceShared.java 2008-02-12 05:46:26 UTC (rev 101)
+++ branches/gridsim4.0-branch3/source/gridsim/turbo/EBParallelSpaceShared.java 2008-02-14 12:00:22 UTC (rev 102)
@@ -37,8 +37,7 @@
* with Backfilling. IEEE Transactions on Parallel and Distributed
* Systems, 12:(6), pp. 529-543, 2001.
* </ul>
- *
- * This policy maintains an availability profile. The availability
+ * <br> This policy maintains an availability profile. The availability
* profile contains information about the ranges of processing elements
* (PEs) that will be released when the running jobs complete.
* In addition, the policy maintains the list of extra nodes, that is, the nodes
@@ -54,9 +53,7 @@
* simulate this, you have to model the local load as gridlets.
* It is more precise and faster. To do so, please check
* {@link Lublin99Workload}.
- * <li> Gridlets cannot be paused nor migrated. This could be
- * easily done, but due to time constraints, I could not
- * implement these features.
+ * <li> Gridlets cannot be paused nor migrated.
* </ul>
*
* @author Marcos Dias de Assuncao
@@ -71,10 +68,12 @@
*/
public class EBParallelSpaceShared extends TAllocPolicy {
-
// Queue of waiting Gridlets
protected LinkedList<SSGridlet> queuedGridlets_;
+ // Pivot job (i.e. the first job in the queue)
+ private SSGridlet pivot_;
+
// Queue of running Gridlets
protected LinkedList<SSGridlet> runningGridlets_;
@@ -97,9 +96,6 @@
// queue is scheduled
private PERangeList extraPEs_;
- // used only to set the extraPEs_ back to the default value
- private PERangeList allPEs_;
-
// a tag to indicate that a gridlet has finished
private static final int UPDATE_SCHEDULE_TAG = 10;
@@ -133,7 +129,9 @@
availProfile_ = new AvailabilityProfile();
lastScheduleUpdate_ = 0.0D;
shadowTime_ = Double.MAX_VALUE;
+ extraPEs_ = null;
ratingPE_ = 0;
+ pivot_ = null;
}
/**
@@ -148,10 +146,6 @@
// of one PE assuming that the machines are homogeneous
ratingPE_ = resource_.getMIPSRatingOfOnePE();
- // the extra PEs to start are the same that are free
- extraPEs_ = resource_.getFreePERanges().clone();
- allPEs_ = extraPEs_.clone();
-
// a loop that is looking for internal events only
Sim_event ev = new Sim_event();
while ( Sim_system.running() ) {
@@ -180,10 +174,8 @@
availProfile_.clear();
lastScheduleUpdate_ = 0.0D;
shadowTime_ = Double.MAX_VALUE;
- ratingPE_ = 0;
+ extraPEs_ = null;
resource_.resetFreePERanges();
- extraPEs_ = resource_.getFreePERanges().clone();
- allPEs_ = extraPEs_.clone();
}
/**
@@ -233,21 +225,13 @@
if( reqPE <= freePE ) {
success = startGridlet(sgl);
-
- //------------------ FOR DEBUGGING PURPOSES ONLY ----------------
-
- // Notifies the listeners that a Gridlet has been either scheduled
- // to run immediately or put in the waiting queue
- GridSim.notifyListeners(this.get_id(),
- AllocationAction.ITEM_SCHEDULED, true, sgl);
-
- //---------------------------------------------------------------
}
// if the job could not be scheduled immediately, then
// it has to be put in the waiting queue
if(!success) {
- enqueueGridlet(sgl);
+ scheduleGridlet(sgl);
+ queuedGridlets_.add(sgl);
}
// sends back an ack if required
@@ -396,8 +380,7 @@
private boolean startGridlet(SSGridlet sgl) {
int reqPE = sgl.getNumPE();
- if(resource_.getFreePERanges() == null ||
- resource_.getFreePERanges().getNumPE() < reqPE) {
+ if(resource_.getNumFreePE() < reqPE) {
return false;
}
@@ -419,72 +402,23 @@
// time is equals to the gridlet's or advance reservation's finish time
int tailIndex = -1;
- // if there are no jobs in the queue or in execution
- if(availProfile_.size() == 0 && shadowTime_ == Double.MAX_VALUE) {
- selected = super.selectPERangeList(reqPE, resource_.getFreePERanges());
- }
- else {
- // a pointer to the last entry analysed
- AvailabilityProfileEntry tailEntry = null;
-
- // the list of selected ranges
- PERangeList intersectList = null;
-
- // For immediate gridlets the start point
- // is the current list of PEs available
- intersectList = resource_.getFreePERanges().clone();
-
- // scan the availability profile until the expected termination
- // of the Gridlet to check whether enough PEs will be available
- // for the Gridlet. Stop the search if not enough PEs are available
- for(AvailabilityProfileEntry entry : availProfile_) {
- double entryTime = entry.getTime();
- if(entryTime < currentTime) {
- continue;
- }
- else if(entryTime > finishTime) {
- break;
- }
- else {
- tailEntry = entry;
- // if the finish time is equals to the entry time, so there
- // is no need to check the intersection
- if(entryTime < finishTime) {
- PERangeList listEntry = entry.getPERanges();
- intersectList = PERangeList.intersection(listEntry, intersectList);
- if(intersectList == null || intersectList.getNumPE() < reqPE)
- break;
- }
- }
- tailIndex = availProfile_.indexOf(tailEntry);
- }
+ PERangeList intersect = resource_.getFreePERanges();
+
+ if(finishTime > shadowTime_)
+ intersect = PERangeList.intersection(intersect, extraPEs_);
+
+ selected = super.selectPERangeList(reqPE, intersect);
+ if(selected == null || selected.getNumPE() < reqPE)
+ return false;
- // return false if the number of PEs available over the required
- // time interval is smaller than what the Gridlet requires
- if(intersectList == null || intersectList.getNumPE() < reqPE) {
- return false;
- }
- else {
- // the job has to finish before the shadow time or has
- // to use less PEs than the extra nodes
- if(finishTime < shadowTime_) {
- selected = super.selectPERangeList(reqPE, intersectList);
- }
- else {
- intersectList = PERangeList.intersection(intersectList, extraPEs_);
- if(intersectList == null || intersectList.getNumPE() < reqPE) {
- return false;
- }
- else {
- selected = super.selectPERangeList(reqPE, intersectList);
- extraPEs_ = PERangeList.difference(extraPEs_, selected);
- }
- }
- }
- }
+ // a pointer to the last entry analysed
+ AvailabilityProfileEntry tailEntry =
+ availProfile_.getPrecedingEntry(finishTime);
+
+ tailIndex = tailEntry == null ? -1 : availProfile_.indexOf(tailEntry);
// allocate the ranges of PEs to the gridlet
- allocatePERanges(tailIndex, selected, currentTime, finishTime);
+ allocatePERanges(tailIndex, selected, finishTime);
// add this Gridlet into execution list
runningGridlets_.add(sgl);
@@ -500,29 +434,36 @@
// then send this event to itself to update the queues after
// this gridlet's completion time
super.sendInternalEvent(executionTime, UPDATE_SCHEDULE_TAG);
+
+ //------------------ FOR DEBUGGING PURPOSES ONLY ----------------
+
+ // Notifies the listeners that a Gridlet has been either scheduled
+ // to run immediately or put in the waiting queue
+ GridSim.notifyListeners(this.get_id(),
+ AllocationAction.ITEM_SCHEDULED, true, sgl);
+
+ //---------------------------------------------------------------
+
return true;
}
/**
- * Enqueues a gridlet. That is, put the gridlet into the
- * queue of waiting gridlets. If the gridlet is the first into the queue,
- * then updates the extra nodes and the shadow time. The shadow time will
+ * Tries to schedule a gridlet. That is, make the gridlet the pivot,
+ * or the first gridlet in the queue. If that is not possible, then return
+ * false. If the gridlet is the first into the queue, then updates the
+ * pivot, extra nodes and the shadow time. The shadow time will
* be the start time of the gridlet whereas the extra PEs will be the
* PEs left unused when the gridlet starts execution.
* @param sgl the resource gridlet
+ * @return <tt>true</tt> if scheduled; <tt>false</tt> otherwise.
*/
- private void enqueueGridlet(SSGridlet sgl) {
+ private boolean scheduleGridlet(SSGridlet sgl) {
int reqPE = sgl.getNumPE();
// if there are gridlets waiting execution already, then simply
// insert this gridlet into the queue and return
- if(queuedGridlets_.size() > 0) {
- queuedGridlets_.add(sgl);
- return;
- }
-
- // otherwise, just add the gridlet in the queue and continue
- queuedGridlets_.add(sgl);
+ if(pivot_ != null)
+ return false;
// calculate the execution time of the Gridlet
double executionTime =
@@ -553,6 +494,7 @@
sgl.setStatus(Gridlet.QUEUED);
sgl.setStartTime(startTime);
sgl.setFinishTime(finishTime);
+ pivot_ = sgl;
//------------------ FOR DEBUGGING PURPOSES ONLY ----------------
@@ -561,6 +503,8 @@
GridSim.notifyListeners(this.get_id(), AllocationAction.ITEM_SCHEDULED, true, sgl);
//---------------------------------------------------------------
+
+ return true;
}
/**
@@ -568,13 +512,13 @@
* availability profile accordingly
* @param tailIndex the index of the entry closest to the finish time but
* whose time is smaller or equals to the finish time
- * @param selected the list of PE ranges selected
- * @param startTime the start time of the Gridlet
+ * @param selected the list of PE ranges selected
* @param finishTime the finish time of the Gridlet
*/
private void allocatePERanges(int tailIndex,
- PERangeList selected, double startTime, double finishTime) {
+ PERangeList selected, double finishTime) {
+ double startTime = GridSim.clock();
AvailabilityProfileEntry newEntryAfterTail = null;
// if the time of the entry at (tailIndex) is equals to
@@ -616,7 +560,7 @@
// Update entries of the profile
for(int index=0; index<=updTo; index++) {
AvailabilityProfileEntry entry = availProfile_.get(index);
- if(entry.getTime() < startTime){
+ if(entry.getTime() < startTime) {
continue;
}
PERangeList uptList =
@@ -630,6 +574,10 @@
// subtract the selected ranges from the currently free ranges
resource_.setPEsBusy(selected);
+
+ if(finishTime > shadowTime_)
+ extraPEs_ = PERangeList.difference(extraPEs_, selected);
+
}
/**
@@ -642,102 +590,41 @@
* array[1] the list of PE ranges available at that time<br>
*/
private Object[] findStartTime(int reqPE, double duration) {
-
- // the anchor index, the entry in the profile where
- // the gridlet will be placed OR the closest entry to the
- // point where the anchor of the advance reservation will be placed
- int anchorIndex = -1;
-
- // a pointer to the anchor entry (described above)
- AvailabilityProfileEntry anchorEntry = null;
-
- // the list of selected ranges
- PERangeList intersectList = null;
-
- double potStartTime = -1; // keep the potential start time of the gridlet
- double potFinishTime = -1; // store the gridlet's expected finish time
-
- intersectList = null;
- int length = availProfile_.size();
+ PERangeList availRanges = null; // list of ranges available for the job
+ double startTime = -1; // the job's potential start time
Iterator<AvailabilityProfileEntry> iterProfile = availProfile_.iterator();
while(iterProfile.hasNext()) {
-
- AvailabilityProfileEntry entry = iterProfile.next();
+ AvailabilityProfileEntry entry = iterProfile.next();
// scan the profile until an entry with enough PEs is found
if(entry.getNumPE() < reqPE) {
continue;
}
else {
-
- anchorEntry = entry;
- anchorIndex = availProfile_.indexOf(anchorEntry);
-
- // sets the start time as the time of the entry
- potStartTime = entry.getTime();
- // calculates when the finish time will be if
- // the gridlet is put at this position
- potFinishTime = potStartTime + duration;
-
- // if an entry with enough PEs is found, then scan the profile
- // from that point onwards analysing the intersection of
- // the ranges available in the entries until the
- // gridlet expected completion time
- intersectList = entry.getPERanges().clone();
-
- // Look for the intersection of available ranges from
- // the anchor until the end of the profile or until
- // the entries are further than the expected completion time
- for(int i=anchorIndex+1; i<length; i++){
- AvailabilityProfileEntry nextEntry = availProfile_.get(i);
- if(nextEntry.getTime() > potFinishTime){
- break;
- }
- else {
- // if the finish time is equals to the entry time, so there
- // is no need to check the intersection
- if(nextEntry.getTime() < potFinishTime) {
- intersectList = PERangeList.intersection(intersectList,
- nextEntry.getPERanges());
- if(intersectList == null || intersectList.getNumPE() < reqPE) {
- break;
- }
- }
- }
- }
- // If a time slot with enough PEs has been found, then stop the search
- if(intersectList != null && intersectList.getNumPE() >= reqPE) {
- break;
- }
+ // sets the start time as the time of the entry
+ startTime = entry.getTime();
+ availRanges = entry.getPERanges().clone();
+ break;
}
}
// creates the array with the result
Object[] result = new Object[3];
- result[0] = new Double(anchorEntry.getTime());
- result[1] = intersectList;
+ result[0] = new Double(startTime);
+ result[1] = availRanges;
return result;
}
- /**
- * This method is called to update the schedule. It removes completed
- * gridlets and return them to the users and verifies whether the first gridlet
- * in the waiting queue can be started. If it cannot be started, them
- * tries to backfill with jobs waiting in the queue. The method also
- * removes old entries from the availability profile.
+ /**
+ * This method finalises the gridlets in execution whose time
+ * is smaller or equals to the current simulation time.
+ * @param currentTime the current simulation time
+ * @return the number of gridlets completed
*/
- private void updateSchedule(){
+ protected int finishRunningGridlets(double currentTime) {
+ int itemsFinished = 0;
- double currentTime = GridSim.clock();
- int gridletFinished = 0;
- int gridletStarted = 0;
-
- // removes all Gridlets that have already completed from
- // the queue of running Gridlets
- PERangeList releasedRanges = new PERangeList();
- LinkedList<SSGridlet> grlsCompleted = new LinkedList<SSGridlet>();
-
// iterates the list to check what has finished
Iterator<SSGridlet> iter = runningGridlets_.iterator();
while (iter.hasNext()) {
@@ -747,92 +634,86 @@
// is enough. There's no need to check status
if(gridlet.getFinishTime() <= currentTime) {
// Update the list of ranges released
- releasedRanges.addAll(gridlet.getPERangeList().clone());
- grlsCompleted.add(gridlet);
gridletFinish(gridlet, Gridlet.SUCCESS);
iter.remove();
- gridletFinished++;
- }
- }
+ itemsFinished++;
+ }
+ }
+ return itemsFinished;
+ }
+
+ /**
+ * This method is called to update the schedule. It removes completed
+ * gridlets and return them to the users and verifies whether the first gridlet
+ * in the waiting queue can be started. If it cannot be started, them
+ * tries to backfill with jobs waiting in the queue. The method also
+ * removes old entries from the availability profile.
+ */
+ private void updateSchedule() {
+ int itemsFinished = 0;
+ double currentTime = GridSim.clock();
+ int itemsStarted = 0;
- // returns ranges of PEs to the list of PEs available
- resource_.setPEsAvailable(releasedRanges);
+ itemsFinished = finishRunningGridlets(currentTime);
- // Updates the availability profile
- Iterator<AvailabilityProfileEntry> iterProfile = availProfile_.iterator();
- while(iterProfile.hasNext()) {
- AvailabilityProfileEntry entry = iterProfile.next();
- if(entry.getTime() <= currentTime){
- iterProfile.remove();
- }
+ // remove past entries from the availability profile
+ AvailabilityProfileEntry currentStatus = availProfile_.removePastEntries(currentTime);
+ if(currentStatus != null) {
+ resource_.resetFreePERanges(currentStatus.getPERanges());
}
+
+ itemsStarted = startQueuedGridlets(currentTime);
- // if at least a gridlet has finished, then we should iterate the
- // waiting queue. We need to try to start the first gridlet in the queue.
- // If it cannot be started, then we should backfill with the remaining
- // gridlets in the queue.
- if(gridletFinished > 0) {
- if(queuedGridlets_.size() > 0) {
-
- // This is a tricky approach. We decided to clone the waiting
- // queue, try to start the first job, and then enqueue all
- // jobs again, including the first job if it cannot be started
- LinkedList<SSGridlet> clonedQueue =
- (LinkedList<SSGridlet>)queuedGridlets_.clone();
- queuedGridlets_.clear();
-
- //TODO: To think a better way to do this. But the idea is to
- // try to start first job, then enqueue all the other jobs again.
- // If the first job cannot be started, then try to start the other
- // jobs (ie. backfill) or enqueue them again
- SSGridlet gridlet = clonedQueue.getFirst();
- clonedQueue.removeFirst();
-
- if(gridlet.getStartTime() <= currentTime) {
- // if the gridlet can be started, then the extra nodes
- // and the shadow time will be set back to the default values
- // and will be changed when the next gridlet in the waiting queue
- // is scheduled.
- extraPEs_ = allPEs_.clone();
- shadowTime_ = Double.MAX_VALUE;
- if (!startGridlet(gridlet)) {
- // NOTE that it should NOT happen,
- // but if it does, enqueue the job
- enqueueGridlet(gridlet);
- }
- }
- else {
- // if the first job cannot be started, then put it back into
- // the queue and backfill with other jobs. That is, try to
- // start the other jobs.
- queuedGridlets_.add(gridlet);
- iter = clonedQueue.iterator();
- while(iter.hasNext()) {
- gridlet = iter.next();
- if(startGridlet(gridlet))
- iter.remove();
- }
- }
-
- // Add the jobs still remaining back into the waiting queue
- iter = clonedQueue.iterator();
- while(iter.hasNext()) {
- gridlet = iter.next();
- enqueueGridlet(gridlet);
- }
- }
-
- //---------------- USED FOR DEBUGGING PURPOSES ONLY --------------------
+ //---------------- USED FOR DEBUGGING PURPOSES ONLY --------------------
- // If a gridlet has started execution or one has finished,
- // then inform the listeners
- if(gridletStarted > 0 || gridletFinished > 0){
- GridSim.notifyListeners(this.get_id(), AllocationAction.ITEM_COMPLETED,
- true, grlsCompleted);
- }
+ // If a gridlet has started execution or one has finished,
+ // then inform the listeners
+ if(itemsStarted > 0 || itemsFinished > 0) {
+ GridSim.notifyListeners(this.get_id(),
+ AllocationAction.SCHEDULE_CHANGED, true);
+ }
- //----------------------------------------------------------------------
+ //----------------------------------------------------------------------
+ }
+
+ /**
+ * This method starts gridlets that are in the queue and
+ * whose start time is smaller than the reference time and updates
+ * the availability accordingly
+ * @param currentTime the current simulation time
+ * @return the number of gridlets started
+ */
+ protected int startQueuedGridlets(double currentTime) {
+ int gridletStarted = 0;
+
+ // first checks the pivot first
+ if(pivot_ != null) {
+ if(pivot_.getStartTime() <= currentTime) {
+ shadowTime_ = Double.MAX_VALUE;
+ startGridlet(pivot_);
+ gridletStarted++;
+ queuedGridlets_.remove(pivot_);
+ pivot_ = null;
+ }
}
+
+ // Start the execution of Gridlets that are queued
+ Iterator<SSGridlet> iter = queuedGridlets_.iterator();
+ while (iter.hasNext()) {
+ SSGridlet gridlet = iter.next();
+ boolean success = startGridlet(gridlet);
+
+ // if the job could not be scheduled immediately, then enqueue it
+ if(success) {
+ iter.remove();
+ gridletStarted++;
+ }
+ else if (pivot_ == null) { // if there is not a pivot already
+ scheduleGridlet(gridlet);
+ }
+ }
+
+ return gridletStarted;
}
/**
Modified: branches/gridsim4.0-branch3/source/gridsim/turbo/MultipleEasyBackfillingQueues.java
===================================================================
--- branches/gridsim4.0-branch3/source/gridsim/turbo/MultipleEasyBackfillingQueues.java 2008-02-12 05:46:26 UTC (rev 101)
+++ branches/gridsim4.0-branch3/source/gridsim/turbo/MultipleEasyBackfillingQueues.java 2008-02-14 12:00:22 UTC (rev 102)
@@ -13,10 +13,12 @@
import gridsim.GridSim;
import gridsim.GridSimTags;
import gridsim.Gridlet;
+import gridsim.ParameterException;
import gridsim.gui.AllocationAction;
import java.util.ArrayList;
import java.util.Calendar;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
@@ -37,17 +39,23 @@
public class MultipleEasyBackfillingQueues extends TAllocPolicy {
// Queue of running Gridlets
- protected LinkedList<SSGridlet> runningGridlets_;
+ protected LinkedList<MQGridlet> runningGridlets_;
+
+ // Queue of Gridlets waiting in this queue
+ protected LinkedList<MQGridlet> queuedGridlets_;
- // The queues used by this scheduler
- protected ArrayList<EasyBackfillingQueue> queues_;
-
// The rating of one PE
protected int ratingPE_;
// the resource characteristics object to be used
- protected TResourceCharacteristics resource_;
+ protected TResourceCharacteristics resource_;
+ // The availability profile
+ protected Profile profile_;
+
+ // the number of queues in this scheduler
+ private int numQueues_;
+
// the last time when the schedule updated was called
private double lastScheduleUpdate_;
@@ -56,13 +64,14 @@
// a constant that denotes an unknown value
private static final int UNKNOWN = -1;
-
+
/**
* Allocates a new <tt>EBParallelSpaceShared</tt> object
*
* @param resourceName the <tt>GridResource</tt> entity name that will
* contain this allocation policy
* @param entityName this object entity name
+ * @param numQueues The number of queues in the scheduler
* @throws Exception This happens when one of the following scenarios occur:
* <ul>
* <li> Creating this entity before initialising GridSim package
@@ -78,14 +87,30 @@
* String[], String[], String)
*/
public MultipleEasyBackfillingQueues(String resourceName,
- String entityName) throws Exception{
+ String entityName, int numQueues) throws Exception {
super(resourceName, entityName);
+ // makes sure that the scheduler has at least one queue
+ if(numQueues <= 0) {
+ throw new ParameterException("Number of queues" +
+ "should be larger than 1");
+ }
+
// initialises local data structure
- runningGridlets_ = new LinkedList<SSGridlet>();
+ runningGridlets_ = new LinkedList<MQGridlet>();
+ queuedGridlets_ = new LinkedList<MQGridlet>();
+ numQueues_ = numQueues;
+ profile_ = new Profile();
lastScheduleUpdate_ = 0.0D;
ratingPE_ = 0;
}
+
+
+ public boolean createQueue(int queueId, int numPE, QueuePredicate predicate) {
+ EasyBackFillingQueue queue = new EasyBackFillingQueue(queueId, numPE, predicate);
+ profile_.addQueue(queue);
+ return true;
+ }
/**
* Handles internal events that come to this entity.
@@ -99,6 +124,51 @@
// of one PE assuming that the machines are homogeneous
ratingPE_ = resource_.getMIPSRatingOfOnePE();
+ if(numQueues_ > 1 && profile_.getNumberOfQueues() != numQueues_) {
+ System.out.println(super.get_name() + ".body(): The scheduler" +
+ " is expected to have " + numQueues_ + " queues. However," +
+ " only " + profile_.getNumberOfQueues() + " have been defined");
+ return;
+ }
+
+ //TODO: To validate the processing elements assigned to the queues
+
+ // if the user has not specified the queues and the scheduler is
+ // expected to have only one queue, then creates the queue and
+ // includes it in the list.
+ if(profile_.getNumberOfQueues() == 0 && numQueues_ == 1) {
+ // creates the accept all predicate
+ QueuePredicate predicate = new QueuePredicate() {
+ public boolean match(SSGridlet gridlet) {
+ return true;
+ }
+ };
+
+ EasyBackFillingQueue queue =
+ new EasyBackFillingQueue(0, resource_.getNumPE(), predicate);
+ queue.idlePERanges_ = resource_.getFreePERanges().clone();
+ profile_.addQueue(queue);
+ }
+ // assigns the PEs to the queues
+ else {
+ int allocPE = 0;
+ PERangeList freeRanges = resource_.getFreePERanges().clone();
+ for(EasyBackFillingQueue queue : profile_.queues_.values()) {
+ allocPE += queue.initialNumPEs_;
+
+ if(allocPE > resource_.getNumPE()) {
+ System.out.println(super.get_name() + ".body(): The scheduler" +
+ " cannot allocate PEs to all queues because there are not" +
+ " anough PEs");
+ return;
+ }
+
+ PERangeList selected = super.selectPERangeList(queue.initialNumPEs_, freeRanges);
+ queue.idlePERanges_ = selected;
+ freeRanges = PERangeList.difference(freeRanges, selected);
+ }
+ }
+
// a loop that is looking for internal events only
Sim_event ev = new Sim_event();
while ( Sim_system.running() ) {
@@ -160,12 +230,63 @@
}
// Create a resource Gridlet
- SSGridlet sgl = new SSGridlet(gridlet);
+ MQGridlet sgl = new MQGridlet(gridlet);
//-------------- FOR DEBUGGING PURPOSES ONLY --------------
- GridSim.notifyListeners(this.get_id(), AllocationAction.ITEM_ARRIVED, true, sgl);
+ GridSim.notifyListeners(this.get_id(),
+ AllocationAction.ITEM_ARRIVED, true, sgl);
+
+ //----------------------------------------------------------
+
+ // the id of the queue where the job can be scheduled
+ int queueId = profile_.getCorrespondingQueue(sgl);
+
+ // if no queue can handle the gridlet, then reject it
+ if(queueId == UNKNOWN) {
+ String userName = GridSim.getEntityName( gridlet.getUserID() );
+ System.out.println(super.get_name() + ".gridletSubmit(): " +
+ " Gridlet #" + gridlet.getGridletID() + " from " +
+ userName + " cannot be handled by any queue in this resource.");
+ try {
+ gridlet.setGridletStatus(Gridlet.FAILED);
+ } catch (Exception ex) {
+ System.out.println(super.get_name() +
+ ": Exception on submission of a Gridlet");
+ }
+ super.sendFinishGridlet(gridlet);
+ return;
+ }
+
+ sgl.setQueueID(queueId);
+
+ // If there are no jobs in the queue list, then check if
+ // there are enough PEs to process the job immediately
+ boolean success = startGridlet(sgl);
+ // if the job could not be scheduled immediately, then enqueue it
+ if(!success) {
+ scheduleGridlet(sgl);
+ queuedGridlets_.add(sgl);
+ }
+
+// System.out.println("\nFree Ranges=" + profile_.getIdlePEsPerQueue());
+// System.out.println(profile_);
+
+ //------------------ FOR DEBUGGING PURPOSES ONLY ----------------
+
+ // Notifies the listeners that a Gridlet has been either scheduled
+ // to run immediately or put in the waiting queue
+ GridSim.notifyListeners(this.get_id(), AllocationAction.ITEM_SCHEDULED, true, sgl);
+
+ //---------------------------------------------------------------
+
+ // sends back an ack if required
+ if (ack == true) {
+ super.sendAck(GridSimTags.GRIDLET_SUBMIT_ACK, true,
+ gridlet.getGridletID(), gridlet.getUserID()
+ );
+ }
}
/**
@@ -239,8 +360,222 @@
}
// -------------------- PRIVATE METHODS ----------------------------
+
+ /**
+ *
+ */
+ private boolean startGridlet(MQGridlet sgl) {
+
+ int reqPE = sgl.getNumPE();
+ if(reqPE > resource_.getNumFreePE())
+ return false;
+
+ boolean success = false; // to test various conditions
+ int queueId = sgl.getQueueID();
+
+ // calculate the execution time of the Gridlet
+ double executionTime =
+ super.forecastExecutionTime(ratingPE_, sgl.getRemainingLength());
+ // calculates how much ahead to look into the availability profile
+ double currentTime = GridSim.clock() ;
+
+ // the Gridlet's expected finish time if it starts now
+ double finishTime = currentTime + executionTime;
+
+ PERangeList ranges =
+ profile_.getImmediateAvailability(queueId, executionTime);
+
+ // if the above method returns null, it means that there are not enough
+ // PEs to serve the reservation or Gridlet
+ if(ranges.getNumPE() >= reqPE) {
+ ranges = super.selectPERangeList(reqPE, ranges);
+ profile_.allocateImmediateRanges(queueId, finishTime, ranges);
+ success = true;
+ }
+
+ // If the queue to which the gridlet is assigned does not have the
+ // required PEs, then try to borrow the additional PEs from other queues.
+ if(!success) {
+ PERangeList overallAvailPEs =
+ profile_.getImmediateAvailability(executionTime);
+
+ // additional PEs required
+ int addRequired = reqPE - ranges.getNumPE();
+
+ PERangeList addRanges =
+ PERangeList.difference(overallAvailPEs, ranges);
+
+ if(addRanges != null && addRanges.getNumPE() >= addRequired) {
+ // subtracts the ranges already obtained from the gridlet's queue
+
+// System.out.println("\nRanges to Add to queue " + queueId +" = " +
+// addRanges + "\noverall = " + overallAvailPEs +
+// "\n overall num available = " + overallAvailPEs.getNumPE() +
+// "\n free PEs = " + resource_.getNumFreePE() +
+// "\n free PEs profile = " + profile_.getNumFreePEs() +
+// "\n PEs from the queue = " + ranges.getNumPE() +
+// "\n req PEs = " + reqPE);
+
+ // borrows the ranges from the queues and adds it into the
+ // specified queue
+ addRanges = super.selectPERangeList(addRequired, addRanges);
+ profile_.transferPEs(queueId, addRanges, currentTime, finishTime);
+
+ // allocate the ranges to the job
+ ranges.addAll(addRanges);
+ profile_.allocateImmediateRanges(queueId, finishTime, ranges);
+ success = true;
+ }
+ }
+
+ if(!success)
+ return false;
+
+ // sets the PEs to busy at resource class. This is just to provide
+ // information to other classes that may query it
+ resource_.setPEsBusy(ranges);
+
+ // add this Gridlet into execution list
+ runningGridlets_.add(sgl);
+ sgl.setStartTime(currentTime);
+ sgl.setFinishTime(finishTime);
+
+ // change Gridlet status
+ sgl.setStatus(Gridlet.INEXEC);
+
+ // Sets the list of ranges used by the gridlet
+ sgl.setPERangeList(ranges);
+
+ // then send this event to itself to update the queues after
+ // this gridlet's completion time
+ super.sendInternalEvent(executionTime, UPDATE_SCHEDULE_TAG);
+
+ //------------------ FOR DEBUGGING PURPOSES ONLY ----------------
+
+ // Notifies the listeners that a Gridlet has been either scheduled
+ // to run immediately or put in the waiting queue
+ GridSim.notifyListeners(this.get_id(), AllocationAction.ITEM_SCHEDULED, true, sgl);
+
+ //---------------------------------------------------------------
+ return true;
+ }
+
/**
+ * @param sgl the resource gridlet
+ */
+ private boolean scheduleGridlet(MQGridlet sgl) {
+ int reqPE = sgl.getNumPE();
+ int queueId = sgl.getQueueID();
+
+ EasyBackFillingQueue queue = profile_.getQueue(queueId);
+
+ // if queue has a pivot already, then just add
+ // the job to the waiting queue
+ if(queue.pivot_ != null) {
+ return false;
+ }
+
+ PERangeList ranges = null;
+
+ // calculate the execution time of the Gridlet
+ double executionTime =
+ super.forecastExecutionTime(ratingPE_, sgl.getRemainingLength());
+
+ double startTime = -1; // keep the potential start time of the gridlet
+ double finishTime = -1; // store the gridlet's expected finish time
+
+ // check whether there are PEs available over the time interval requested
+ Object[] availObjQueue =
+ profile_.checkPERangesAvailability(queueId, reqPE, executionTime);
+
+ Object[] availObj =
+ profile_.checkPERangesAvailability(reqPE, executionTime);
+
+ int anchor;
+ double startTimeQueue;
+ if (availObjQueue == null)
+ startTimeQueue = Double.MAX_VALUE;
+ else {
+ anchor = (Integer)availObjQueue[0];
+ startTimeQueue=profile_.get(anchor).getTime();
+ }
+
+// System.out.println(profile_);
+
+ anchor = (Integer)availObj[0];
+ double startTimeAll = profile_.get(anchor).getTime();
+
+ if(startTimeQueue <= startTimeAll) {
+ ranges = (PERangeList)availObjQueue[2];
+ ranges = super.selectPERangeList(reqPE, ranges);
+
+ int anchorIndex = (Integer)availObjQueue[0];
+ int tailIndex = (Integer)availObjQueue[1];
+
+ startTime = startTimeQueue;
+ finishTime = startTime + executionTime;
+
+ profile_.allocatePERanges(queueId, anchorIndex, tailIndex,
+ ranges, startTime, finishTime);
+ }
+ // If the queue to which the gridlet is assigned does not have the
+ // required PEs, then try to borrow the additional PEs from other queues.
+ else {
+ PERangeList addRanges = (PERangeList)availObj[2];
+
+ // the anchor index, the entry in the profile where the gridlet will be placed
+ int anchorIndex = (Integer)availObj[0];
+ // insert index represents the position after which the entry
+ // corresponding to the gridlet's finish time will be placed
+ int tailIndex = (Integer)availObj[1];
+
+ // a pointer to the anchor entry
+ startTime = startTimeAll;
+ finishTime = startTime + executionTime;
+
+ availObjQueue = profile_.checkPERangesAvailability(queueId,
+ startTime, executionTime);
+
+ ranges = availObjQueue == null ? new PERangeList() : (PERangeList)availObjQueue[2];
+ addRanges = availObjQueue == null ? addRanges : PERangeList.difference(addRanges, ranges);
+ addRanges = super.selectPERangeList(reqPE - ranges.getNumPE(), addRanges);
+
+// System.out.println("\nRanges to transfer to queue " + queueId +" = " +
+// addRanges + " from " + startTime + " to " + finishTime);
+
+ // borrows the ranges from the queues and adds it into the
+ // specified queue
+ profile_.transferPEs(queueId, addRanges, startTime, finishTime);
+
+ // finally allocate the ranges to the gridlet
+ ranges.addAll(addRanges);
+ profile_.allocatePERanges(queueId, anchorIndex, tailIndex,
+ ranges, startTime, finishTime);
+ }
+
+ queue.pivot_ = sgl;
+
+ // Set the list of ranges used by the gridlet
+ sgl.setPERangeList(ranges);
+
+ // change Gridlet status
+ sgl.setStatus(Gridlet.QUEUED);
+ sgl.setStartTime(startTime);
+ sgl.setFinishTime(finishTime);
+
+ //------------------ FOR DEBUGGING PURPOSES ONLY ----------------
+
+ // Notifies the listeners that a Gridlet has been either scheduled
+ // to run immediately or put in the waiting queue
+ GridSim.notifyListeners(this.get_id(), AllocationAction.ITEM_SCHEDULED, true, sgl);
+
+ //---------------------------------------------------------------
+
+ return true;
+ }
+
+ /**
* Process and event sent to this entity
* @param ev the event to be handled
*/
@@ -273,39 +608,109 @@
* tries to backfill with jobs waiting in the queue. The method also
* removes old entries from the availability profile.
*/
- private void updateSchedule(){
-
+ private void updateSchedule() {
- }
+ int itemsFinished = 0;
+ double currentTime = GridSim.clock();
+ int itemsStarted = 0;
- static class EasyBackfillingQueue {
+ itemsFinished = finishRunningGridlets(currentTime);
- int queueId_ = UNKNOWN;
+ // remove past entries from the availability profile
+ ProfileEntry currentStatus = profile_.removePastEntries(currentTime);
+ if(currentStatus != null) {
+ profile_.setCurrentStatus(currentStatus);
+ resource_.resetFreePERanges(currentStatus.getPERanges());
+ }
- // initial number of PEs assigned to this queue
- int initialNumPE_ = 0;
-
- // Queue of Gridlets waiting in this queue
- LinkedList<SSGridlet> queuedGridlets_;
-
- // the time when the first job in the waiting queue can
- // start its execution
- double shadowTime_ = ...
[truncated message content] |