/*
* 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();
}
}