All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.cloudbus.cloudsim.schedulers.cloudlet.CloudletSchedulerAbstract Maven / Gradle / Ivy

Go to download

CloudSim Plus: A modern, highly extensible and easier-to-use Java 8 Framework for Modeling and Simulation of Cloud Computing Infrastructures and Services

There is a newer version: 8.0.0
Show newest version
/*
 * 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.schedulers.cloudlet;

import org.cloudbus.cloudsim.cloudlets.Cloudlet;
import org.cloudbus.cloudsim.cloudlets.Cloudlet.Status;
import org.cloudbus.cloudsim.cloudlets.CloudletExecution;
import org.cloudbus.cloudsim.resources.Ram;
import org.cloudbus.cloudsim.resources.ResourceManageable;
import org.cloudbus.cloudsim.schedulers.cloudlet.network.CloudletTaskScheduler;
import org.cloudbus.cloudsim.util.Conversion;
import org.cloudbus.cloudsim.utilizationmodels.UtilizationModel;
import org.cloudbus.cloudsim.vms.Vm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toList;
import static org.cloudbus.cloudsim.utilizationmodels.UtilizationModel.Unit;

/**
 * Implements the basic features of a {@link CloudletScheduler}, representing
 * the policy of scheduling performed by a virtual machine to run its
 * {@link Cloudlet Cloudlets}. So, classes extending this must execute
 * Cloudlets. The interface for cloudlet management is also implemented in this
 * class. Each VM has to have its own instance of a CloudletScheduler.
 *
 * @author Rodrigo N. Calheiros
 * @author Anton Beloglazov
 * @author Manoel Campos da Silva Filho
 * @since CloudSim Toolkit 1.0
 */
public abstract class CloudletSchedulerAbstract implements CloudletScheduler {
    private static final Logger logger = LoggerFactory.getLogger(CloudletSchedulerAbstract.class.getSimpleName());

    /**
     * @see #getCloudletPausedList()
     */
    private final List cloudletPausedList;
    /**
     * @see #getCloudletFinishedList()
     */
    private final List cloudletFinishedList;
    /**
     * @see #getCloudletFailedList()
     */
    private final List cloudletFailedList;
    /**
     * @see #getTaskScheduler()
     */
    private CloudletTaskScheduler taskScheduler;
    /**
     * @see #getPreviousTime()
     */
    private double previousTime;
    /**
     * @see #getCurrentMipsShare()
     */
    private List currentMipsShare;
    /**
     * @see #getCloudletExecList()
     */
    private final List cloudletExecList;
    /**
     * @see #getCloudletWaitingList()
     */
    private final List cloudletWaitingList;

    /**
     * @see #getVm()
     */
    private Vm vm;

    /**
     * @see #getCloudletReturnedList()
     */
    private final Set cloudletReturnedList;

    /**
     * Creates a new CloudletScheduler object.
     */
    protected CloudletSchedulerAbstract() {
        setPreviousTime(0.0);
        vm = Vm.NULL;
        cloudletExecList = new ArrayList<>();
        cloudletPausedList = new ArrayList<>();
        cloudletFinishedList = new ArrayList<>();
        cloudletFailedList = new ArrayList<>();
        cloudletWaitingList = new ArrayList<>();
        cloudletReturnedList = new HashSet<>();
        currentMipsShare = new ArrayList<>();
        taskScheduler = CloudletTaskScheduler.NULL;
    }

    @Override
    public double getPreviousTime() {
        return previousTime;
    }

    /**
     * Sets the previous time when the scheduler updated the processing of
     * cloudlets it is managing.
     *
     * @param previousTime the new previous time
     */
    protected final void setPreviousTime(final double previousTime) {
        this.previousTime = previousTime;
    }

    @Override
    public List getCurrentMipsShare() {
        return Collections.unmodifiableList(currentMipsShare);
    }

    /**
     * Sets the list of current mips share available for the VM using the
     * scheduler.
     *
     * @param currentMipsShare the new current mips share
     * @see #getCurrentMipsShare()
     */
    protected void setCurrentMipsShare(final List currentMipsShare) {
        if(currentMipsShare.size() > vm.getNumberOfPes()){
            logger.warn("Requested {} PEs but {} has just {}", currentMipsShare.size(), vm, vm.getNumberOfPes());
        }
        this.currentMipsShare = currentMipsShare;
    }

    /**
     * Gets the amount of MIPS available (free) for each Processor PE,
     * considering the currently executing cloudlets in this processor
     * and the number of PEs these cloudlets require.
     * This is the amount of MIPS that each Cloudlet is allowed to used,
     * considering that the processor is shared among all executing
     * cloudlets.
     *
     * 

In the case of space shared schedulers, * there is no concurrency for PEs because some cloudlets * may wait in a queue until there is available PEs to be used * exclusively by them.

* * @return the amount of available MIPS for each Processor PE. * * @TODO Splitting the capacity of a CPU core among different applications * is not in fact possible. This was just an oversimplification * performed by the CloudletSchedulerTimeShared that may affect * other schedulers such as the CloudletSchedulerCompletelyFair, * which in fact performs task preemption. */ public double getAvailableMipsByPe(){ final long totalPesOfAllExecCloudlets = totalPesOfAllExecCloudlets(); if(totalPesOfAllExecCloudlets > currentMipsShare.size()) { return getTotalMipsShare() / totalPesOfAllExecCloudlets; } return getPeCapacity(); } private Double getPeCapacity() { return currentMipsShare.stream().findFirst().orElse(0.0); } /** * Gets the total number of PEs of all cloudlets currently executing in this processor. * @return */ private long totalPesOfAllExecCloudlets() { return cloudletExecList.stream() .map(CloudletExecution::getCloudlet) .mapToLong(Cloudlet::getNumberOfPes).sum(); } private double getTotalMipsShare(){ return currentMipsShare.stream().mapToDouble(d -> d).sum(); } @Override public List getCloudletExecList() { return Collections.unmodifiableList(cloudletExecList); } protected void addCloudletToWaitingList(final CloudletExecution cloudlet) { Objects.requireNonNull(cloudlet); if(cloudlet == CloudletExecution.NULL){ return; } cloudlet.setCloudletStatus(Cloudlet.Status.QUEUED); cloudletWaitingList.add(cloudlet); } /** * Gets the list of paused cloudlets. * * @return the cloudlet paused list */ protected List getCloudletPausedList() { return cloudletPausedList; } @Override public List getCloudletFinishedList() { return cloudletFinishedList; } protected void addCloudletToFinishedList(final CloudletExecution cloudlet) { cloudletFinishedList.add(cloudlet); } /** * Gets the list of failed cloudlets. * * @return the cloudlet failed list. */ protected List getCloudletFailedList() { return cloudletFailedList; } @Override public List getCloudletWaitingList() { return Collections.unmodifiableList(cloudletWaitingList); } /** * Sorts the {@link #cloudletWaitingList} using a given {@link Comparator}. * @param comparator the {@link Comparator} to sort the Waiting Cloudlets List */ protected void sortCloudletWaitingList(final Comparator comparator){ cloudletWaitingList.sort(comparator); } @Override public final double cloudletSubmit(final Cloudlet cloudlet) { return cloudletSubmit(cloudlet, 0.0); } @Override public final double cloudletSubmit(final Cloudlet cl, final double fileTransferTime) { return cloudletSubmitInternal(new CloudletExecution(cl), fileTransferTime); } /** * @see #cloudletSubmit(Cloudlet, double) */ protected double cloudletSubmitInternal(final CloudletExecution ce, final double fileTransferTime) { if (canAddCloudletToExecutionList(ce)) { ce.setCloudletStatus(Status.INEXEC); ce.setFileTransferTime(fileTransferTime); addCloudletToExecList(ce); return fileTransferTime + (ce.getCloudletLength() / getPeCapacity()); } // No enough free PEs, then add Cloudlet to the waiting queue addCloudletToWaitingList(ce); return 0.0; } /** * Adds a Cloudlet to the list of cloudlets in execution. * * @param cloudlet the Cloudlet to be added */ protected void addCloudletToExecList(final CloudletExecution cloudlet) { cloudlet.setCloudletStatus(Cloudlet.Status.INEXEC); cloudlet.setLastProcessingTime(getVm().getSimulation().clock()); cloudletExecList.add(cloudlet); addUsedPes(cloudlet.getNumberOfPes()); } @Override public boolean hasFinishedCloudlets() { return !cloudletFinishedList.isEmpty(); } @Override public int runningCloudletsNumber() { return cloudletExecList.size(); } /** * Returns the first cloudlet in the execution list to migrate to another * VM, removing it from the list. * * @return the first executing cloudlet or {@link Cloudlet#NULL} if the * executing list is empty * @pre $none * @post $none */ @Override public Cloudlet getCloudletToMigrate() { return cloudletExecList.stream() .findFirst() .map(this::finishCloudletMigration) .orElse(Cloudlet.NULL); } private Cloudlet finishCloudletMigration(final CloudletExecution ce) { removeCloudletFromExecListAndAddToFinishedList(ce); ce.finalizeCloudlet(); return ce.getCloudlet(); } @Override public int getCloudletStatus(final int cloudletId) { final Optional optional = findCloudletInAllLists(cloudletId); return optional .map(CloudletExecution::getCloudlet) .map(Cloudlet::getStatus) .map(Status::ordinal) .orElse(-1); } /** * Search for a Cloudlet into all Cloudlet lists. * * @param cloudletId the id of the Cloudlet to search for * @return an {@link Optional} value that is able to indicate if the * Cloudlet was found or not */ protected Optional findCloudletInAllLists(final double cloudletId) { //Concatenate all lists into a stream final Stream> streamOfAllLists = Stream.of(cloudletExecList, cloudletPausedList, cloudletWaitingList, cloudletFinishedList, cloudletFailedList); //Gets all elements in each list and makes them a single full list, //returning the first Cloudlet with the given id return streamOfAllLists .flatMap(List::stream) .filter(c -> c.getCloudletId() == cloudletId) .findFirst(); } /** * Search for a Cloudlet into a given list. * * @param cloudletId the id of the Cloudlet to search for * @param list the list to search the Cloudlet into * @return an {@link Optional} value that is able to indicate if the * Cloudlet was found or not */ protected Optional findCloudletInList(final double cloudletId, final List list) { return list.stream() .filter(ce -> ce.getCloudletId() == cloudletId) .findFirst(); } @Override public void cloudletFinish(final CloudletExecution ce) { ce.setCloudletStatus(Cloudlet.Status.SUCCESS); ce.finalizeCloudlet(); addCloudletToFinishedList(ce); } @Override public boolean cloudletPause(final int cloudletId) { if (changeStatusOfCloudletIntoList(cloudletExecList, cloudletId, this::changeInexecToPaused) != Cloudlet.NULL) { return true; } return changeStatusOfCloudletIntoList(cloudletWaitingList, cloudletId, this::changeReadyToPaused) != Cloudlet.NULL; } private void changeInexecToPaused(final CloudletExecution c) { changeStatusOfCloudlet(c, Status.INEXEC, Status.PAUSED); } private void changeReadyToPaused(final CloudletExecution c) { changeStatusOfCloudlet(c, Status.READY, Status.PAUSED); } @Override public Cloudlet cloudletCancel(final int cloudletId) { Cloudlet cloudlet; //Removes finished cloudlets from the list cloudlet = changeStatusOfCloudletIntoList(cloudletFinishedList, cloudletId, c -> {}); if (cloudlet != Cloudlet.NULL) { return cloudlet; } cloudlet = changeStatusOfCloudletIntoList( cloudletExecList, cloudletId, c -> changeStatusOfCloudlet(c, Status.INEXEC, Status.CANCELED)); if (cloudlet != Cloudlet.NULL) { return cloudlet; } cloudlet = changeStatusOfCloudletIntoList( cloudletPausedList, cloudletId, c -> changeStatusOfCloudlet(c, Status.PAUSED, Status.CANCELED)); if (cloudlet != Cloudlet.NULL) { return cloudlet; } cloudlet = changeStatusOfCloudletIntoList( cloudletWaitingList, cloudletId, c -> changeStatusOfCloudlet(c, Status.READY, Status.CANCELED)); if (cloudlet != Cloudlet.NULL) { return cloudlet; } return Cloudlet.NULL; } /** * Changes the status of a given cloudlet. * * @param cloudlet Cloudlet to set its status * @param currentStatus the current cloudlet status * @param newStatus the new status to set * @todo @author manoelcampos The parameter currentStatus only exists * because apparently, the cloudlet status is not being accordingly changed * along the simulation run. */ private void changeStatusOfCloudlet(final CloudletExecution cloudlet, final Status currentStatus, final Status newStatus) { if ((currentStatus == Status.INEXEC || currentStatus == Status.READY) && cloudlet.getCloudlet().isFinished()) { cloudletFinish(cloudlet); } else { cloudlet.setCloudletStatus(newStatus); } switch (newStatus) { case PAUSED: cloudletPausedList.add(cloudlet); break; } } /** * Search for a cloudlet into a given list in order to change its status and * remove it from that list. * * @param cloudletList the list where to search the cloudlet * @param cloudletId the id of the cloudlet to have its status changed * @param cloudletStatusUpdaterConsumer the {@link Consumer} that will apply * the change in the status of the found cloudlet * @return the changed cloudlet or {@link Cloudlet#NULL} if not found in the * given list */ private Cloudlet changeStatusOfCloudletIntoList( final List cloudletList, final int cloudletId, final Consumer cloudletStatusUpdaterConsumer) { final Function removeCloudletFromListAndUpdateItsStatus = c -> { cloudletList.remove(c); cloudletStatusUpdaterConsumer.accept(c); return c.getCloudlet(); }; return cloudletList.stream() .filter(c -> c.getCloudlet().getId() == cloudletId) .findFirst() .map(removeCloudletFromListAndUpdateItsStatus) .orElse(Cloudlet.NULL); } @Override public double updateProcessing(final double currentTime, final List mipsShare) { setCurrentMipsShare(mipsShare); if (isEmpty()) { setPreviousTime(currentTime); return Double.MAX_VALUE; } updateCloudletsProcessing(currentTime); updateVmRamAbsoluteUtilization(); removeFinishedCloudletsFromExecutionListAndAddToFinishedList(); moveNextCloudletsFromWaitingToExecList(); final double nextSimulationTime = getEstimatedFinishTimeOfSoonerFinishingCloudlet(currentTime); setPreviousTime(currentTime); return nextSimulationTime; } /** * Updates the processing of all cloudlets of the Vm using this scheduler * that are in the {@link #getCloudletExecList() cloudlet execution list}. * * @param currentTime current simulation time */ @SuppressWarnings("ForLoopReplaceableByForEach") private void updateCloudletsProcessing(final double currentTime) { /* Uses a traditional for to avoid ConcurrentModificationException, * e.g., in cases when Cloudlet is cancelled during simulation execution. */ for (int i = 0; i < cloudletExecList.size(); i++) { final CloudletExecution ce = cloudletExecList.get(i); updateCloudletProcessingAndPacketsDispatch(ce, currentTime); } } /** * Updates the processing of a specific cloudlet of the Vm using this * scheduler and packets that such a Cloudlet has to send or to receive * (if the CloudletScheduler has a {@link CloudletTaskScheduler} assigned to it). * * @param ce The cloudlet to be its processing updated * @param currentTime current simulation time */ private void updateCloudletProcessingAndPacketsDispatch(final CloudletExecution ce, final double currentTime) { long partialFinishedMI = 0; if (taskScheduler.isTimeToUpdateCloudletProcessing(ce.getCloudlet())) { partialFinishedMI = updateCloudletProcessing(ce, currentTime); } taskScheduler.processCloudletTasks(ce.getCloudlet(), partialFinishedMI); } /** * Updates the processing of a specific cloudlet of the Vm using this * scheduler. * * @param ce The cloudlet to be its processing updated * @param currentTime current simulation time * @return the executed length, in Million Instructions (MI), since the last time cloudlet was processed. */ protected long updateCloudletProcessing(final CloudletExecution ce, final double currentTime) { final long partialFinishedInstructions = cloudletExecutedInstructionsForTimeSpan(ce, currentTime); ce.updateProcessing(partialFinishedInstructions); return partialFinishedInstructions/Conversion.MILLION; } /** * Updates the VM usage of RAM, based on the current utilization of all * its running Cloudlets, that depends on the {@link Cloudlet#getUtilizationModelRam()}. * *

It deallocates all resources so that the VM's amount of allocated resource will be update * for each running Cloudlet. This way, each Cloudlet requests an amount that is allocated. * The request for the next Cloudlet may not be fulfilled due to lack of resources. * If a Cloudlet requests more resources than is available, just the available * amount is allocated to it.

*/ private void updateVmRamAbsoluteUtilization() { final ResourceManageable ram = vm.getResource(Ram.class); ram.deallocateAllResources(); for (final CloudletExecution cloudletExecution : cloudletExecList) { final Cloudlet cloudlet = cloudletExecution.getCloudlet(); final long requested = (long)getCloudletRamAbsoluteUtilization(cloudlet); if(requested > ram.getAvailableResource()){ final String msg = ram.getAvailableResource() > 0 ? String.format("just %d was available and allocated to it.", ram.getAvailableResource()): "no amount is available."; logger.warn( "{}: {}: {} requested {} MB of RAM but {}", vm.getSimulation().clock(), getClass().getSimpleName(), cloudlet, requested, msg); } ram.allocateResource(Math.min(requested, ram.getAvailableResource())); } } /** * Gets the absolute value of RAM utilization for a given Cloudlet * * @param cloudlet the Cloudlet to get the absolute value of RAM utilization * @return the Cloudlet RAM utilization in absolute value */ private double getCloudletRamAbsoluteUtilization(final Cloudlet cloudlet) { final ResourceManageable ram = vm.getResource(Ram.class); final UtilizationModel um = cloudlet.getUtilizationModelRam(); return um.getUnit() == Unit.ABSOLUTE ? Math.min(um.getUtilization(), vm.getRam().getCapacity()) : um.getUtilization() * ram.getCapacity(); } /** * Computes the length of a given cloudlet, in number * of Instructions (I), which has been executed since the last time cloudlet * processing was updated. * *

* This method considers the delay for actually starting the Cloudlet * execution due to the time to transfer * {@link Cloudlet#getRequiredFiles() required Cloudlet files} from the * Datacenter storage (such as a SAN) to the Vm running the Cloudlet.

* *

* During this transfer time, the method will always return 0 to indicate * that the Cloudlet was not processed in fact, it is just waiting the * required files to be acquired. The required time to transfer the files is * stored in the {@link CloudletExecution#getFileTransferTime()} * attribute and is set when the Cloudlet is submitted to the scheduler.

* * @param cl the Cloudlet to compute the executed length * @param currentTime current simulation time * @return the executed length, in Number of Instructions (I), since the last time cloudlet was processed. * @TODO @author manoelcampos This method is being called 2 times more than required. * Despite it is not causing any apparent issue, it has to be * investigated. For instance, for simulation time 2, with 2 cloudlets, the * method is being called 4 times instead of just 2 (1 for each cloudlet for * that time). * @see #updateCloudletsProcessing(double) */ private long cloudletExecutedInstructionsForTimeSpan(final CloudletExecution cl, final double currentTime) { /* The time the Cloudlet spent executing in fact, since the last time Cloudlet update was * called by the scheduler. If it is zero, indicates that the Cloudlet didn't use * the CPU in this time span, because it is waiting for its required files * to be transferred from the Datacenter storage. */ final double actualProcessingTime = hasCloudletFileTransferTimePassed(cl, currentTime) ? timeSpan(cl, currentTime) : 0; final double cloudletUsedMips = getAbsoluteCloudletResourceUtilization( cl.getCloudlet().getUtilizationModelCpu(), currentTime, getAvailableMipsByPe()); return (long) (cloudletUsedMips * actualProcessingTime * Conversion.MILLION); } /** * Checks if the time to transfer the files required by a Cloudlet to * execute has already passed, in order to start executing the Cloudlet in * fact. * * @param ce Cloudlet to check if the time to transfer the files has passed * @param currentTime the current simulation time * @return true if the time to transfer the files has passed, false * otherwise */ private boolean hasCloudletFileTransferTimePassed(final CloudletExecution ce, final double currentTime) { return ce.getFileTransferTime() == 0 || currentTime - ce.getCloudletArrivalTime() > ce.getFileTransferTime() || ce.getCloudlet().getFinishedLengthSoFar() > 0; } /** * Computes the time span between the current simulation time and the last * time the processing of a cloudlet was updated. * * @param cl the cloudlet to compute the execution time span * @param currentTime the current simulation time * @return */ protected double timeSpan(final CloudletExecution cl, final double currentTime) { return currentTime - cl.getLastProcessingTime(); } /** * Removes finished cloudlets from the * {@link #getCloudletExecList() list of cloudlets to execute} * and adds them to finished list. * * @return the number of finished cloudlets removed from the * {@link #getCloudletExecList() execution list} */ private int removeFinishedCloudletsFromExecutionListAndAddToFinishedList() { final List finishedCloudlets = cloudletExecList.stream() .filter(c -> c.getCloudlet().isFinished()) .collect(toList()); for (final CloudletExecution c : finishedCloudlets) { removeCloudletFromExecListAndAddToFinishedList(c); } return finishedCloudlets.size(); } private void removeCloudletFromExecListAndAddToFinishedList(final CloudletExecution cloudlet) { setCloudletFinishTimeAndAddToFinishedList(cloudlet); removeCloudletFromExecList(cloudlet); } /** * Removes a Cloudlet from the list of cloudlets in execution. * * @param cloudlet the Cloudlet to be removed * @return the removed Cloudlet or {@link CloudletExecution#NULL} if not found */ protected CloudletExecution removeCloudletFromExecList(final CloudletExecution cloudlet) { removeUsedPes(cloudlet.getNumberOfPes()); return cloudletExecList.remove(cloudlet) ? cloudlet : CloudletExecution.NULL; } /** * Sets the finish time of a cloudlet and adds it to the * finished list. * * @param ce the cloudlet to set the finish time */ private void setCloudletFinishTimeAndAddToFinishedList(final CloudletExecution ce) { final double clock = vm.getSimulation().clock(); ce.setFinishTime(clock); cloudletFinish(ce); } /** * Gets the estimated time, considering the current time, that a next Cloudlet is expected to finish. * * @param currentTime current simulation time * @return the estimated finish time of sooner finishing cloudlet * (which is a relative delay from the current simulation time) */ protected double getEstimatedFinishTimeOfSoonerFinishingCloudlet(final double currentTime) { return cloudletExecList .stream() .mapToDouble(c -> getEstimatedFinishTimeOfCloudlet(c, currentTime)) .min().orElse(Double.MAX_VALUE); } /** * Gets the estimated time when a given cloudlet is supposed to finish * executing. It considers the amount of Vm PES and the sum of PEs required * by all VMs running inside the VM. * * @param ce cloudlet to get the estimated finish time * @param currentTime current simulation time * @return the estimated finish time of the given cloudlet * (which is a relative delay from the current simulation time) */ protected double getEstimatedFinishTimeOfCloudlet(final CloudletExecution ce, final double currentTime) { final double cloudletUsedMips = getAbsoluteCloudletResourceUtilization(ce.getCloudlet().getUtilizationModelCpu(), currentTime, getAvailableMipsByPe()); double estimatedFinishTime = ce.getRemainingCloudletLength() / cloudletUsedMips; if (estimatedFinishTime < vm.getSimulation().getMinTimeBetweenEvents()) { estimatedFinishTime = vm.getSimulation().getMinTimeBetweenEvents(); } return estimatedFinishTime; } /** * Selects the next Cloudlets in the waiting list to move to the execution * list in order to start executing them. While there is enough free PEs, * the method try to find a suitable Cloudlet in the list, until it reaches * the end of such a list. * *

* The method might also exchange some cloudlets in the execution list with * some in the waiting list. Thus, some running cloudlets may be preempted * to give opportunity to previously waiting cloudlets to run. This is a * process called * context switch. * However, each CloudletScheduler implementation decides how * such a process is implemented. For instance, Space-Shared schedulers may * just perform context switch just after currently running Cloudlets * completely finish executing. *

*

* This method is called internally by the * {@link CloudletScheduler#updateProcessing(double, List)} one.

* * @pre currentTime >= 0 * @post $none */ protected void moveNextCloudletsFromWaitingToExecList() { Optional optional = Optional.of(CloudletExecution.NULL); while (!cloudletWaitingList.isEmpty() && optional.isPresent() && getFreePes() > 0) { optional = findSuitableWaitingCloudlet(); optional.ifPresent(this::addWaitingCloudletToExecList); } } /** * Try to find the first Cloudlet in the waiting list which the number of * required PEs is not higher than the number of free PEs. * * @return an {@link Optional} containing the found Cloudlet or an empty * Optional otherwise */ protected Optional findSuitableWaitingCloudlet() { return cloudletWaitingList.stream() .filter(this::isThereEnoughFreePesForCloudlet) .findFirst(); } /** * Checks if the amount of PEs required by a given Cloudlet is free to use. * * @param c the Cloudlet to get the number of required PEs * @return true if there is the amount of free PEs, false otherwise */ protected boolean isThereEnoughFreePesForCloudlet(final CloudletExecution c) { return vm.getProcessor().getAvailableResource() >= c.getNumberOfPes(); } /** * Removes a Cloudlet from waiting list and adds it to the exec list. * @param cloudlet the cloudlet to add to to exec list * @return the given cloudlet */ protected CloudletExecution addWaitingCloudletToExecList(final CloudletExecution cloudlet) { /*If the Cloudlet is not found in the waiting List, there is no problem. * Just add it to the exec List.*/ cloudletWaitingList.remove(cloudlet); addCloudletToExecList(cloudlet); return cloudlet; } @Override public Vm getVm() { return vm; } @Override public void setVm(final Vm vm) { Objects.requireNonNull(vm); if (isOtherVmAssigned(vm)) { throw new IllegalArgumentException( "CloudletScheduler already has a Vm assigned to it. Each Vm must have its own CloudletScheduler instance."); } this.vm = vm; } /** * Checks if the {@link CloudletScheduler} has a {@link Vm} assigned that is * different from the given one * * @param vm the Vm to check if assigned scheduler's Vm is different from * @return */ private boolean isOtherVmAssigned(final Vm vm) { return this.vm != null && this.vm != Vm.NULL && !vm.equals(this.vm); } @Override public long getUsedPes() { return vm.getProcessor().getAllocatedResource(); } /** * Gets the number of PEs currently not being used. * * @return */ @Override public long getFreePes() { return currentMipsShare.size() - getUsedPes(); } /** * Adds a given number of PEs to the amount of currently used PEs. * * @param usedPesToAdd number of PEs to add to the amount of used PEs */ private void addUsedPes(final long usedPesToAdd) { vm.getProcessor().allocateResource(usedPesToAdd); } /** * Subtracts a given number of PEs from the amount of currently used PEs. * * @param usedPesToRemove number of PEs to subtract from the amount of used PEs */ private void removeUsedPes(final long usedPesToRemove) { vm.getProcessor().deallocateResource(usedPesToRemove); } @Override public CloudletTaskScheduler getTaskScheduler() { return taskScheduler; } @Override public void setTaskScheduler(final CloudletTaskScheduler taskScheduler) { Objects.requireNonNull(taskScheduler); this.taskScheduler = taskScheduler; this.taskScheduler.setVm(vm); } @Override public boolean isTherePacketScheduler() { return taskScheduler != null && taskScheduler != CloudletTaskScheduler.NULL; } @Override public double getRequestedCpuPercentUtilization(final double time) { return cloudletExecList.stream() .map(CloudletExecution::getCloudlet) .mapToDouble(c -> getAbsoluteCloudletCpuUtilizationForAllPes(time, c)) .sum() / vm.getTotalMipsCapacity(); } /** * Gets the total CPU utilization in MIPS for a Cloudlet, considering * all the PEs in which it is running. * * @param time the simulation time * @param cloudlet the Cloudlet to get the total CPU utilization * @return the total Cloudlet CPU utilization (in MIPS) across all PEs it is using */ private double getAbsoluteCloudletCpuUtilizationForAllPes(final double time, final Cloudlet cloudlet) { final double cloudletCpuUsageForOnePe = getAbsoluteCloudletResourceUtilization( cloudlet.getUtilizationModelCpu(), time, getAvailableMipsByPe()); return cloudletCpuUsageForOnePe * cloudlet.getNumberOfPes(); } @Override public double getRequestedMipsForCloudlet(final CloudletExecution ce, final double time) { return getAbsoluteCloudletResourceUtilization(ce.getCloudlet().getUtilizationModelCpu(), time, vm.getMips()); } @Override public double getAllocatedMipsForCloudlet(final CloudletExecution ce, final double time) { return getAbsoluteCloudletResourceUtilization(ce.getCloudlet().getUtilizationModelCpu(), time, getAvailableMipsByPe()); } @Override public double getCurrentRequestedBwPercentUtilization() { return cloudletExecList.stream() .map(CloudletExecution::getCloudlet) .map(Cloudlet::getUtilizationModelBw) .mapToDouble(um -> getAbsoluteCloudletResourceUtilization(um, vm.getBw().getCapacity())) .sum() / vm.getBw().getCapacity(); } @Override public double getCurrentRequestedRamPercentUtilization() { return cloudletExecList.stream() .map(CloudletExecution::getCloudlet) .map(Cloudlet::getUtilizationModelRam) .mapToDouble(um -> getAbsoluteCloudletResourceUtilization(um, vm.getRam().getCapacity())) .sum() / vm.getRam().getCapacity(); } /** * Computes the absolute amount of a resource used by a given Cloudlet * for the current simulation time, based on the maximum amount of resource that the Cloudlet can use * this time. * * @param um the {@link UtilizationModel} to get the absolute amount of resource used by the Cloudlet * @param maxResourceAllowedToUse the maximum absolute resource that the Cloudlet will be allowed to use * @return the absolute amount of resource that the Cloudlet will use */ private double getAbsoluteCloudletResourceUtilization(final UtilizationModel um, final double maxResourceAllowedToUse) { return getAbsoluteCloudletResourceUtilization(um, vm.getSimulation().clock(), maxResourceAllowedToUse); } /** * Computes the absolute amount of a resource used by a given Cloudlet * for a given time, based on the maximum amount of resource that the Cloudlet can use * this time. * * @param um the {@link UtilizationModel} to get the absolute amount of resource used by the Cloudlet * @param time the simulation time * @param maxResourceAllowedToUse the maximum absolute resource that the Cloudlet will be allowed to use * @return the absolute amount of resource that the Cloudlet will use */ private double getAbsoluteCloudletResourceUtilization( final UtilizationModel um, final double time, final double maxResourceAllowedToUse) { return um.getUnit() == Unit.ABSOLUTE ? Math.min(um.getUtilization(time), maxResourceAllowedToUse) : um.getUtilization() * maxResourceAllowedToUse; } @Override public Set getCloudletReturnedList() { return Collections.unmodifiableSet(cloudletReturnedList); } @Override public boolean isCloudletReturned(final Cloudlet cloudlet) { return cloudletReturnedList.contains(cloudlet); } @Override public void addCloudletToReturnedList(final Cloudlet cloudlet) { this.cloudletReturnedList.add(cloudlet); } @Override public void deallocatePesFromVm(int pesToRemove) { pesToRemove = Math.min(pesToRemove, currentMipsShare.size()); removeUsedPes(pesToRemove); IntStream.range(0, pesToRemove).forEach(i -> currentMipsShare.remove(0)); } @Override public List getCloudletList() { return Stream.concat(cloudletExecList.stream(), cloudletWaitingList.stream()) .map(CloudletExecution::getCloudlet) .collect(collectingAndThen(toList(), Collections::unmodifiableList)); } @Override public boolean isEmpty() { return cloudletExecList.isEmpty() && cloudletWaitingList.isEmpty(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy