From: <mar...@us...> - 2008-02-11 23:42:34
|
Revision: 99 http://gridsim.svn.sourceforge.net/gridsim/?rev=99&view=rev Author: marcos_dias Date: 2008-02-11 15:42:40 -0800 (Mon, 11 Feb 2008) Log Message: ----------- This update contains: + A simpler advance reservation policy. Now the advance reservation policy extends the normal conservative backfilling so the repeating methods were eliminated. The advance reservation policy has become smaller and simpler. + Small corrections in the comments and java documentation. Modified Paths: -------------- branches/gridsim4.0-branch3/examples/examples/workload/ar/TurboARExample01.java branches/gridsim4.0-branch3/source/gridsim/turbo/ARParallelSpaceShared.java branches/gridsim4.0-branch3/source/gridsim/turbo/ARTGridResource.java branches/gridsim4.0-branch3/source/gridsim/turbo/ARTPolicy.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/Lublin99Workload.java branches/gridsim4.0-branch3/source/gridsim/turbo/TResourceCharacteristics.java Modified: branches/gridsim4.0-branch3/examples/examples/workload/ar/TurboARExample01.java =================================================================== --- branches/gridsim4.0-branch3/examples/examples/workload/ar/TurboARExample01.java 2008-02-11 06:09:53 UTC (rev 98) +++ branches/gridsim4.0-branch3/examples/examples/workload/ar/TurboARExample01.java 2008-02-11 23:42:40 UTC (rev 99) @@ -89,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 Modified: branches/gridsim4.0-branch3/source/gridsim/turbo/ARParallelSpaceShared.java =================================================================== --- branches/gridsim4.0-branch3/source/gridsim/turbo/ARParallelSpaceShared.java 2008-02-11 06:09:53 UTC (rev 98) +++ branches/gridsim4.0-branch3/source/gridsim/turbo/ARParallelSpaceShared.java 2008-02-11 23:42:40 UTC (rev 99) @@ -8,14 +8,14 @@ package gridsim.turbo; import eduni.simjava.Sim_event; -import eduni.simjava.Sim_system; import gridsim.GridSim; import gridsim.GridSimTags; import gridsim.Gridlet; +import gridsim.IO_data; import gridsim.gui.AllocationAction; import java.util.Calendar; -import java.util.Collections; +import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; @@ -39,43 +39,15 @@ * Systems, 12:(6), pp. 529-543, 2001. * </ul> * - * This policy maintains an availability profile. The availability - * profile contains information about the ranges of processing elements - * (PEs) available at future times. The size of the availability profile - * is proportional to the number of gridlets in the running and waiting - * queues. To illustrate how the availability profile works, imagine that - * the simulation has just started and the availability profile is empty. - * The grid resource has 500 PEs. Therefore, the range of PEs available - * is [0..499]. At simulation time 100, a gridlet (GA) arrives requiring - * 100 PEs. The Gridlet is expected to execute for 500 seconds. As the - * resource is not executing any gridlets, GA is accepted and given - * the range [0..99]. The ranges of current PEs available is updated - * to [100..499] and one entry is inserted at the profile to indicate - * that the range [0..499] will be available again at simulation time - * 600 seconds. Now suppose that a Gridlet (GB) arrives at simulation - * time 200 requiring 400 PEs and expected to run for 500 seconds. - * The policy checks the ranges currently available and find [100..499]. - * It then scans the availability profile and analyses all the entries whose - * time is smaller than the expected termination time of GB. The policy - * finds the intersections of PEs amongst the entries, process similar - * to finding intersections of sequences. While scanning the profile, - * the policy finds the entry at 600 seconds. The intersection of - * [100..499] and [0..499] is [100..499]. That means that there are - * enough resources to schedule GB and then GB starts the execution. - * The policy then updates the ranges of current PEs to []. - * After that, the policy updates the entry at 600 seconds to [0..99] - * and inserts an entry with time 700 seconds with the range [0..499]. - * Now consider that a third Gridlet (GC) arrives at simulation time 250 - * requiring 500 PEs and expected to run for 100 seconds. As the - * current ranges available is [], the policy scans the profile until - * it finds an entry with enough PEs available. In this case, the entry - * found is at 700 seconds. The policy would continue scanning the profile - * finding the intersection with other ranges if there were more. In this - * case, 700 seconds is the last entry in the profile. The Gridlet is - * then set to start execution at time 700 seconds. The policy then - * updates the entry at time 700 seconds to [] and creates an entry - * at 800 with [0..499]. GC is then put in the waiting queue. - * <p> + * This policy extends <tt>CBParallelSpaceShared</tt> so also maintains + * an availability profile. The main difference is that in many instances + * an advance reservation will require two entries in the availability profile, + * one to mark its start time and another to delimit its finish time. For more + * details on the availability profile see {@link CBParallelSpaceShared}. + * Another important difference is that when a Gridlet is cancelled, the + * advance reservations are not removed from the availability profile and + * therefore are not moved forwards in the queue. + * <br> * This scheduler supports parallel jobs and some AR functionalities, * such as: * <ul> @@ -84,18 +56,20 @@ * <li> commit a reservation * <li> process a reservation status query * <li> list free time over a certain period of time + * <li> provide availability information when an advance + * reservation is cancelled. * </ul> * <p> * <b>LIMITATIONS:</b><br> * <ul> * <li> The list of machines comprising this resource must * be homogeneous. - * <li> Local load is not considered. If you would like to - * simulate this, you have to model the local load as - * gridlets. It is more precise and faster. + * <li> Local load is not considered. If you would like to 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. + * implement these features. * </ul> * * @author Marcos Dias de Assuncao @@ -109,54 +83,22 @@ * @see CBParallelSpaceShared */ -public class ARParallelSpaceShared extends ARTPolicy { +public class ARParallelSpaceShared extends + CBParallelSpaceShared implements ARTPolicy { - // Queue of waiting Gridlets - private LinkedList<SSGridlet> queuedGridlets_; - - // Queue of running Gridlets - private LinkedList<SSGridlet> runningGridlets_; - - // Comparator to order gridlets by start time - private OrderGridletByStartTime orderStartTime_; - // a new reservation table private LinkedHashMap<Integer, SSReservation> reservTable_; // a table that contains expired reservations private LinkedHashMap<Integer, SSReservation> expiryTable_; - // The rating of one PE - private int ratingPE_; - - // a list containing the availability of PEs - private AvailabilityProfile availProfile_; - - // the resource characteristics object to be used - private TResourceCharacteristics resource_; - // default booking/reservation commit period private int commitPeriod_; // internal event tags used by this gridlet // a tag to denote expiry time private final int EXPIRY_TIME = 12; - - // a tag to indicate that a reservation has to start - private final int START_RESERVATION = 13; - - // a tag to indicate that a reservation has to finish - private final int FINISH_RESERVATION = 14; - - // a tag to indicate that a gridlet has finished - private static final int GRIDLET_FINISHED = 10; - - // Some variables to prevent the policy from iterating - // the lists unnecessarily - // the last time when the schedule update was called - private double lastScheduleUpdate_; - // last time the expiration of reservations was checked private double lastCheckExpiryTime_; @@ -243,42 +185,10 @@ * Handles internal events that are received by this entity. */ public void body() { - - // get the resource characteristics object to be used - resource_ = getTResourceCharacteristics(); - - // Gets the information on number of PEs and rating - // of one PE assuming that the machines are homogeneous - ratingPE_ = resource_.getMIPSRatingOfOnePE(); - - // a loop that is looking for internal events only - // This loop does not stop when the policy receives an - // end of simulation event because it needs to handle - // all the internal events before it finishes its - // execution. This is important particularly for the - // graphical user interface to show the completion of - // advance reservations - Sim_event ev = new Sim_event(); - while ( Sim_system.running() ) { - super.sim_get_next(ev); - processEvent(ev); - } - - // CHECK for ANY INTERNAL EVENTS WAITING TO BE PROCESSED - while (super.sim_waiting() > 0) { - // wait for event and ignore since it is likely to be related to - // internal event scheduled to update Gridlets processing - super.sim_get_next(ev); - System.out.println(super.get_name() + - ".body(): ignore internal events"); - } - - queuedGridlets_.clear(); - runningGridlets_.clear(); - orderStartTime_ = null; + super.body(); reservTable_.clear(); - expiryTable_.clear(); - availProfile_.clear(); + expiryTable_.clear(); + lastCheckExpiryTime_ = 0.0D; } //---------------- RESERVATION RELATED PUBLIC METHODS --------------------- @@ -323,7 +233,7 @@ reservation.setStatus(Reservation.STATUS_FAILED); response.setErrorCode(ARMessage.EC_OPERATION_FAILURE); - super.sendARMessage(response); + sendARMessage(response); return; } @@ -436,7 +346,8 @@ // committed and sends an internal event to start the reservation if(currentTime == startTime) { sRes.setStatus(Reservation.STATUS_COMMITTED); - super.sendInternalEvent(GridSimTags.SCHEDULE_NOW, START_RESERVATION); + super.sendInternalEvent(GridSimTags.SCHEDULE_NOW, + CBParallelSpaceShared.UPDATE_SCHEDULE_TAG); } else { sRes.setStatus(Reservation.STATUS_NOT_COMMITTED); @@ -447,7 +358,7 @@ // add the reservation into the reservation table and sends the // response message to the requester reservTable_.put(new Integer(sRes.getID()), sRes); - super.sendARMessage(response); + sendARMessage(response); // then send this into itself to check for expired reservations super.sendInternalEvent(expTime - currentTime, @@ -469,7 +380,7 @@ reservation.setStatus(Reservation.STATUS_FAILED); reservation.setReservationOptions(availability); response.setErrorCode(ARMessage.EC_OPERATION_FAILURE_BUT_OPTIONS); - super.sendARMessage(response); + sendARMessage(response); } } @@ -515,7 +426,7 @@ // an error message back to the requester if(!success) { response.setErrorCode(ARMessage.EC_OPERATION_FAILURE); - super.sendARMessage(response); + sendARMessage(response); return; } @@ -550,7 +461,7 @@ //---------------------------------------------------------------------- // send the response message back to the requester - super.sendARMessage(response); + sendARMessage(response); } /** @@ -606,7 +517,7 @@ // sends the message back to the requester if(!success) { response.setErrorCode(ARMessage.EC_OPERATION_FAILURE); - super.sendARMessage(response); + sendARMessage(response); return; } @@ -616,11 +527,11 @@ // then send this into itself to start the reservation super.sendInternalEvent(sRes.getStartTime() - currentTime, - START_RESERVATION); + CBParallelSpaceShared.UPDATE_SCHEDULE_TAG); } // sends the response message with no error - super.sendARMessage(response); + sendARMessage(response); //-------------- FOR DEBUGGING PURPOSES ONLY -------------- @@ -663,7 +574,7 @@ response.getReservation().setReservationOptions(availability); // Sends the response back to the user - super.sendARMessage(response); + sendARMessage(response); } /** @@ -690,7 +601,7 @@ // Just sends the message because the reply has a reference to // the reservation object, which contains the status of the reservation - super.sendARMessage(response); + sendARMessage(response); } //---------------- GRIDLET RELATED PUBLIC METHODS ------------------------ @@ -704,247 +615,42 @@ */ public void gridletSubmit(Gridlet gridlet, boolean ack) { if(!gridlet.hasReserved()) { - handleNonReservationGridlet(gridlet, ack); + super.gridletSubmit(gridlet, ack); } else { handleReservationGridlet(gridlet, ack); } } - /** - * Finds the status of a specified <tt>Gridlet</tt>. - * @param gridletId a Gridlet ID - * @param userId the user or owner's ID of this Gridlet - * @return the Gridlet status or <tt>-1</tt> if not found - * @see gridsim.Gridlet - * @pre gridletId > 0 - * @pre userId > 0 - * @post $none - */ - public int gridletStatus(int gridletId, int userId) { - SSGridlet sgl = null; - - // Look for the Gridlet in the running queue - sgl = findSSGridlet(runningGridlets_, gridletId, userId); - if (sgl != null) { - // Get the Gridlet from the execution list - return sgl.getStatus(); - } - - // Look for the gridlet in the waiting queue - sgl = findSSGridlet(queuedGridlets_, gridletId, userId); - if (sgl != null) { - // Get the Gridlet from the execution list - return sgl.getStatus(); - } - - // if not found in all lists then report the Gridlet has not found - return -1; - } - - /** - * Cancels a Gridlet running or in the waiting queue. - * This method will search the running and waiting queues. - * The User ID is important as many users might have the same - * Gridlet ID in the lists. If a Gridlet is cancelled, the - * availability profile is shifted forwards. This process ensures - * that the Gridlets will not have an expected completion time - * worse than the one initially stipulated for the Gridlet. - * This process if known as the compression of the schedule. - * For more details please look at the references provided - * at the initial part of this documentation.<br> - * <b>NOTE:</b> - * <ul> - * <li> Before cancelling a Gridlet, this method updates when - * the expected completion time of the Gridlet is. If the - * completion time is smaller than the current time, then - * the Gridlet is considered to be <tt>finished</tt>. - * Therefore the Gridlet cannot be cancelled. - * - * <li> Once a Gridlet has been cancelled, it cannot be resumed - * to execute again since this method will pass the Gridlet - * back to sender, i.e. the <tt>userId</tt>. - * - * <li> If a Gridlet cannot be found in either execution and - * paused list, then a <tt>null</tt> Gridlet will be send back - * to sender, i.e. the <tt>userId</tt>. - * - * <li> Once a Gridlet is cancelled, the availability profile - * is scanned and Gridlets are moved forwards. The entries - * in the profile incurred by each Gridlet are updated and - * the new anchor for the Gridlet is found again. This process - * is repeated for each Gridlet. This guarantees that Gridlets - * will not have a time completion worse than those initially - * provided. - * </ul> - * @param gridletId a Gridlet ID - * @param userId the user or owner's ID of this Gridlet - * @pre gridletId > 0 - * @pre userId > 0 - */ - public void gridletCancel(int gridletId, int userId) { - double currentTime = GridSim.clock(); - - // stores the gridlet if found - SSGridlet sgl = null; - boolean found = false; - - // The gridlets whose execution time is larger than - // this time onwards have to be shifted forwards - double referenceTime = currentTime; - - // Look for the Gridlet in the running queue - sgl = findSSGridlet(runningGridlets_, gridletId, userId); - if (sgl != null) { - found = true; - - // if the Gridlet's finish time is smaller than the current - // time or the status is FINISHED, it means that the Gridlet - // has finished, but has not been removed from the running - // queue yet. It will probably be done shortly, - // so just send a null to the user. - if(sgl.getStatus() == Gridlet.SUCCESS || - sgl.getFinishTime() <= currentTime){ - super.sendCancelGridlet(GridSimTags.GRIDLET_CANCEL, - null, gridletId, userId); - return; // return as it is impossible to cancel the Gridlet - } - else{ - // remove from the queue before compressing the schedule - runningGridlets_.remove(sgl); - } - } - - if(!found) { - // Look for the gridlet in the waiting queue - sgl = findSSGridlet(queuedGridlets_, gridletId, userId); - if (sgl != null) { - found = true; - - // Get the Gridlet from the waiting queue and - // remove from the queue before compressing the schedule - queuedGridlets_.remove(sgl); - referenceTime = sgl.getStartTime(); - } - } - - // If the Gridlet could not be found in neither queue, then send a null - // Gridlet to the user and return because there is no need to - // compress the schedule - if(!found) { - System.out.println(super.get_name() + ".gridletCancel():" + - " Cannot find Gridlet #" + gridletId + " for User #" + userId); - super.sendCancelGridlet(GridSimTags.GRIDLET_CANCEL, - null, gridletId, userId); - return; - } - - //----------------- USED FOR DEBUGGING PURPOSES ONLY ------------------- - - // If a gridlet has been cancelled, then inform the listeners - GridSim.notifyListeners(this.get_id(), AllocationAction.ITEM_CANCELLED, true, sgl); - - //---------------------------------------------------------------------- - - // remove/update entries of the gridlet in the profile - this.removeGridlet(sgl); - - // compress the schedule, that is, moves the gridlets forwards - compressSchedule(referenceTime, sgl.getStatus() == Gridlet.INEXEC); - - //------------------- USED FOR DEBUGGING PURPOSES ONLY ----------------- - - // Inform the listeners about the new schedule - GridSim.notifyListeners(this.get_id(), AllocationAction.SCHEDULE_CHANGED, true); - - //---------------------------------------------------------------------- - - // sends the Gridlet back to user - sgl.setStatus(Gridlet.CANCELED); - sgl.finalizeGridlet(); - super.sendCancelGridlet(GridSimTags.GRIDLET_CANCEL, - sgl.getGridlet(), gridletId, userId); - } - - /** - * Moves a Gridlet from this GridResource entity to a different one. - * <b>NOTE: This operation is not supported. </b> - * @param gridletId a Gridlet ID - * @param userId the user or owner's ID of this Gridlet - * @param destId a new destination GridResource ID for this Gridlet - * @param ack an acknowledgement, i.e. <tt>true</tt> if wanted to know - * whether this operation is success or not, <tt>false</tt> - * otherwise - */ - public void gridletMove(int gridletId, int userId, - int destId, boolean ack) { - System.out.println(super.get_name() + - ".gridletMove(): not supported at the moment."); - } - - /** - * Pauses a Gridlet only if it is currently executing. - * <b>NOTE: This operation is not supported. </b> - * @param gridletId a Gridlet ID - * @param userId the user or owner's ID of this Gridlet - * @param ack an acknowledgement, i.e. <tt>true</tt> if wanted to know - * whether this operation is success or not, <tt>false</tt> - * otherwise. - */ - public void gridletPause(int gridletId, int userId, boolean ack) { - System.out.println(super.get_name() + - ".gridletPause(): not supported at the moment."); - } - - /** - * Resumes a Gridlet only in the paused list. - * <b>NOTE: This operation is not supported. </b> - * @param gridletId a Gridlet ID - * @param userId the user or owner's ID of this Gridlet - * @param ack an acknowledgement, i.e. <tt>true</tt> if wanted to know - * whether this operation is success or not, <tt>false</tt> - * otherwise - */ - public void gridletResume(int gridletId, int userId, boolean ack) { - System.out.println(super.get_name() + - ".gridletResume(): not supported at the moment."); - } - // -------------------- PRIVATE METHODS ---------------------------- /** * Process and event sent to this entity * @param ev the event to be handled */ - private void processEvent(Sim_event ev) { + public void processOtherEvent(Sim_event ev) { // handle an internal event double currentTime = GridSim.clock(); - switch(ev.get_tag()) { - // time to update the schedule, finish gridlets, - // finish reservations, start reservations and start gridlets - case GRIDLET_FINISHED: - case START_RESERVATION: - case FINISH_RESERVATION: - if(currentTime > lastScheduleUpdate_) { - updateSchedule(); - } - lastScheduleUpdate_ = currentTime; - break; + if(ev.get_src() == myId_) { + switch(ev.get_tag()) { - // checks the expiry time for a given gridlet - case EXPIRY_TIME: - if(currentTime > lastCheckExpiryTime_) { - checkExpiryTime(); - } - lastCheckExpiryTime_ = currentTime; - break; - - default: - processOtherEvent(ev); - break; - } + // checks the expiry time for a given gridlet + case EXPIRY_TIME: + if(currentTime > lastCheckExpiryTime_) { + checkExpiryTime(); + } + lastCheckExpiryTime_ = currentTime; + break; + + default: + super.processOtherEvent(ev); + break; + } + } + else + super.processOtherEvent(ev); } /** @@ -954,92 +660,13 @@ */ private void init() { // initialises local data structure - runningGridlets_ = new LinkedList<SSGridlet>(); - queuedGridlets_ = new LinkedList<SSGridlet>(); - availProfile_ = new AvailabilityProfile(); reservTable_ = new LinkedHashMap<Integer, SSReservation>(); expiryTable_ = new LinkedHashMap<Integer, SSReservation>(); - orderStartTime_ = new OrderGridletByStartTime(); - lastScheduleUpdate_ = -1; - lastCheckExpiryTime_ = -1; - ratingPE_ = 0; + lastCheckExpiryTime_ = 0.0D; } /** * Schedules a new Gridlet received by the <tt>ARTGridResource</tt> - * entity and for which no advance reservation has been made. - * @param gridlet a Gridlet object to be executed - * @param ack an acknowledgement, i.e. <tt>true</tt> if the - * user wants to know whether this operation is successful - * or not, <tt>false</tt> otherwise. - */ - private void handleNonReservationGridlet(Gridlet gridlet, boolean ack) { - int reqPE = gridlet.getNumPE(); - - try{ - // reject the Gridlet if it requires more PEs than the resource - // is able to provide - if(reqPE > super.totalPE_){ - String userName = GridSim.getEntityName( gridlet.getUserID() ); - System.out.println(super.get_name() + ".gridletSubmit(): " + - " Gridlet #" + gridlet.getGridletID() + " from " + - userName + " user requires " + gridlet.getNumPE() + " PEs."); - System.out.println("--> The resource has only " + - super.totalPE_ + " PEs."); - gridlet.setGridletStatus(Gridlet.FAILED); - super.sendFinishGridlet(gridlet); - return; - } - } - catch(Exception ex){ - System.out.println(super.get_name() + - ": Exception on submission of a Gridlet"); - } - - // Create a resource Gridlet - SSGridlet sgl = new SSGridlet(gridlet); - - //------------------ FOR DEBUGGING PURPOSES ONLY------------------------ - - GridSim.notifyListeners(this.get_id(), AllocationAction.ITEM_ARRIVED, true, sgl); - - //---------------------------------------------------------------------- - - // If there enough PEs available at the moment, then - // check if it is possible to start the gridlet immediately - boolean success = false; - int freePE = resource_.getNumFreePE(); - - if( reqPE <= freePE ){ - success = scheduleGridletImmediately(sgl); - } - - // if the job could not be scheduled immediately, then - // find the anchor point where the job can be put - if(!success){ - findAnchorPoint(sgl); - // add this Gridlet into waiting list - queuedGridlets_.add(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); - - //--------------------------------------------------------------- - - // sends back an ack if required - if (ack == true) { - super.sendAck(GridSimTags.GRIDLET_SUBMIT_ACK, true, - gridlet.getGridletID(), gridlet.getUserID() - ); - } - } - - /** - * Schedules a new Gridlet received by the <tt>ARTGridResource</tt> * entity and for which an advance reservation has been made. * @param gridlet a Gridlet object to be executed * @param ack an acknowledgement, i.e. <tt>true</tt> if the @@ -1130,13 +757,15 @@ // reservation if (sRes.getStatus() == Reservation.STATUS_NOT_COMMITTED) { sRes.setStatus(Reservation.STATUS_COMMITTED); - super.sendInternalEvent(resStartTime - currentTime, START_RESERVATION); + super.sendInternalEvent(resStartTime - currentTime, + CBParallelSpaceShared.UPDATE_SCHEDULE_TAG); } // if the reservation has already started, then update the // schedule, which will force the gridlets in the queue to // be started else if(sRes.getStatus() == Reservation.STATUS_IN_PROGRESS) { - startQueuedGridlets(); + super.sendInternalEvent(resStartTime - currentTime, + CBParallelSpaceShared.UPDATE_SCHEDULE_TAG); } } @@ -1156,113 +785,7 @@ } } - /** - * Allocates a Gridlet into free PEs, sets the Gridlet status to INEXEC, - * updates the availability profile and the ranges currently available - * @param sgl a SSGridlet object - * @return <tt>true</tt> if there is are free PE to process this Gridlet, - * <tt>false</tt> otherwise - * @pre sgl != null - * @post $none - */ - private boolean scheduleGridletImmediately(SSGridlet sgl) { - int reqPE = sgl.getNumPE(); - - // 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 - double finishTime = currentTime + executionTime; - - // check whether there are PEs available over the time interval requested - Object[] availObj = - checkImmediatePERangesAvailability(reqPE, currentTime, executionTime); - - // if the above method returns null, it means that there are not enough - // PEs to serve the reservation or Gridlet - if(availObj == null || availObj.length < 2){ - return false; - } - - int tailIndex = ((Integer)availObj[0]).intValue(); - PERangeList selected = (PERangeList)availObj[1]; - allocateImmediatePERanges(tailIndex, selected, currentTime, finishTime); - - // 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(selected); - - // then send this event to itself to update the queues after - // this gridlet's completion time - super.sendInternalEvent(executionTime, GRIDLET_FINISHED); - return true; - } - /** - * Update the information about the jobs scheduled - * @param sgl the resource gridlet - */ - private void findAnchorPoint(SSGridlet sgl){ - int reqPE = sgl.getNumPE(); - - // 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[] availObj = checkPERangesAvailability(reqPE, executionTime); - - // 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]; - PERangeList selected = (PERangeList)availObj[2]; - - // a pointer to the anchor entry - AvailabilityProfileEntry anchorEntry = availProfile_.get(anchorIndex); - startTime = anchorEntry.getTime(); - finishTime = startTime + executionTime; - allocatePERanges(anchorIndex, tailIndex, selected, startTime, finishTime); - - // Set the list of ranges used by the gridlet - sgl.setPERangeList(selected); - - // change Gridlet status - sgl.setStatus(Gridlet.QUEUED); - sgl.setStartTime(startTime); - sgl.setFinishTime(finishTime); - } - - /** - * This method removes/updates all the entries of a gridlet from the profile - * and updates the ranges of current free PEs if the gridlet was in execution. - * @param gridlet the Gridlet to be removed - */ - private void removeGridlet(SSGridlet gridlet) { - // check whether the Gridlet is running - boolean isRunning = gridlet.getStatus() == Gridlet.INEXEC; - - // removes the gridlet from the profile - updateEntriesAtProfile(isRunning, gridlet); - } - - /** * This method removes/updates all the entries of a reservation from * the profile and updates the ranges of current free PEs if the * reservation was in execution. @@ -1313,161 +836,6 @@ } /** - * This method performs the compression of the schedule and - * availability profile. The method iterates the queued gridlets list. - * For each gridlet, it removes its entry from the profile and - * then tries to reinsert the gridlet in the profile. In the worst case, - * the Gridlet will be put back in the same place. This process - * compress the schedule by shifting the jobs forwards, guarantees the - * initial order of jobs given by the scheduler and makes sure that - * no job will have a worse estimate than the one initially given.<br> - * <b>NOTE:</b> - * <ul> - * <li> Optimisations can be made so it may not be required to - * scan the whole list of gridlets. However, this will be - * left for future work as this feature is not required - * for my work YET. - * <li> You are more than welcome to improve it if you want. - * However, do please let me know if come up with a better algorithm. - * <li> This algorithm can be used in case you implement - * gridlets that finish before the expected completion time. - * </ul> - * - * @param referenceTime all gridlets whose start time is larger than - * @param runImmediately <tt>true</tt> means that the gridlet cancelled - * was running, so this method will try to run the gridlets immediately. - * If not possible they are reinserted in the queue with the new start time. - * reference time have to be shifted forwards. - * @return <tt>true</tt> if the Gridlet has been removed and - * the profile has successfully been updated or <tt>false</tt> - * otherwise. - */ - private boolean compressSchedule(double referenceTime, - boolean runImmediately) { - - // iterates the waiting queue and for each gridlet, put the ranges - // used back in the profile. That is, updates the entries - Collections.sort(queuedGridlets_, orderStartTime_); - - Iterator<SSGridlet> iterQueue = queuedGridlets_.iterator(); - while(iterQueue.hasNext()) { - SSGridlet queuedSgl = iterQueue.next(); - - // if the start time of the gridlet is already smaller or equals - // to reference time, then continue. It cannot get better than this. - if(queuedSgl.getStartTime() <= referenceTime) { - continue; - } - - // if the gridlet has not reserved resources, then it can be moved - if(!queuedSgl.hasReserved()) { - - updateEntriesAtProfile(false, queuedSgl); - - // Now try to either schedule the gridlet immediately or - // find the new anchor point - boolean success = false; - if(runImmediately) { - success = scheduleGridletImmediately(queuedSgl); - } - - if(success) { - iterQueue.remove(); - } - else { - findAnchorPoint(queuedSgl); - } - } - } - return true; - } - - /** - * This method removes/updates the entries from the profile - * corresponding to a the given Gridlet or advance reservation. - * - * @param wasRunning indicates whether the gridlet or advance - * reservation was in progress. - * <tt>true</tt> indicates that it was in progress and - * <tt>false</tt> otherwise. - * @param removedItem the Gridlet or advance reservation whose entries - * have to be removed or updated - */ - private void updateEntriesAtProfile(boolean wasRunning, - ScheduleItem removedItem) { - // ranges of PEs used by the Gridlet - PERangeList allocatedRanges = removedItem.getPERangeList(); - - // the reference time used to update the entries in the profile - double startTime = removedItem.getStartTime(); - - // the entries between reference time and endTime must be updated - double endTime = removedItem.getFinishTime(); - - // if the Gridlet was running, then update the range of PEs currently - // available and set the reference time as current simulation time - if(wasRunning) { - // returns the ranges to the list of free ranges - resource_.setPEsAvailable(allocatedRanges); - } - - Iterator<AvailabilityProfileEntry> iterProfile = - availProfile_.iterator(); - - while(iterProfile.hasNext()) { - AvailabilityProfileEntry entry = iterProfile.next(); - - double entryTime = entry.getTime(); - if(entryTime < startTime) { - continue; - } - else if(entryTime > endTime) { - break; - } - else{ - if(entryTime == endTime) { - // if the entry is equals to the finish time of the - // gridlet, then it means that the gridlet uses this entry - // to mark its termination. Therefore, it decreases the - // number of gridlets that rely on this entry to mark - // the finish time. If the number of gridlets is 0, it - // means that the entry can be deleted because it is - // not needed anymore - entry.decreaseGridlet(); - if(entry.getNumGridlets() == 0){ - iterProfile.remove(); - } - continue; - } - // if the entry is the gridlet's anchor point, then - // decrease the number of gridlets that rely on this - // entry to either mark their start time or completion - // time. If the number of Gridlets is 0 then, the - // entry is removed from the profile - if(entryTime == startTime) { - entry.decreaseGridlet(); - if(entry.getNumGridlets() == 0){ - iterProfile.remove(); - continue; - } - } - // returns the ranges to the list of free ranges in - // the entry, and consolidates the ranges to avoid fragments - // As the list may be null, make sure that the list will not be - // null so the released ranges can be added back to it - PERangeList listEntry = entry.getPERanges(); - if(listEntry == null){ - listEntry = new PERangeList(); - } - - listEntry.addAll(allocatedRanges.clone()); - listEntry.mergePERanges(); - entry.setPERangeList(listEntry); - } - } - } - - /** * Checks for expiry time of a given reservations in the list. * @param reservation the reservation to be checked */ @@ -1520,11 +888,6 @@ // gridlets in the queue forwards) compressSchedule(referenceTime, false); - // tries to start the Gridlets. - // TODO: I am not sure whether this is in fact needed. - // TODO: To check this later -// startQueuedGridlets(); - //---------------- USED FOR DEBUGGING PURPOSES ONLY ---------------- // If a gridlet has started execution or one has finished, @@ -1534,65 +897,8 @@ //----------------------------------------------------------------- } } - + /** - * This method is called to update the schedule. It removes completed - * gridlets and return them to the users and verifies whether there are - * gridlets in the waiting list that should start execution. It also - * removes old entries from the availability profile. - */ - private void updateSchedule() { - - int itemsFinished = 0; - double currentTime = GridSim.clock(); - int itemsStarted = 0; - - // finishes the advance reservations first - itemsFinished = finishReservation(currentTime); - - boolean reserved; - // remove all Gridlets that have already completed from - // the queue of running Gridlets - PERangeList releasedRanges = new PERangeList(); - - // iterates the list to check what has finished - Iterator<SSGridlet> iter = runningGridlets_.iterator(); - while (iter.hasNext()) { - SSGridlet gridlet = iter.next(); - reserved = gridlet.hasReserved(); - // as gridlets are removed from running queue once they finish - // time is smaller than current time, then testing the time - // is enough. There's no need to check status - if(gridlet.getFinishTime() <= currentTime) { - // Update the list of ranges released - if(!reserved) { - releasedRanges.addAll(gridlet.getPERangeList().clone()); - } - gridletFinish(gridlet, Gridlet.SUCCESS); - iter.remove(); - itemsFinished++; - } - } - resource_.setPEsAvailable(releasedRanges); - itemsStarted = startReservation(currentTime); - - // remove past entries from the availability profile - cleanAvailabilityProfile(currentTime); - - // Start the execution of Gridlets that are queued and whose - // potential start execution time is smaller than current time - itemsStarted += startQueuedGridlets(); - - //---------------- USED FOR DEBUGGING PURPOSES ONLY -------------------- - - // 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 is called to start a reservation and consequently update * the availability profile. * @refTime the reservations whose start time is smaller @@ -1619,7 +925,7 @@ startedReservations.add(sRes); super.sendInternalEvent(sRes.getFinishTime()-refTime, - FINISH_RESERVATION); + CBParallelSpaceShared.UPDATE_SCHEDULE_TAG); numStartedRes++; } @@ -1694,81 +1000,6 @@ return reservationFinished; } - /** - * Removes all the past entries from the availability profile that are - * older than the reference time - * @param referenceTime the time to be used as reference when removing - * past entries. - */ - private void cleanAvailabilityProfile(double referenceTime) { - // Update the availability profile - Iterator<AvailabilityProfileEntry> iterProfile = availProfile_.iterator(); - while(iterProfile.hasNext()) { - AvailabilityProfileEntry entry = iterProfile.next(); - - if(entry.getTime() <= referenceTime){ - iterProfile.remove(); - } - else{ - return; - } - } - } - - /** - * This method starts gridlets that are in the queue and - * whose start time is smaller than the reference time and updates - * the availability profile and ranges of PEs currently available accordingly - * @return the number of gridlets started - */ - private int startQueuedGridlets() { - - int gridletStarted = 0; - boolean reserved; // to indicate whether the gridlet refers to a reserv. - double currentTime = GridSim.clock(); - - // Start the execution of Gridlets that are queued and whose - // potential start execution time is smaller than reference time - PERangeList allocatedRanges = new PERangeList(); - Iterator<SSGridlet> iter = queuedGridlets_.iterator(); - while (iter.hasNext()) { - SSGridlet gridlet = iter.next(); - // check whether there is a reservation for this gridlet - reserved = gridlet.hasReserved(); - if(gridlet.getStartTime() <= currentTime) { - // Update the list of ranges allocated - if(!reserved) - allocatedRanges.addAll(gridlet.getPERangeList()); - - runningGridlets_.add(gridlet); - iter.remove(); - gridletStarted++; - - // change Gridlet status - gridlet.setStatus(Gridlet.INEXEC); - super.sendInternalEvent(gridlet.getFinishTime()-currentTime, - GRIDLET_FINISHED); - } - } - - resource_.setPEsBusy(allocatedRanges); - return gridletStarted++; - } - - /** - * Updates the Gridlet's properties, such as status once a - * Gridlet is considered finished. - * @param sgl a SSGridlet object - * @param status the Gridlet status - */ - private void gridletFinish(SSGridlet sgl, int status) { - // the order is important! Set the status first then finalise - // due to timing issues in SSGridlet class - sgl.setStatus(status); - sgl.finalizeGridlet(); - super.sendFinishGridlet( sgl.getGridlet() ); - } - /** * Selects a list of PE ranges able to provide enough PEs to handle * a reservation or a Gridlet. @@ -1856,114 +1087,6 @@ /** * Selects a list of PE ranges able to provide enough PEs - * to handle a Gridlet. - * - * @param reqPE the number of PEs - * @param duration the duration in seconds to execute the Gridlet - * @return an array[2] of Objects as follows:<br> - * array[0] the index of the anchor point<br> - * array[1] the index of the last entry before or equals to the finish time - * of the Gridlet in the availability profile<br> - * array[2] the list of PE ranges<br> - */ - private Object[] checkPERangesAvailability(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; - - // tail index represents the position which corresponds to the closest - // entry to the gridlet's finish time OR an existing entry whose - // time is equals to the gridlet's or advance reservation's finish time - int tailIndex = -1; - - // a pointer to the last entry analysed (described above) - AvailabilityProfileEntry tailEntry = null; - - // 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(); - - Iterator<AvailabilityProfileEntry> iterProfile = availProfile_.iterator(); - while(iterProfile.hasNext()) { - - 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); - tailEntry = entry; - - // 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; - } - } - tailEntry = nextEntry; - } - } - // If a time slot with enough PEs has been found, then stop the search - if(intersectList != null && intersectList.getNumPE() >= reqPE) { - break; - } - } - } - - if(intersectList == null || intersectList.getNumPE() < reqPE) - return null; - - anchorIndex = availProfile_.indexOf(anchorEntry); - tailIndex = availProfile_.indexOf(tailEntry); - - // creates the array with the result - Object[] result = new Object[3]; - result[0] = new Integer(anchorIndex); - result[1] = new Integer(tailIndex); - result[2] = super.selectPERangeList(reqPE, intersectList); - return result; - } - - /** - * Selects a list of PE ranges able to provide enough PEs * to handle a reservation. * * @param reqPE the number of PEs @@ -2042,7 +1165,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(nextEntry.getTime() < finishTime) { @@ -2247,6 +1369,46 @@ } } + // ---------------------- PROTECTED METHODS ------------------------ + + /** + * This method is called to update the schedule. It removes completed + * gridlets and return them to the users and verifies whether there are + * gridlets in the waiting list that should start execution. It also + * removes old entries from the availability profile. + */ + protected void updateSchedule() { + + double currentTime = GridSim.clock(); + int itemsFinished = 0; + int itemsStarted = 0; + + // finishes the advance reservations first + itemsFinished = finishReservation(currentTime); + + // then finishes the Gridlets whose start time is smaller + // or equals to the current simulation time + itemsFinished += super.finishRunningGridlets(currentTime); + + // remove past entries from the availability profile + availProfile_.removePastEntries(currentTime); + + // starts the advance reservations + itemsStarted = startReservation(currentTime); + + // Start the execution of Gridlets that are queued and whose + // potential start execution time is smaller than current time + itemsStarted += super.startQueuedGridlets(currentTime); + + //---------------- USED FOR DEBUGGING PURPOSES ONLY -------------------- + + // 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 returns a list that corresponds to the free time slots * in the scheduling queue managed by this scheduler or @@ -2329,4 +1491,48 @@ return list; } + + /** + * Search for a particular reservation in a data structure + * @param obj a data structure + * @param reservID a reservation ID + * @return location in the data structure; <tt>-1</tt> if not found + */ + protected int searchReservation(Collection<Reservation> obj, int reservID) { + + Reservation arObj = null; + int found = -1; // means the reservation is not in the list + + try { + // Search through the list to find the given reservation + int i = 0; + Iterator<Reservation> iter = obj.iterator(); + while ( iter.hasNext() ) { + arObj = iter.next(); + + if (arObj.getID() == reservID) { + found = i; + break; + } + i++; + } + } + catch (Exception e) { + System.out.println("ARTPolicy.findReservation(): " + + "The following error occured:" + e.getMessage()); + } + + return found; + } + + /** + * Sends a reservation message. + * @param message the message to be sent + */ + protected void sendARMessage(ARMessage message) { + // send message to the destination + super.sim_schedule(super.outputPort_, GridSimTags.SCHEDULE_NOW, + message.getMessageType(), new IO_data(message, + message.getMessageSize(), message.getDestinationID())); + } } Modified: branches/gridsim4.0-branch3/source/gridsim/turbo/ARTGridResource.java =================================================================== --- branches/gridsim4.0-branch3/source/gridsim/turbo/ARTGridResource.java 2008-02-11 06:09:53 UTC (rev 98) +++ branches/gridsim4.0-branch3/source/gridsim/turbo/ARTGridResource.java 2008-02-11 23:42:40 UTC (rev 99) @@ -68,7 +68,7 @@ */ public ARTGridResource(String name, double baud_rate, TResourceCharacteristics resource, ResourceCalendar calendar, - ARTPolicy policy) throws Exception { + TAllocPolicy policy) throws Exception { super(name, baud_rate, resource, calendar, policy); if(resource.getResourceAllocationPolicy() != TResourceCharacteristics.AR_PARALLEL_SPACE_SHARED) { @@ -110,7 +110,7 @@ */ public ARTGridResource(String name, Link link, TResourceCharacteristics resource, ResourceCalendar calendar, - ARTPolicy policy) throws Exception { + TAllocPolicy policy) throws Exception { super(name, link, resource, calendar, policy); if(resource.getResourceAllocationPolicy() != TResourceCharacteristics.AR_PARALLEL_SPACE_SHARED) { Modified: branches/gridsim4.0-branch3/source/gridsim/turbo/ARTPolicy.java =================================================================== --- branches/gridsim4.0-branch3/source/gridsim/turbo/ARTPolicy.java 2008-02-11 06:09:53 UTC (rev 98) +++ branches/gridsim4.0-branch3/source/gridsim/turbo/ARTPolicy.java 2008-02-11 23:42:40 UTC (rev 99) @@ -8,19 +8,12 @@ package gridsim.turbo; -import gridsim.GridSimTags; -import gridsim.IO_data; - -import java.util.Calendar; -import java.util.Collection; -import java.util.Iterator; - /** - * <tt>ARTPolicy</tt> is an abstract class that handles the internal - * <tt>ARTGridResource</tt> allocation policy related to Advanced - * Reservation functionalities. New scheduling algorithms can be added - * into a <tt>ARTGridResource</tt> entity by extending this class - * and implement the required abstract methods. + * <tt>ARTPolicy</tt> is an interface that defines the methods that an + * <tt>ARTGridResource</tt>'s needs to implement in order to have + * Advanced Reservation functionalities. New scheduling algorithms can be added + * into a <tt>ARTGridResource</tt> entity by implementing this interface + * and extending <tt>TAllocPolicy</tt>. * @author Marcos Dias de Assuncao * @since GridSim Turbo Alpha 0.1 @@ -31,48 +24,15 @@ * @see TAllocPolicy * */ -public abstract class ARTPolicy extends TAllocPolicy { +public interface ARTPolicy { /** - * Allocates a new <tt>ARTPolicy</tt> object. A child class should call this method - * during its constructor. The name of this entity (or the child class that - * inherits this class) will be <tt>"resName_entityName"</tt>. - * - * @param resourceName the GridResource entity name that will contain - * this allocation policy - * @param entityName this object entity name - * @throws Exception This happens when one of the following scenarios occur: - * <ul> - * <li> creating this entity before initialising GridSim package - * <li> this entity name is <tt>null</tt> or empty - * <li> this entity has <tt>zero</tt> number of PEs (Processing - * Elements). <br> - * No PEs mean the Gridlets can't be processed. - * A GridResource must contain one or more Machines. - * A Machine must contain one or more PEs. - * </ul> - * - * @see gridsim.GridSim#init(int, Calendar, boolean) - * @see gridsim.GridSim#init(int, Calendar, boolean, String[], String[], - * String) - * @pre resourceName != null - * @pre entityName != null - * @post $none - */ - public ARTPolicy(String resourceName, String entityName) - throws Exception { - super(resourceName, entityName); - } - - ///////////////////// ABSTRACT METHODS //////////////////////////////// - - /** * An abstract method that handles a new advanced reservation request. * @param message the advance reservation message received requesting * the reservation * @pre message != null */ - public abstract void handleCreateReservation(ARMessage message); + void handleCreateReservation(ARMessage message); /** * An abstract method that handles a modify reservation request. @@ -80,7 +40,7 @@ * the change * @pre message != null */ - public abstract void handleModifyReservation(ARMessage message); + void handleModifyReservation(ARMessage message); /** * An abstract method that handles a cancel reservation request. @@ -88,78 +48,27 @@ * the cancellation * @pre message != null */ - public abstract void handleCancelReservation(ARMessage message); + void handleCancelReservation(ARMessage message); /** * An abstract method that handles a commit reservation request. * @param message the advance reservation message received * @pre message != null */ - public abstract void handleCommitReservation(ARMessage message); + void handleCommitReservation(ARMessage message); /** * An abstract method that handles a query reservation request. * @param message the advance reservation message received * @pre message != null */ - public abstract void handleQueryReservation(ARMessage message); + void handleQueryReservation(ARMessage message); /** * An abstract method that handles a query free time request. * @param message the advance reservation message received ... [truncated message content] |