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

org.cloudbus.cloudsim.cloudlets.CloudletAbstract 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.cloudlets;

import org.cloudbus.cloudsim.brokers.DatacenterBroker;
import org.cloudbus.cloudsim.core.Simulation;
import org.cloudbus.cloudsim.core.UniquelyIdentificable;
import org.cloudbus.cloudsim.datacenters.Datacenter;
import org.cloudbus.cloudsim.utilizationmodels.UtilizationModel;
import org.cloudbus.cloudsim.vms.Vm;
import org.cloudsimplus.listeners.CloudletVmEventInfo;
import org.cloudsimplus.listeners.EventListener;

import java.util.*;

/**
 * A base class for {@link Cloudlet} implementations.
 *
 * @author Rodrigo N. Calheiros
 * @author Anton Beloglazov
 * @author Manoel Campos da Silva Filho
 */
public abstract class CloudletAbstract implements Cloudlet {
    /**
     * @see #getId()
     */
    private int id;
    /**
     * The list of every {@link Datacenter} where the cloudlet has been executed.
     * In case it starts and finishes executing in a single Datacenter, without
     * being migrated, this list will have only one item.
     *
     * @todo There isn't Cloudlet migration, so this attribute doesn't make sense.
     * But since a lot of methods uses this attribute, it's removal has to be carefully assessed.
     */
    private final List datacenterExecutionList;
    /**
     * @see #getBroker()
     */
    private DatacenterBroker broker;
    /**
     * @see #getLength()
     */
    private long length;
    /**
     * @see #getNumberOfPes()
     */
    private long numberOfPes;
    /**
     * @see #getStatus()
     */
    private Status status;
    /**
     * @see #getExecStartTime()
     */
    private double execStartTime;
    /**
     * @see #getPriority()
     */
    private int priority;
    /**
     * @see #getNetServiceLevel()
     */
    private int netServiceLevel;
    /**
     * @see #getVm()
     */
    private Vm vm;
    /**
     * @see #getRequiredFiles()
     */
    private List requiredFiles;

    /**
     * The index of the last Datacenter where the cloudlet was executed. If the
     * cloudlet is migrated during its execution, this index is updated. The
     * value {@link #NOT_ASSIGNED} indicates the cloudlet has not been executed yet.
     */
    private int lastExecutedDatacenterIdx;

    /**
     * @see #getFileSize()
     */
    private long fileSize;
    /**
     * @see #getOutputSize()
     */
    private long outputSize;
    /**
     * @see #getFinishTime()
     */
    private double finishTime;
    /**
     * @see #getCostPerBw()
     */
    private double costPerBw;
    /**
     * @see #getAccumulatedBwCost()
     */
    private double accumulatedBwCost;
    /**
     * @see #getUtilizationModelCpu()
     */
    private UtilizationModel utilizationModelCpu;
    /**
     * @see #getUtilizationModelRam()
     */
    private UtilizationModel utilizationModelRam;
    /**
     * @see #getUtilizationModelBw()
     */
    private UtilizationModel utilizationModelBw;

    private final Set> onFinishListeners;
    private final Set> onUpdateProcessingListeners;

    /**
     * @see #getSubmissionDelay()
     */
    private double submissionDelay;

    /**
     * Creates a Cloudlet with no priority and file size and output size equal to 1.
     *
     * @param cloudletId     id of the Cloudlet
     * @param length the length or size (in MI) of this cloudlet to be executed in a VM
     * @param pesNumber      number of PEs that Cloudlet will require
     */
    public CloudletAbstract(final int cloudletId, final long length, final long pesNumber) {
        /*
        Normally, a Cloudlet is only executed on a Datacenter without being
        migrated to others. Hence, to reduce memory consumption, set the
        size of this ArrayList to be less than the default one.
        */
        this.datacenterExecutionList = new ArrayList<>(2);
        this.requiredFiles = new LinkedList<>();

        this.id = cloudletId;
        this.netServiceLevel = 0;
        this.execStartTime = 0.0;
        this.status = Status.INSTANTIATED;
        this.priority = 0;
        this.setNumberOfPes(pesNumber);

        this.lastExecutedDatacenterIdx = NOT_ASSIGNED;
        setBroker(DatacenterBroker.NULL);
        setFinishTime(NOT_ASSIGNED);    // meaning this Cloudlet hasn't finished yet
        setVm(Vm.NULL);

        this.setLength(length);
        this.setFileSize(1);
        this.setOutputSize(1);

        setAccumulatedBwCost(0.0);
        setCostPerBw(0.0);
        setSubmissionDelay(0.0);

        setUtilizationModelCpu(UtilizationModel.NULL);
        setUtilizationModelRam(UtilizationModel.NULL);
        setUtilizationModelBw(UtilizationModel.NULL);
        onFinishListeners = new HashSet<>();
        onUpdateProcessingListeners = new HashSet<>();
    }

    /**
     * Creates a Cloudlet with no priority or id. The id is defined when the Cloudlet is submitted to
     * a {@link DatacenterBroker}. The file size and output size is defined as 1.
     *
     * @param length the length or size (in MI) of this cloudlet to be executed in a VM
     * @param pesNumber number of PEs that Cloudlet will require
     */
    public CloudletAbstract(final long length, final int pesNumber) {
        this(-1, length, pesNumber);
    }

    /**
     * Creates a Cloudlet with no priority or id. The id is defined when the Cloudlet is submitted to
     * a {@link DatacenterBroker}. The file size and output size is defined as 1.
     *
     * @param length the length or size (in MI) of this cloudlet to be executed in a VM
     * @param pesNumber number of PEs that Cloudlet will require
     */
    public CloudletAbstract(final long length, final long pesNumber) {
        this(-1, length, pesNumber);
    }

    protected int getLastExecutedDatacenterIdx() {
        return lastExecutedDatacenterIdx;
    }

    protected void setLastExecutedDatacenterIdx(int lastExecutedDatacenterIdx) {
        this.lastExecutedDatacenterIdx = lastExecutedDatacenterIdx;
    }

    @Override
    public Cloudlet setUtilizationModel(UtilizationModel utilizationModel) {
        setUtilizationModelBw(utilizationModel);
        setUtilizationModelRam(utilizationModel);
        setUtilizationModelCpu(utilizationModel);
        return this;
    }

    @Override
    public Cloudlet addOnUpdateProcessingListener(EventListener listener) {
        Objects.requireNonNull(listener);
        this.onUpdateProcessingListeners.add(listener);
        return this;
    }

    @Override
    public boolean removeOnUpdateProcessingListener(EventListener listener) {
        return this.onUpdateProcessingListeners.remove(listener);
    }

    @Override
    public Cloudlet addOnFinishListener(EventListener listener) {
        Objects.requireNonNull(listener);
        this.onFinishListeners.add(listener);
        return this;
    }

    @Override
    public boolean removeOnFinishListener(EventListener listener) {
        return onFinishListeners.remove(listener);
    }

    @Override
    public void notifyOnUpdateProcessingListeners(double time) {
        onUpdateProcessingListeners.forEach(l -> l.update(CloudletVmEventInfo.of(l, time, this)));
    }

    @Override
    public final Cloudlet setLength(final long length) {
        if (length <= 0) {
            throw new IllegalArgumentException("Cloudlet length has to be greater than zero.");
        }

        this.length = length;
        return this;
    }

    @Override
    public boolean setNetServiceLevel(final int netServiceLevel) {
        if (netServiceLevel > 0) {
            this.netServiceLevel = netServiceLevel;
            return true;
        }

        return false;
    }

    @Override
    public int getNetServiceLevel() {
        return netServiceLevel;
    }

    @Override
    public double getWaitingTime() {
        if (datacenterExecutionList.isEmpty()) {
            return 0;
        }

        // use the latest resource submission time
        final double subTime = getLastExecutionInDatacenterInfo().getArrivalTime();
        return execStartTime - subTime;
    }

    @Override
    public int getPriority() {
        return priority;
    }

    @Override
    public void setPriority(final int priority) {
        this.priority = priority;
    }

    @Override
    public final Cloudlet setNumberOfPes(final long numberOfPes) {
        if (numberOfPes <= 0) {
            throw new IllegalArgumentException("Cloudlet number of PEs has to be greater than zero.");
        }
        this.numberOfPes = numberOfPes;
        return this;
    }

    @Override
    public long getNumberOfPes() {
        return numberOfPes;
    }

    @Override
    public long getFinishedLengthSoFar(final Datacenter datacenter) {
        return getDatacenterInfo(datacenter).getFinishedSoFar();
    }

    @Override
    public long getFinishedLengthSoFar() {
        if (datacenterExecutionList.isEmpty()) {
            return 0;
        }

        return Math.min(getLastExecutionInDatacenterInfo().getFinishedSoFar(), getLength());
    }

    @Override
    public boolean isFinished() {
        if (datacenterExecutionList.isEmpty()) {
            return false;
        }

        return getLastExecutionInDatacenterInfo().getFinishedSoFar() >= getLength();
    }

    @Override
    public boolean addFinishedLengthSoFar(final long partialFinishedMI) {
        if (partialFinishedMI < 0.0 || datacenterExecutionList.isEmpty()) {
            return false;
        }


        final long maxLengthToAdd = Math.min(partialFinishedMI, getLength()-getFinishedLengthSoFar());
        getLastExecutionInDatacenterInfo().addFinishedSoFar(maxLengthToAdd);
        notifyListenersIfCloudletIsFinished();
        return true;
    }

    /**
     * Notifies all registered listeners about the termination of the Cloudlet
     * if it in fact has finished.
     * It then removes the registered listeners to avoid a Listener to be notified
     * multiple times about a Cloudlet termination.
     */
    private void notifyListenersIfCloudletIsFinished() {
        if (isFinished()) {
            onFinishListeners.forEach(l -> l.update(CloudletVmEventInfo.of(l, this)));
            onFinishListeners.clear();
        }
    }

    @Override
    public final Cloudlet setBroker(final DatacenterBroker broker) {
        Objects.requireNonNull(broker);
        this.broker = broker;
        return this;
    }

    @Override
    public DatacenterBroker getBroker() {
        return broker;
    }

    @Override
    public Datacenter getLastDatacenter() {
        return getLastExecutionInDatacenterInfo().getDatacenter();
    }

    private CloudletDatacenterExecution getLastExecutionInDatacenterInfo() {
        if (datacenterExecutionList.isEmpty()) {
            return CloudletDatacenterExecution.NULL;
        }

        return datacenterExecutionList.get(datacenterExecutionList.size() - 1);
    }

    @Override
    public long getFileSize() {
        return fileSize;
    }

    @Override
    public long getOutputSize() {
        return outputSize;
    }

    @Override
    public double getExecStartTime() {
        return execStartTime;
    }

    @Override
    public void setExecStartTime(final double clockTime) {
        this.execStartTime = clockTime;
    }

    @Override
    public boolean setWallClockTime(final double wallTime, final double actualCpuTime) {
        if (wallTime < 0.0 || actualCpuTime < 0.0 || datacenterExecutionList.isEmpty()) {
            return false;
        }

        final CloudletDatacenterExecution datacenter = getLastExecutionInDatacenterInfo();
        datacenter.setWallClockTime(wallTime);
        datacenter.setActualCpuTime(actualCpuTime);

        return true;
    }

    @Override
    public boolean setStatus(final Status newStatus) {
        // if the new status is same as current one, then ignore the rest
        if (this.status == newStatus) {
            return false;
        }

        if (newStatus == Status.SUCCESS) {
            setFinishTime(getSimulation().clock());
        }

        this.status = newStatus;
        return true;
    }

    @Override
    public long getLength() {
        return length;
    }

    @Override
    public long getTotalLength() {
        return length * numberOfPes;
    }

    @Override
    public double getCostPerSec() {
        return getLastExecutionInDatacenterInfo().getCostPerSec();
    }

    @Override
    public double getCostPerSec(final Datacenter datacenter) {
        return getDatacenterInfo(datacenter).getCostPerSec();
    }

    @Override
    public double getWallClockTimeInLastExecutedDatacenter() {
        return getLastExecutionInDatacenterInfo().getWallClockTime();
    }

    @Override
    public double getActualCpuTime(final Datacenter datacenter) {
        return getDatacenterInfo(datacenter).getActualCpuTime();
    }

    @Override
    public double getActualCpuTime() {
        if (getFinishTime() == NOT_ASSIGNED) {
            return NOT_ASSIGNED;
        }

        return finishTime - execStartTime;
    }

    @Override
    public double getArrivalTime(final Datacenter datacenter) {
        return getDatacenterInfo(datacenter).getArrivalTime();
    }

    @Override
    public double getWallClockTime(final Datacenter datacenter) {
        return getDatacenterInfo(datacenter).getWallClockTime();
    }

    /**
     * Gets information about the cloudlet execution on a given Datacenter.
     *
     * @param datacenterId the Datacenter entity ID
     * @return the Cloudlet execution information on the given Datacenter
     * or {@link CloudletDatacenterExecution#NULL} if the Cloudlet has never been executed there
     * @pre dc >= 0
     * @post $none
     */
    private CloudletDatacenterExecution getDatacenterInfo(final int datacenterId) {
        return datacenterExecutionList.stream()
            .filter(info -> info.getDatacenter().getId() == datacenterId)
            .findFirst().orElse(CloudletDatacenterExecution.NULL);
    }

    /**
     * Gets information about the cloudlet execution on a given Datacenter.
     *
     * @param datacenter the Datacenter entity
     * @return the Cloudlet execution information on the given Datacenter
     * or {@link CloudletDatacenterExecution#NULL} if the Cloudlet has never been executed there
     * @pre dc >= 0
     * @post $none
     */
    private CloudletDatacenterExecution getDatacenterInfo(final Datacenter datacenter) {
        return getDatacenterInfo(datacenter.getId());
    }

    @Override
    public double getFinishTime() {
        return finishTime;
    }

    /**
     * Sets the {@link #getFinishTime() finish time} of this cloudlet in the latest Datacenter.
     *
     * @param finishTime the finish time
     */
    protected final void setFinishTime(final double finishTime) {
        this.finishTime = finishTime;
    }

    @Override
    public Status getStatus() {
        return status;
    }

    @Override
    public int getId() {
        return id;
    }

    @Override
    public void setId(int id) {
        this.id = id;
    }

    @Override
    public Vm getVm() {
        return vm;
    }

    @Override
    public final Cloudlet setVm(final Vm vm) {
        this.vm = vm;
        return this;
    }

    @Override
    public double getTotalCost() {
        // cloudlet cost: execution cost...
        double totalCost = getTotalCpuCostForAllDatacenters();

        // ... plus input data transfer cost...
        totalCost += accumulatedBwCost;

        // ... plus output cost
        totalCost += costPerBw * outputSize;
        return totalCost;
    }

    /**
     * Gets the total cost for using CPU on every Datacenter where the Cloudlet has executed.
     *
     * @return
     */
    private double getTotalCpuCostForAllDatacenters() {
        return datacenterExecutionList.stream()
            .mapToDouble(dcInfo -> dcInfo.getActualCpuTime() * dcInfo.getCostPerSec())
            .sum();
    }

    @Override
    public List getRequiredFiles() {
        return requiredFiles;
    }

    /**
     * Sets the list of {@link #getRequiredFiles() required files}.
     *
     * @param requiredFiles the new list of required files
     */
    public final void setRequiredFiles(final List requiredFiles) {
        Objects.requireNonNull(requiredFiles);
        this.requiredFiles = requiredFiles;
    }

    @Override
    public boolean addRequiredFile(final String fileName) {
        if (getRequiredFiles().stream().anyMatch(s -> s.equals(fileName))) {
            return false;
        }

        requiredFiles.add(fileName);
        return true;
    }

    @Override
    public boolean addRequiredFiles(final List fileNames) {
        boolean atLeastOneFileAdded = false;
        for (final String fileName : fileNames) {
            atLeastOneFileAdded |= addRequiredFile(fileName);
        }
        return atLeastOneFileAdded;
    }

    @Override
    public boolean deleteRequiredFile(final String filename) {
        for (int i = 0; i < getRequiredFiles().size(); i++) {
            final String temp = requiredFiles.get(i);

            if (temp.equals(filename)) {
                requiredFiles.remove(i);
                return true;
            }
        }

        return false;
    }

    @Override
    public boolean requiresFiles() {
        return !getRequiredFiles().isEmpty();
    }

    @Override
    public UtilizationModel getUtilizationModelCpu() {
        return utilizationModelCpu;
    }

    @Override
    public final Cloudlet setUtilizationModelCpu(final UtilizationModel utilizationModelCpu) {
        Objects.requireNonNull(utilizationModelCpu);
        this.utilizationModelCpu = utilizationModelCpu;
        return this;
    }

    @Override
    public UtilizationModel getUtilizationModelRam() {
        return utilizationModelRam;
    }

    @Override
    public final Cloudlet setUtilizationModelRam(final UtilizationModel utilizationModelRam) {
        Objects.requireNonNull(utilizationModelRam);
        this.utilizationModelRam = utilizationModelRam;
        return this;
    }

    @Override
    public UtilizationModel getUtilizationModelBw() {
        return utilizationModelBw;
    }

    @Override
    public final Cloudlet setUtilizationModelBw(final UtilizationModel utilizationModelBw) {
        Objects.requireNonNull(utilizationModelBw);
        this.utilizationModelBw = utilizationModelBw;
        return this;
    }

    @Override
    public double getUtilizationOfCpu() {
        return getUtilizationOfCpu(getSimulation().clock());
    }

    @Override
    public double getUtilizationOfCpu(final double time) {
        return getUtilizationModelCpu().getUtilization(time);
    }

    @Override
    public double getUtilizationOfBw() {
        return getUtilizationOfBw(getSimulation().clock());
    }

    @Override
    public double getUtilizationOfBw(final double time) {
        return getUtilizationModelBw().getUtilization(time);
    }

    @Override
    public double getUtilizationOfRam() {
        return getUtilizationOfRam(getSimulation().clock());
    }

    @Override
    public double getUtilizationOfRam(final double time) {
        return getUtilizationModelRam().getUtilization(time);
    }

    @Override
    public double getCostPerBw() {
        return costPerBw;
    }

    /**
     * Sets {@link #getCostPerBw() the cost of each byte of bandwidth (bw)} consumed.
     *
     * @param costPerBw the new cost per bw to set
     */
    protected final void setCostPerBw(double costPerBw) {
        this.costPerBw = costPerBw;
    }

    @Override
    public double getAccumulatedBwCost() {
        return accumulatedBwCost;
    }

    /**
     * Sets the {@link #getAccumulatedBwCost() accumulated bw cost}.
     *
     * @param accumulatedBwCost the accumulated bw cost to set
     */
    protected final void setAccumulatedBwCost(double accumulatedBwCost) {
        this.accumulatedBwCost = accumulatedBwCost;
    }

    @Override
    public double getSubmissionDelay() {
        return this.submissionDelay;
    }

    @Override
    public final void setSubmissionDelay(final double submissionDelay) {
        if (submissionDelay < 0) {
            return;
        }

        this.submissionDelay = submissionDelay;
    }

    @Override
    public boolean isBindToVm() {
        return vm != null && vm != Vm.NULL;
    }

    @Override
    public final Cloudlet setFileSize(final long fileSize) {
        if (fileSize <= 0) {
            throw new IllegalArgumentException("Cloudlet file size has to be greater than zero.");
        }

        this.fileSize = fileSize;
        return this;
    }

    @Override
    public final Cloudlet setOutputSize(final long outputSize) {
        if (outputSize <= 0) {
            throw new IllegalArgumentException("Cloudlet output size has to be greater than zero.");
        }
        this.outputSize = outputSize;
        return this;
    }

    @Override
    public void assignToDatacenter(final Datacenter datacenter) {
        final CloudletDatacenterExecution dcInfo = new CloudletDatacenterExecution();
        dcInfo.setDatacenter(datacenter);
        dcInfo.setCostPerSec(datacenter.getCharacteristics().getCostPerSecond());

        // add into a list if moving to a new cloud Datacenter
        datacenterExecutionList.add(dcInfo);

        setLastExecutedDatacenterIdx(getLastExecutedDatacenterIdx() + 1);

        this.setCostPerBw(datacenter.getCharacteristics().getCostPerBw());
        setAccumulatedBwCost(this.costPerBw * fileSize);
    }

    @Override
    public double registerArrivalInDatacenter() {
        if (!isAssignedToDatacenter()) {
            return NOT_ASSIGNED;
        }

        final CloudletDatacenterExecution dcInfo = datacenterExecutionList.get(lastExecutedDatacenterIdx);
        dcInfo.setArrivalTime(getSimulation().clock());

        return dcInfo.getArrivalTime();
    }

    @Override
    public boolean isAssignedToDatacenter() {
        return !datacenterExecutionList.isEmpty();
    }

    @Override
    public double getLastDatacenterArrivalTime() {
        return getLastExecutionInDatacenterInfo().getArrivalTime();
    }

    @Override
    public String getUid() {
        return UniquelyIdentificable.getUid(broker.getId(), id);
    }

    @Override
    public Simulation getSimulation() {
        return broker.getSimulation();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof CloudletAbstract)) return false;

        final CloudletAbstract that = (CloudletAbstract) o;

        if (id != that.id) return false;
        return broker.equals(that.broker);
    }

    @Override
    public int hashCode() {
        int result = id;
        result = 31 * result + broker.hashCode();
        return result;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy