/* * 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-2010, The University of Melbourne, Australia */package org.cloudbus.cloudsim;import java.util.ArrayList;import java.util.List;import org.cloudbus.cloudsim.core.CloudSim;/** * cloudletschedulerspaceshared實現了vm對於cloudlet的一個調度策略 * * CloudletSchedulerSpaceShared implements a policy of * scheduling performed by a virtual machine. It consider * that there will be only one cloudlet per VM. Other cloudlets will be in a * waiting list. We consider that file transfer from cloudlets waiting happens * before cloudlet execution. I.e., even though cloudlets must wait for CPU, * data transfer happens as soon as cloudlets are submitted. * * @authorRodrigo N. Calheiros * @authorAnton Beloglazov * @sinceCloudSim Toolkit 1.0 */public class CloudletSchedulerSpaceShared extends CloudletScheduler {/** The cloudlet waiting list. */private List<? extends ResCloudlet> cloudletWaitingList;/** The cloudlet exec list. */private List<? extends ResCloudlet> cloudletExecList;/** The cloudlet paused list. */private List<? extends ResCloudlet> cloudletPausedList;/** The cloudlet finished list. */private List<? extends ResCloudlet> cloudletFinishedList;/** The current CPUs. */protected int currentCpus;/** The used PEs. */protected int usedPes;/** * Creates a new CloudletSchedulerSpaceShared object. This method must be invoked * before starting the actual simulation. * * @pre $none * @post $none */public CloudletSchedulerSpaceShared() {//父類欄位:previoustime和currentmipsharesuper();this.cloudletWaitingList = new ArrayList<ResCloudlet>();this.cloudletExecList = new ArrayList<ResCloudlet>();this.cloudletPausedList = new ArrayList<ResCloudlet>();this.cloudletFinishedList = new ArrayList<ResCloudlet>();this.usedPes = 0;this.currentCpus = 0;}/** * 目前時間,更新cloudlet狀態,當有任務完成時,加入新的任務,返回下一個任務完成的時刻 * Updates the processing of cloudlets running under management of this scheduler. * * @param currentTime current simulation time * @param mipsShare array with MIPS share of each processor available to the scheduler * 每個cpu提供的計算能力 * @return time predicted completion time of the earliest finishing cloudlet, or 0 * if there is no next events * * @pre currentTime >= 0 * @post $none */@Overridepublic double updateVmProcessing(double currentTime, List<Double> mipsShare) {setCurrentMipsShare(mipsShare);double timeSpam = currentTime - getPreviousTime(); // time since last updatedouble capacity = 0.0;int cpus = 0;for (Double mips : mipsShare) { // count the CPUs available to the VMMcapacity += mips;if (mips > 0) {cpus++;}}currentCpus = cpus;capacity /= cpus; // average capacity of each cpufor (ResCloudlet rcl : getCloudletExecList()) { // cpu個數等於任務在exec隊列中乘以pe個數each machine in the exec list has the same amount of cpurcl.updateCloudletFinishedSoFar((long) (capacity * timeSpam * rcl.getPesNumber()));}if (getCloudletExecList().size() == 0 && getCloudletWaitingList().size() == 0) { // no more cloudlets in this schedulersetPreviousTime(currentTime); //所有任務執行完畢,設定此時刻return 0.0;}//update each cloudletint finished = 0;int cont = 0;List<ResCloudlet> toRemove = new ArrayList<ResCloudlet>();for (ResCloudlet rcl : getCloudletExecList()) {if (rcl.getRemainingCloudletLength() == 0.0) {// finished anyway, rounding issue...toRemove.add(rcl);cloudletFinish(rcl); //設定狀態,釋放pesfinished++;}cont++;}getCloudletExecList().removeAll(toRemove); //for each finished cloudlet, add a new one from the waiting list//從等候隊列中選擇cloudlet加入到執行隊列中,需要檢查currentcpus>usedpes+rcl.pesif (!getCloudletWaitingList().isEmpty()) {//??為什麼要加這個迴圈,資源不是已經釋放完了嗎,??//回答:為了加id號for (int i = 0; i < finished; i++) {toRemove.clear();for (ResCloudlet rcl : getCloudletWaitingList()) {if ((currentCpus - usedPes) >= rcl.getPesNumber()) {rcl.setCloudletStatus(Cloudlet.INEXEC);for (int k = 0; k < rcl.getPesNumber(); k++) {//??加一樣的有什麼意義??,是不是應該是rcl.setMachineAndPeId(i,k);;rcl.setMachineAndPeId(0, i);}getCloudletExecList().add(rcl);usedPes += rcl.getPesNumber();toRemove.add(rcl);break;}}getCloudletWaitingList().removeAll(toRemove);}// for(cont) } //estimate finish time of cloudlets in the execution queuedouble nextEvent = Double.MAX_VALUE;for (ResCloudlet rcl : getCloudletExecList()) {double remainingLength = rcl.getRemainingCloudletLength();double estimatedFinishTime = currentTime + (remainingLength / (capacity * rcl.getPesNumber()));if (estimatedFinishTime - currentTime < 0.1) {estimatedFinishTime = currentTime + 0.1;}if (estimatedFinishTime < nextEvent) {nextEvent = estimatedFinishTime;}}setPreviousTime(currentTime); //每當有任務完成(可能有任務加入),就設定目前時間return nextEvent; //nextevent為下一個任務完成的時刻}/** * 取消一個cloudlet * Cancels execution of a cloudlet. * * @param cloudletId ID of the cloudlet being cancealed * * @return the canceled cloudlet, $null if not found * * @pre $none * @post $none */@Overridepublic Cloudlet cloudletCancel(int cloudletId) {//First, looks in the finished queuefor (ResCloudlet rcl : getCloudletFinishedList()) {if (rcl.getCloudletId() == cloudletId) {getCloudletFinishedList().remove(rcl);return rcl.getCloudlet();}}//Then searches in the exec listfor (ResCloudlet rcl : getCloudletExecList()) {if (rcl.getCloudletId() == cloudletId) {getCloudletExecList().remove(rcl);if (rcl.getRemainingCloudletLength() == 0.0) {cloudletFinish(rcl);} else {rcl.setCloudletStatus(Cloudlet.CANCELED);}return rcl.getCloudlet();}}//Now, looks in the paused queuefor (ResCloudlet rcl : getCloudletPausedList()) {if (rcl.getCloudletId() == cloudletId) {getCloudletPausedList().remove(rcl);return rcl.getCloudlet();}}//Finally, looks in the waiting listfor (ResCloudlet rcl : getCloudletWaitingList()) {if (rcl.getCloudletId() == cloudletId) {rcl.setCloudletStatus(Cloudlet.CANCELED);getCloudletWaitingList().remove(rcl);return rcl.getCloudlet();}}return null;}/** * 暫停一個cloudlet * Pauses execution of a cloudlet. * * @param cloudletId ID of the cloudlet being paused * * @return $true if cloudlet paused, $false otherwise * * @pre $none * @post $none */@Overridepublic boolean cloudletPause(int cloudletId) {boolean found = false;int position = 0;//first, looks for the cloudlet in the exec listfor (ResCloudlet rcl : getCloudletExecList()) {if (rcl.getCloudletId() == cloudletId) {found = true;break;}position++;}if (found){//moves to the paused listResCloudlet rgl = getCloudletExecList().remove(position);if (rgl.getRemainingCloudletLength() == 0.0) {cloudletFinish(rgl);} else {rgl.setCloudletStatus(Cloudlet.PAUSED);getCloudletPausedList().add(rgl);}return true;}//now, look for the cloudlet in the waiting listposition = 0;found = false;for (ResCloudlet rcl : getCloudletWaitingList()) {if (rcl.getCloudletId() == cloudletId) {found = true;break;}position++;}if (found) {// moves to the paused listResCloudlet rgl = getCloudletWaitingList().remove(position);if (rgl.getRemainingCloudletLength() == 0.0) {cloudletFinish(rgl);} else {rgl.setCloudletStatus(Cloudlet.PAUSED);getCloudletPausedList().add(rgl);}return true;}return false;}/** * cloudlet執行完畢,設定狀態,移入完成隊列中,釋放pe單元 * Processes a finished cloudlet. * * @param rcl finished cloudlet * * @pre rgl != $null * @post $none */@Overridepublic void cloudletFinish(ResCloudlet rcl) {rcl.setCloudletStatus(Cloudlet.SUCCESS);//設定執行了多長時間等rcl.finalizeCloudlet();getCloudletFinishedList().add(rcl);usedPes -= rcl.getPesNumber();}/** * 恢複cloudlet,返回估計完成時間或0 * Resumes execution of a paused cloudlet. * * @param cloudletId ID of the cloudlet being resumed * * @return $true if the cloudlet was resumed, $false otherwise * * @pre $none * @post $none */@Overridepublic double cloudletResume(int cloudletId) {boolean found=false;int position=0;//look for the cloudlet in the paused listfor (ResCloudlet rcl : getCloudletPausedList()) {if (rcl.getCloudletId() == cloudletId) {found = true;break;}position++;}if (found){ResCloudlet rcl = getCloudletPausedList().remove(position);if ((currentCpus - usedPes) >= rcl.getPesNumber()) {// it can go to the exec listrcl.setCloudletStatus(Cloudlet.INEXEC);for (int i = 0; i < rcl.getPesNumber(); i++) {rcl.setMachineAndPeId(0, i);}long size = rcl.getRemainingCloudletLength();size *= rcl.getPesNumber();rcl.getCloudlet().setCloudletLength(size);getCloudletExecList().add(rcl);usedPes += rcl.getPesNumber();// calculate the expected time for cloudlet completiondouble capacity = 0.0;int cpus = 0;for (Double mips : getCurrentMipsShare()) {capacity += mips;if (mips > 0) {cpus++;}}currentCpus = cpus;capacity /= cpus;long remainingLength = rcl.getRemainingCloudletLength();double estimatedFinishTime = CloudSim.clock() + (remainingLength / (capacity * rcl.getPesNumber()));return estimatedFinishTime;} else {// no enough free PEs: go to the waiting queuercl.setCloudletStatus(Cloudlet.QUEUED);long size = rcl.getRemainingCloudletLength();size *= rcl.getPesNumber();rcl.getCloudlet().setCloudletLength(size);getCloudletWaitingList().add(rcl);return 0.0;}}//not found in the paused list: either it is in in the queue, executing or not existreturn 0.0;}/** * 任務提交,收到一個cloudlet,加入到執行隊列,或者等待隊列中 * Receives an cloudlet to be executed in the VM managed by this scheduler. * * @param cloudlet the submited cloudlet * @param fileTransferTime time required to move the required files from the SAN to the VM * * @return expected finish time of this cloudlet, or 0 if it is in the waiting queue * * @pre gl != null * @post $none */@Overridepublic double cloudletSubmit(Cloudlet cloudlet, double fileTransferTime) {if ((currentCpus - usedPes) >= cloudlet.getPesNumber()) {// it can go to the exec listResCloudlet rcl = new ResCloudlet(cloudlet);rcl.setCloudletStatus(Cloudlet.INEXEC);for (int i = 0; i < cloudlet.getPesNumber(); i++) {rcl.setMachineAndPeId(0, i);}getCloudletExecList().add(rcl);usedPes += cloudlet.getPesNumber();} else {// no enough free PEs: go to the waiting queueResCloudlet rcl = new ResCloudlet(cloudlet);rcl.setCloudletStatus(Cloudlet.QUEUED);getCloudletWaitingList().add(rcl);return 0.0;}// calculate the expected time for cloudlet completiondouble capacity = 0.0;int cpus = 0;for (Double mips : getCurrentMipsShare()) {capacity += mips;if (mips > 0) {cpus++;}}currentCpus = cpus;capacity /= cpus;// use the current capacity to estimate the extra amount of// time to file transferring. It must be added to the cloudlet lengthdouble extraSize = capacity * fileTransferTime;long length = cloudlet.getCloudletLength();length += extraSize;cloudlet.setCloudletLength(length);return cloudlet.getCloudletLength() / capacity;}/* (non-Javadoc) * 提交任務,沒有檔案 * @see cloudsim.CloudletScheduler#cloudletSubmit(cloudsim.Cloudlet) */@Overridepublic double cloudletSubmit(Cloudlet cloudlet) {cloudletSubmit(cloudlet, 0);return 0;}/** * 獲得一個cloudlet狀態,需要檢查三個列表 * Gets the status of a cloudlet. * * @param cloudletId ID of the cloudlet * * @return status of the cloudlet, -1 if cloudlet not found * * @pre $none * @post $none */@Overridepublic int getCloudletStatus(int cloudletId) {for (ResCloudlet rcl : getCloudletExecList()) {if (rcl.getCloudletId() == cloudletId) {return rcl.getCloudletStatus();}}for (ResCloudlet rcl : getCloudletPausedList()) {if (rcl.getCloudletId() == cloudletId) {return rcl.getCloudletStatus();}}for (ResCloudlet rcl : getCloudletWaitingList()) {if (rcl.getCloudletId() == cloudletId) {return rcl.getCloudletStatus();}}return -1;}/** * 獲得所有cpu的利用率 * Get utilization created by all cloudlets. * * @param time the time * * @return total utilization */@Overridepublic double getTotalUtilizationOfCpu(double time) {double totalUtilization = 0;for (ResCloudlet gl : getCloudletExecList()) {totalUtilization += gl.getCloudlet().getUtilizationOfCpu(time);}return totalUtilization;}/** * 是否存在完成的任務 * Informs about completion of some cloudlet in the VM managed * by this scheduler. * * @return $true if there is at least one finished cloudlet; $false otherwise * * @pre $none * @post $none */@Overridepublic boolean isFinishedCloudlets() {return getCloudletFinishedList().size() > 0;}/** * Returns the next cloudlet in the finished list, $null if this list is empty. * * @return a finished cloudlet * * @pre $none * @post $none */@Overridepublic Cloudlet getNextFinishedCloudlet() {if (getCloudletFinishedList().size() > 0) {return getCloudletFinishedList().remove(0).getCloudlet();}return null;}/** * Returns the number of cloudlets runnning in the virtual machine. * * @return number of cloudlets runnning * * @pre $none * @post $none */@Overridepublic int runningCloudlets() {return getCloudletExecList().size();}/** * 在此vm上結算後返回 * Returns one cloudlet to migrate to another vm. * * @return one running cloudlet * * @pre $none * @post $none */@Overridepublic Cloudlet migrateCloudlet() {ResCloudlet rcl = getCloudletExecList().remove(0);rcl.finalizeCloudlet();Cloudlet cl = rcl.getCloudlet();usedPes -= cl.getPesNumber();return cl;}/** * Gets the cloudlet waiting list. * * @param <T> the generic type * @return the cloudlet waiting list */@SuppressWarnings("unchecked")protected <T extends ResCloudlet> List<T> getCloudletWaitingList() {return (List<T>) cloudletWaitingList;}/** * Cloudlet waiting list. * * @param <T> the generic type * @param cloudletWaitingList the cloudlet waiting list */protected <T extends ResCloudlet> void cloudletWaitingList(List<T> cloudletWaitingList) {this.cloudletWaitingList = cloudletWaitingList;}/** * Gets the cloudlet exec list. * * @param <T> the generic type * @return the cloudlet exec list */@SuppressWarnings("unchecked")protected <T extends ResCloudlet> List<T> getCloudletExecList() {return (List<T>) cloudletExecList;}/** * Sets the cloudlet exec list. * * @param <T> the generic type * @param cloudletExecList the new cloudlet exec list */protected <T extends ResCloudlet> void setCloudletExecList(List<T> cloudletExecList) {this.cloudletExecList = cloudletExecList;}/** * Gets the cloudlet paused list. * * @param <T> the generic type * @return the cloudlet paused list */@SuppressWarnings("unchecked")protected <T extends ResCloudlet> List<T> getCloudletPausedList() {return (List<T>) cloudletPausedList;}/** * Sets the cloudlet paused list. * * @param <T> the generic type * @param cloudletPausedList the new cloudlet paused list */protected <T extends ResCloudlet> void setCloudletPausedList(List<T> cloudletPausedList) {this.cloudletPausedList = cloudletPausedList;}/** * Gets the cloudlet finished list. * * @param <T> the generic type * @return the cloudlet finished list */@SuppressWarnings("unchecked")protected <T extends ResCloudlet> List<T> getCloudletFinishedList() {return (List<T>) cloudletFinishedList;}/** * Sets the cloudlet finished list. * * @param <T> the generic type * @param cloudletFinishedList the new cloudlet finished list */protected <T extends ResCloudlet> void setCloudletFinishedList(List<T> cloudletFinishedList) {this.cloudletFinishedList = cloudletFinishedList;}/* (non-Javadoc) * @see org.cloudbus.cloudsim.CloudletScheduler#getCurrentRequestedMips() */@Overridepublic List<Double> getCurrentRequestedMips() {List<Double> mipsShare = new ArrayList<Double>();if (getCurrentMipsShare() != null) {for (Double mips : getCurrentMipsShare()) {mipsShare.add(mips);}}return mipsShare;}/* (non-Javadoc) * @see org.cloudbus.cloudsim.CloudletScheduler#getTotalCurrentAvailableMipsForCloudlet(org.cloudbus.cloudsim.ResCloudlet, java.util.List) */@Overridepublic double getTotalCurrentAvailableMipsForCloudlet(ResCloudlet rcl, List<Double> mipsShare) {double capacity = 0.0;int cpus = 0;for (Double mips : mipsShare) { // count the cpus available to the vmmcapacity += mips;if (mips > 0) {cpus++;}}currentCpus = cpus;capacity /= cpus; // average capacity of each cpureturn capacity;}/* (non-Javadoc) * @see org.cloudbus.cloudsim.CloudletScheduler#getTotalCurrentAllocatedMipsForCloudlet(org.cloudbus.cloudsim.ResCloudlet, double) */@Overridepublic double getTotalCurrentAllocatedMipsForCloudlet(ResCloudlet rcl, double time) {// TODO Auto-generated method stubreturn 0.0;}/* (non-Javadoc) * @see org.cloudbus.cloudsim.CloudletScheduler#getTotalCurrentRequestedMipsForCloudlet(org.cloudbus.cloudsim.ResCloudlet, double) */@Overridepublic double getTotalCurrentRequestedMipsForCloudlet(ResCloudlet rcl, double time) {// TODO Auto-generated method stubreturn 0.0;}}