/* * Title: CloudSim Toolkit * Description: CloudSim (Cloud Simulation) Toolkit for Modeling and Simulation of Clouds * Licence: GPL - http://www.gnu.org/copyleft/gpl.html * * Copyright (c) 2009-2012, The University of Melbourne, Australia */ package org.cloudbus.cloudsim; import org.cloudbus.cloudsim.core.CloudSim; /** * CloudSim ResCloudlet represents a Cloudlet submitted to CloudResource for processing. This class * keeps track the time for all activities in the CloudResource for a specific Cloudlet. Before a * Cloudlet exits the CloudResource, it is RECOMMENDED to call this method * {@link #finalizeCloudlet()}. * <p/> * It contains a Cloudlet object along with its arrival time and the ID of the machine and the Pe * (Processing Element) allocated to it. It acts as a placeholder for maintaining the amount of * resource share allocated at various times for simulating any scheduling using internal events. * * @author Manzur Murshed * @author Rajkumar Buyya * @since CloudSim Toolkit 1.0 */ public class ResCloudlet { /** The Cloudlet object. */ private final Cloudlet cloudlet; /** The Cloudlet arrival time for the first time. */ private double arrivalTime; /** The estimation of Cloudlet finished time. */ private double finishedTime; /** The length of Cloudlet finished so far. */ private long cloudletFinishedSoFar; /** * Cloudlet execution start time. This attribute will only hold the latest time since a Cloudlet * can be canceled, paused or resumed. */ private double startExecTime; /** The total time to complete this Cloudlet. */ private double totalCompletionTime; // The below attributes are only to be used by the SpaceShared policy. /** The machine id this Cloudlet is assigned to. */ private int machineId; /** The Pe id this Cloudlet is assigned to. */ private int peId; /** The an array of machine IDs. */ private int[] machineArrayId = null; /** The an array of Pe IDs. */ private int[] peArrayId = null; /** The index of machine and Pe arrays. */ private int index; // NOTE: Below attributes are related to AR stuff /** The Constant NOT_FOUND. */ private static final int NOT_FOUND = -1; /** The reservation start time. */ private final long startTime; /** The reservation duration time. */ private final int duration; /** The reservation id. */ private final int reservId; /** The num Pe needed to execute this Cloudlet. */ private int pesNumber; /** * Allocates a new ResCloudlet object upon the arrival of a Cloudlet object. The arriving time * is determined by {@link gridsim.CloudSim#clock()}. * * @param cloudlet a cloudlet object * @see gridsim.CloudSim#clock() * @pre cloudlet != null * @post $none */ public ResCloudlet(Cloudlet cloudlet) { // when a new ResCloudlet is created, then it will automatically set // the submission time and other properties, such as remaining length this.cloudlet = cloudlet; startTime = 0; reservId = NOT_FOUND; duration = 0; init(); } /** * Allocates a new ResCloudlet object upon the arrival of a Cloudlet object. Use this * constructor to store reserved Cloudlets, i.e. Cloudlets that done reservation before. The * arriving time is determined by {@link gridsim.CloudSim#clock()}. * * @param cloudlet a cloudlet object * @param startTime a reservation start time. Can also be interpreted as starting time to * execute this Cloudlet. * @param duration a reservation duration time. Can also be interpreted as how long to execute * this Cloudlet. * @param reservID a reservation ID that owns this Cloudlet * @see gridsim.CloudSim#clock() * @pre cloudlet != null * @pre startTime > 0 * @pre duration > 0 * @pre reservID > 0 * @post $none */ public ResCloudlet(Cloudlet cloudlet, long startTime, int duration, int reservID) { this.cloudlet = cloudlet; this.startTime = startTime; reservId = reservID; this.duration = duration; init(); } /** * Gets the Cloudlet or reservation start time. * * @return Cloudlet's starting time * @pre $none * @post $none */ public long getStartTime() { return startTime; } /** * Gets the reservation duration time. * * @return reservation duration time * @pre $none * @post $none */ public int getDurationTime() { return duration; } /** * Gets the number of PEs required to execute this Cloudlet. * * @return number of Pe * @pre $none * @post $none */ public int getNumberOfPes() { return pesNumber; } /** * Gets the reservation ID that owns this Cloudlet. * * @return a reservation ID * @pre $none * @post $none */ public int getReservationID() { return reservId; } /** * Checks whether this Cloudlet is submitted by reserving or not. * * @return <tt>true</tt> if this Cloudlet has reserved before, <tt>false</tt> otherwise * @pre $none * @post $none */ public boolean hasReserved() { if (reservId == NOT_FOUND) { return false; } return true; } /** * Initialises all local attributes. * * @pre $none * @post $none */ private void init() { // get number of PEs required to run this Cloudlet pesNumber = cloudlet.getNumberOfPes(); // if more than 1 Pe, then create an array if (pesNumber > 1) { machineArrayId = new int[pesNumber]; peArrayId = new int[pesNumber]; } arrivalTime = CloudSim.clock(); cloudlet.setSubmissionTime(arrivalTime); // default values finishedTime = NOT_FOUND; // Cannot finish in this hourly slot. machineId = NOT_FOUND; peId = NOT_FOUND; index = 0; totalCompletionTime = 0.0; startExecTime = 0.0; // In case a Cloudlet has been executed partially by some other grid // hostList. cloudletFinishedSoFar = cloudlet.getCloudletFinishedSoFar() * Consts.MILLION; } /** * Gets this Cloudlet entity Id. * * @return the Cloudlet entity Id * @pre $none * @post $none */ public int getCloudletId() { return cloudlet.getCloudletId(); } /** * Gets the user or owner of this Cloudlet. * * @return the Cloudlet's user Id * @pre $none * @post $none */ public int getUserId() { return cloudlet.getUserId(); } /** * Gets the Cloudlet's length. * * @return Cloudlet's length * @pre $none * @post $none */ public long getCloudletLength() { return cloudlet.getCloudletLength(); } /** * Gets the total Cloudlet's length (across all PEs). * * @return total Cloudlet's length * @pre $none * @post $none */ public long getCloudletTotalLength() { return cloudlet.getCloudletTotalLength(); } /** * Gets the Cloudlet's class type. * * @return class type of the Cloudlet * @pre $none * @post $none */ public int getCloudletClassType() { return cloudlet.getClassType(); } /** * Sets the Cloudlet status. * * @param status the Cloudlet status * @return <tt>true</tt> if the new status has been set, <tt>false</tt> otherwise * @pre status >= 0 * @post $none */ public boolean setCloudletStatus(int status) { // gets Cloudlet's previous status int prevStatus = cloudlet.getCloudletStatus(); // if the status of a Cloudlet is the same as last time, then ignore if (prevStatus == status) { return false; } boolean success = true; try { double clock = CloudSim.clock(); // gets the current clock // sets Cloudlet's current status cloudlet.setCloudletStatus(status); // if a previous Cloudlet status is INEXEC if (prevStatus == Cloudlet.INEXEC) { // and current status is either CANCELED, PAUSED or SUCCESS if (status == Cloudlet.CANCELED || status == Cloudlet.PAUSED || status == Cloudlet.SUCCESS) { // then update the Cloudlet completion time totalCompletionTime += (clock - startExecTime); index = 0; return true; } } if (prevStatus == Cloudlet.RESUMED && status == Cloudlet.SUCCESS) { // then update the Cloudlet completion time totalCompletionTime += (clock - startExecTime); return true; } // if a Cloudlet is now in execution if (status == Cloudlet.INEXEC || (prevStatus == Cloudlet.PAUSED && status == Cloudlet.RESUMED)) { startExecTime = clock; cloudlet.setExecStartTime(startExecTime); } } catch (Exception e) { success = false; } return success; } /** * Gets the Cloudlet's execution start time. * * @return Cloudlet's execution start time * @pre $none * @post $none */ public double getExecStartTime() { return cloudlet.getExecStartTime(); } /** * Sets this Cloudlet's execution parameters. These parameters are set by the CloudResource * before departure or sending back to the original Cloudlet's owner. * * @param wallClockTime the time of this Cloudlet resides in a CloudResource (from arrival time * until departure time). * @param actualCPUTime the total execution time of this Cloudlet in a CloudResource. * @pre wallClockTime >= 0.0 * @pre actualCPUTime >= 0.0 * @post $none */ public void setExecParam(double wallClockTime, double actualCPUTime) { cloudlet.setExecParam(wallClockTime, actualCPUTime); } /** * Sets the machine and Pe (Processing Element) ID. * * @param machineId machine ID * @param peId Pe ID * @pre machineID >= 0 * @pre peID >= 0 * @post $none * * @todo the machineId param and attribute mean a VM or a PM id? * Only the term machine is ambiguous. * At {@link CloudletSchedulerTimeShared#cloudletSubmit(org.cloudbus.cloudsim.Cloudlet)} * it is stated it is a VM. */ public void setMachineAndPeId(int machineId, int peId) { // if this job only requires 1 Pe this.machineId = machineId; this.peId = peId; // if this job requires many PEs if (peArrayId != null && pesNumber > 1) { machineArrayId[index] = machineId; peArrayId[index] = peId; index++; } } /** * Gets machine ID. * * @return machine ID or <tt>-1</tt> if it is not specified before * @pre $none * @post $result >= -1 */ public int getMachineId() { return machineId; } /** * Gets Pe ID. * * @return Pe ID or <tt>-1</tt> if it is not specified before * @pre $none * @post $result >= -1 */ public int getPeId() { return peId; } /** * Gets a list of Pe IDs. <br> * NOTE: To get the machine IDs corresponding to these Pe IDs, use {@link #getMachineIdList()}. * * @return an array containing Pe IDs. * @pre $none * @post $none */ public int[] getPeIdList() { return peArrayId; } /** * Gets a list of Machine IDs. <br> * NOTE: To get the Pe IDs corresponding to these machine IDs, use {@link #getPeIdList()}. * * @return an array containing Machine IDs. * @pre $none * @post $none */ public int[] getMachineIdList() { return machineArrayId; } /** * Gets the remaining cloudlet length that has to be execute yet, * considering the {@link #getCloudletTotalLength()}. * * @return cloudlet length * @pre $none * @post $result >= 0 */ public long getRemainingCloudletLength() { long length = cloudlet.getCloudletTotalLength() * Consts.MILLION - cloudletFinishedSoFar; // Remaining Cloudlet length can't be negative number. if (length < 0) { return 0; } return (long) Math.floor(length / Consts.MILLION); } /** * Finalizes all relevant information before <tt>exiting</tt> the CloudResource entity. This * method sets the final data of: * <ul> * <li>wall clock time, i.e. the time of this Cloudlet resides in a CloudResource (from arrival * time until departure time). * <li>actual CPU time, i.e. the total execution time of this Cloudlet in a CloudResource. * <li>Cloudlet's finished time so far * </ul> * * @pre $none * @post $none */ public void finalizeCloudlet() { // Sets the wall clock time and actual CPU time double wallClockTime = CloudSim.clock() - arrivalTime; cloudlet.setExecParam(wallClockTime, totalCompletionTime); long finished = 0; //if (cloudlet.getCloudletTotalLength() * Consts.MILLION < cloudletFinishedSoFar) { if (cloudlet.getCloudletStatus()==Cloudlet.SUCCESS) { finished = cloudlet.getCloudletLength(); } else { finished = cloudletFinishedSoFar / Consts.MILLION; } cloudlet.setCloudletFinishedSoFar(finished); } /** * Updates the length of cloudlet that has already been completed. * * @param miLength cloudlet length in Instructions (I) * @pre miLength >= 0.0 * @post $none */ public void updateCloudletFinishedSoFar(long miLength) { cloudletFinishedSoFar += miLength; } /** * Gets arrival time of a cloudlet. * * @return arrival time * @pre $none * @post $result >= 0.0 * * @todo It is being used different words for the same term. * Here it is used arrival time while at Resource inner classe of the Cloudlet class * it is being used submissionTime. It needs to be checked if they are * the same term or different ones in fact. */ public double getCloudletArrivalTime() { return arrivalTime; } /** * Sets the finish time for this Cloudlet. If time is negative, then it is being ignored. * * @param time finish time * @pre time >= 0.0 * @post $none */ public void setFinishTime(double time) { if (time < 0.0) { return; } finishedTime = time; } /** * Gets the Cloudlet's finish time. * * @return finish time of a cloudlet or <tt>-1.0</tt> if it cannot finish in this hourly slot * @pre $none * @post $result >= -1.0 */ public double getClouddletFinishTime() { return finishedTime; } /** * Gets the related Cloudlet object. * * @return cloudlet object * @pre $none * @post $result != null */ public Cloudlet getCloudlet() { return cloudlet; } /** * Gets the Cloudlet status. * * @return Cloudlet status * @pre $none * @post $none */ public int getCloudletStatus() { return cloudlet.getCloudletStatus(); } /** * Get am Unique Identifier (UID) of the cloudlet. * * @return The UID */ public String getUid() { return getUserId() + "-" + getCloudletId(); } }