/* * 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.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.cloudbus.cloudsim.core.CloudSim; import org.cloudbus.cloudsim.core.CloudSimTags; import org.cloudbus.cloudsim.core.SimEntity; import org.cloudbus.cloudsim.core.SimEvent; import org.cloudbus.cloudsim.lists.CloudletList; import org.cloudbus.cloudsim.lists.VmList; /** * * DatacentreBroker represents a broker * acting on behalf of a user. It hides VM management, * as vm creation, sumbission of cloudlets to this VMs * and destruction of VMs. * * @author Rodrigo N. Calheiros * @author Anton Beloglazov * @since CloudSim Toolkit 1.0 */ public class DatacenterBroker extends SimEntity { // TODO: remove unnecessary variables /** 需要创建的vm列表The vm list. */ private List<? extends Vm> vmList; /** 已经创建的vm列表The vms created list. */ private List<? extends Vm> vmsCreatedList; /** cloudlet列表The cloudlet list. */ private List<? extends Cloudlet> cloudletList; /** 已经提交的cloudlet列表The cloudlet submitted list. */ private List<? extends Cloudlet> cloudletSubmittedList; /** 接受到的完成的cloudlet,The cloudlet received list. */ private List<? extends Cloudlet> cloudletReceivedList; /** 已经提交的cloudlet数,不包括已经完成返回的cloudletThe cloudlets submitted. */ private int cloudletsSubmitted; /** 已经请求建立的vms,The vms requested. */ private int vmsRequested; /** vm建立恢复数量The vms acks. */ private int vmsAcks; /** The vms destroyed. */ private int vmsDestroyed; /** The datacenter ids list. */ private List<Integer> datacenterIdsList; /** 已经请求过的数据中心列表The datacenter requested ids list. */ private List<Integer> datacenterRequestedIdsList; /** The vms to datacenters map. */ private Map<Integer, Integer> vmsToDatacentersMap; /** The datacenter characteristics list. */ private Map<Integer, DatacenterCharacteristics> datacenterCharacteristicsList; /** * Created a new DatacenterBroker object. * * @param name name to be associated with this entity (as * required by Sim_entity class from simjava package) * * @throws Exception the exception * * @pre name != null * @post $none */ public DatacenterBroker(String name) throws Exception { super(name); setVmList(new ArrayList<Vm>()); setVmsCreatedList(new ArrayList<Vm>()); setCloudletList(new ArrayList<Cloudlet>()); setCloudletSubmittedList(new ArrayList<Cloudlet>()); setCloudletReceivedList(new ArrayList<Cloudlet>()); cloudletsSubmitted=0; setVmsRequested(0); setVmsAcks(0); setVmsDestroyed(0); setDatacenterIdsList(new LinkedList<Integer>()); setDatacenterRequestedIdsList(new ArrayList<Integer>()); setVmsToDatacentersMap(new HashMap<Integer, Integer>()); setDatacenterCharacteristicsList(new HashMap<Integer, DatacenterCharacteristics>()); } /** * 提交创建vm列表 * This method is used to send to the broker the list with * virtual machines that must be created. * * @param list the list * * @pre list !=null * @post $none */ public void submitVmList(List<? extends Vm> list) { getVmList().addAll(list); } /** * This method is used to send to the broker the list of * cloudlets. * * @param list the list * * @pre list !=null * @post $none */ public void submitCloudletList(List<? extends Cloudlet> list){ getCloudletList().addAll(list); } /** * Specifies that a given cloudlet must run in a specific virtual machine. * 绑定一个cloudlet到一个虚拟机上 * @param cloudletId ID of the cloudlet being bount to a vm * @param vmId the vm id * * @pre cloudletId > 0 * @pre id > 0 * @post $none */ public void bindCloudletToVm(int cloudletId, int vmId){ CloudletList.getById(getCloudletList(), cloudletId).setVmId(vmId); } /** * Processes events available for this Broker. * * @param ev a SimEvent object * * @pre ev != null * @post $none */ @Override public void processEvent(SimEvent ev) { //Log.printLine(CloudSim.clock()+"[Broker]: event received:"+ev.getTag()); switch (ev.getTag()){ // Resource characteristics request case CloudSimTags.RESOURCE_CHARACTERISTICS_REQUEST: //收到 请求characteristic事件 processResourceCharacteristicsRequest(ev); //获得数据中心列表,向数据中心发送请求 break; // Resource characteristics answer case CloudSimTags.RESOURCE_CHARACTERISTICS: //得到回答, processResourceCharacteristics(ev); //处理,记录,请求建立虚拟机 break; // VM Creation answer case CloudSimTags.VM_CREATE_ACK: //记录,请求建立更多vm,提交任务 processVmCreate(ev); break; //A finished cloudlet returned case CloudSimTags.CLOUDLET_RETURN: processCloudletReturn(ev); //收到了一个完成的cloudlet,加入到cloudreceivedlist中 break; // if the simulation finishes case CloudSimTags.END_OF_SIMULATION: shutdownEntity(); //关闭 break; // other unknown tags are processed by this method default: processOtherEvent(ev); break; } } /** * 处理从datacenter中心返回的请求characteristic事件 * Process the return of a request for the characteristics of a PowerDatacenter. * * @param ev a SimEvent object * * @pre ev != $null * @post $none */ protected void processResourceCharacteristics(SimEvent ev) { //获得datacenter的characteristic DatacenterCharacteristics characteristics = (DatacenterCharacteristics) ev.getData(); //添加到datacenter和characteristic映射表中 getDatacenterCharacteristicsList().put(characteristics.getId(), characteristics); //每一个datacenter都得到了characteristic if (getDatacenterCharacteristicsList().size() == getDatacenterIdsList().size()) { setDatacenterRequestedIdsList(new ArrayList<Integer>()); //向第一个数据中心请求建立vms createVmsInDatacenter(getDatacenterIdsList().get(0)); } } /** * 处理一个characteristic请求事件 * Process a request for the characteristics of a PowerDatacenter. * * @param ev a SimEvent object * * @pre ev != $null * @post $none */ protected void processResourceCharacteristicsRequest(SimEvent ev) { //设置datacenter所有datacenter中心列表 setDatacenterIdsList(CloudSim.getCloudResourceList()); //建立用于记录datacenter和characteristic的映射表 setDatacenterCharacteristicsList(new HashMap<Integer, DatacenterCharacteristics>()); Log.printLine(CloudSim.clock()+": "+getName()+ ": Cloud Resource List received with "+getDatacenterIdsList().size()+" resource(s)"); //向所有数据中心发送请求 for (Integer datacenterId : getDatacenterIdsList()) { sendNow(datacenterId, CloudSimTags.RESOURCE_CHARACTERISTICS, getId()); } } /** * 发送请求建立虚拟机服务收到确定回答事件后,处理该事件 * 主要是记录,请求建立更多vm,提交任务 * Process the ack received due to a request for VM creation. * * @param ev a SimEvent object * * @pre ev != null * @post $none */ protected void processVmCreate(SimEvent ev) { int[] data = (int[]) ev.getData(); int datacenterId = data[0]; int vmId = data[1]; int result = data[2]; if (result == CloudSimTags.TRUE) { //记录已建立的vm和datacenter到映射表中 getVmsToDatacentersMap().put(vmId, datacenterId); //添加到已建立的vm列表中 getVmsCreatedList().add(VmList.getById(getVmList(), vmId)); Log.printLine(CloudSim.clock()+": "+getName()+ ": VM #"+vmId+" has been created in Datacenter #" + datacenterId + ", Host #" + VmList.getById(getVmsCreatedList(), vmId).getHost().getId()); } else { Log.printLine(CloudSim.clock()+": "+getName()+ ": Creation of VM #"+vmId+" failed in Datacenter #" + datacenterId); } incrementVmsAcks(); //++vmAcks,用于记录收到了多少发送vm创建返回的回答 if (getVmsCreatedList().size() == getVmList().size() - getVmsDestroyed()) { // all the requested VMs have been created submitCloudlets(); } else { //请求的虚拟机都接收到回答了,但是已经建立的虚拟机却不等于虚拟机列表-已经销毁的虚拟机数量,有的虚拟机还没有被创建 //说明第一个数据中心无法在创建vm了 if (getVmsRequested() == getVmsAcks()) { // all the acks received, but some VMs were not created // find id of the next datacenter that has not been tried for (int nextDatacenterId : getDatacenterIdsList()) { if (!getDatacenterRequestedIdsList().contains(nextDatacenterId)) { //请求数据中心尽最大能力建立vms createVmsInDatacenter(nextDatacenterId); return; } } //all datacenters already queried if (getVmsCreatedList().size() > 0) { //if some vm were created submitCloudlets(); //提交云任务 } else { //no vms created. abort Log.printLine(CloudSim.clock() + ": " + getName() + ": none of the required VMs could be created. Aborting"); finishExecution(); } } } } /** * 收到了一个完成的cloudlet,加入到cloudreceivedlist中 * Process a cloudlet return event. * * @param ev a SimEvent object * * @pre ev != $null * @post $none */ protected void processCloudletReturn(SimEvent ev) { Cloudlet cloudlet = (Cloudlet) ev.getData(); getCloudletReceivedList().add(cloudlet); //记录 Log.printLine(CloudSim.clock()+": "+getName()+ ": Cloudlet "+cloudlet.getCloudletId()+" received"); cloudletsSubmitted--; if (getCloudletList().size()==0&&cloudletsSubmitted==0) { //结束all cloudlets executed Log.printLine(CloudSim.clock()+": "+getName()+ ": All Cloudlets executed. Finishing..."); clearDatacenters(); finishExecution(); } else { //some cloudlets haven't finished yet if (getCloudletList().size()>0 && cloudletsSubmitted==0) { //创建新的虚拟机 //all the cloudlets sent finished. It means that some bount //cloudlet is waiting its VM be created clearDatacenters(); createVmsInDatacenter(0); } } } /** * Overrides this method when making a new and different type of Broker. * This method is called by {@link #body()} for incoming unknown tags. * * @param ev a SimEvent object * * @pre ev != null * @post $none */ protected void processOtherEvent(SimEvent ev){ if (ev == null){ Log.printLine(getName() + ".processOtherEvent(): " + "Error - an event is null."); return; } Log.printLine(getName() + ".processOtherEvent(): " + "Error - event unknown by this DatacenterBroker."); } /** * Create the virtual machines in a datacenter. * 创建一些虚拟机在datacenter中心,尽最大努力建立 * @param datacenterId Id of the chosen PowerDatacenter * * @pre $none * @post $none */ protected void createVmsInDatacenter(int datacenterId) { // send as much vms as possible for this datacenter before trying the next one int requestedVms = 0; String datacenterName = CloudSim.getEntityName(datacenterId); for (Vm vm : getVmList()) { if (!getVmsToDatacentersMap().containsKey(vm.getId())) { Log.printLine(CloudSim.clock() + ": " + getName() + ": Trying to Create VM #" + vm.getId() + " in " + datacenterName); sendNow(datacenterId, CloudSimTags.VM_CREATE_ACK, vm); //发送到datacenter创建 requestedVms++; } } //已经请求的datacenter记录到requestedidslist getDatacenterRequestedIdsList().add(datacenterId); //设置已经请求建立的虚拟机的数量 setVmsRequested(requestedVms); setVmsAcks(0); } /** * vm被建立后可以提交cloudlets了,提交的cloudlets从等待队列中移进sumittedlist中 * Submit cloudlets to the created VMs. * * @pre $none * @post $none */ protected void submitCloudlets() { int vmIndex = 0; for (Cloudlet cloudlet : getCloudletList()) { Vm vm; if (cloudlet.getVmId() == -1) { //没有指定则直接选择第一个可用虚拟机if user didn't bind this cloudlet and it has not been executed yet vm = getVmsCreatedList().get(vmIndex); } else { //submit to the specific vm vm = VmList.getById(getVmsCreatedList(), cloudlet.getVmId()); if (vm == null) { // vm was not created Log.printLine(CloudSim.clock()+": "+getName()+ ": Postponing execution of cloudlet "+cloudlet.getCloudletId()+": bount VM not available"); continue; } } Log.printLine(CloudSim.clock()+": "+getName()+ ": Sending cloudlet "+cloudlet.getCloudletId()+" to VM #"+vm.getId()); cloudlet.setVmId(vm.getId()); //发送到指定的虚拟机 sendNow(getVmsToDatacentersMap().get(vm.getId()), CloudSimTags.CLOUDLET_SUBMIT, cloudlet); cloudletsSubmitted++; vmIndex = (vmIndex + 1) % getVmsCreatedList().size(); getCloudletSubmittedList().add(cloudlet); } // remove submitted cloudlets from waiting list for (Cloudlet cloudlet : getCloudletSubmittedList()) { getCloudletList().remove(cloudlet); } } /** * 清理在数据中心的虚拟机 * Destroy the virtual machines running in datacenters. * * @pre $none * @post $none */ protected void clearDatacenters() { for (Vm vm : getVmsCreatedList()) { Log.printLine(CloudSim.clock() + ": " + getName() + ": Destroying VM #" + vm.getId()); sendNow(getVmsToDatacentersMap().get(vm.getId()), CloudSimTags.VM_DESTROY, vm); } getVmsCreatedList().clear(); } /** * Send an internal event communicating the end of the simulation. * * @pre $none * @post $none */ private void finishExecution() { sendNow(getId(), CloudSimTags.END_OF_SIMULATION); } /* (non-Javadoc) * @see cloudsim.core.SimEntity#shutdownEntity() */ @Override public void shutdownEntity() { Log.printLine(getName() + " is shutting down..."); } /* (non-Javadoc) * @see cloudsim.core.SimEntity#startEntity() */ @Override public void startEntity() { Log.printLine(getName() + " is starting..."); schedule(getId(), 0, CloudSimTags.RESOURCE_CHARACTERISTICS_REQUEST); } /** * Gets the vm list. * * @param <T> the generic type * @return the vm list */ @SuppressWarnings("unchecked") public <T extends Vm> List<T> getVmList() { return (List<T>) vmList; } /** * Sets the vm list. * * @param <T> the generic type * @param vmList the new vm list */ protected <T extends Vm> void setVmList(List<T> vmList) { this.vmList = vmList; } /** * Gets the cloudlet list. * * @param <T> the generic type * @return the cloudlet list */ @SuppressWarnings("unchecked") public <T extends Cloudlet> List<T> getCloudletList() { return (List<T>) cloudletList; } /** * Sets the cloudlet list. * * @param <T> the generic type * @param cloudletList the new cloudlet list */ protected <T extends Cloudlet> void setCloudletList(List<T> cloudletList) { this.cloudletList = cloudletList; } /** * Gets the cloudlet submitted list. * * @param <T> the generic type * @return the cloudlet submitted list */ @SuppressWarnings("unchecked") public <T extends Cloudlet> List<T> getCloudletSubmittedList() { return (List<T>) cloudletSubmittedList; } /** * Sets the cloudlet submitted list. * * @param <T> the generic type * @param cloudletSubmittedList the new cloudlet submitted list */ protected <T extends Cloudlet> void setCloudletSubmittedList(List<T> cloudletSubmittedList) { this.cloudletSubmittedList = cloudletSubmittedList; } /** * Gets the cloudlet received list. * * @param <T> the generic type * @return the cloudlet received list */ @SuppressWarnings("unchecked") public <T extends Cloudlet> List<T> getCloudletReceivedList() { return (List<T>) cloudletReceivedList; } /** * Sets the cloudlet received list. * * @param <T> the generic type * @param cloudletReceivedList the new cloudlet received list */ protected <T extends Cloudlet> void setCloudletReceivedList(List<T> cloudletReceivedList) { this.cloudletReceivedList = cloudletReceivedList; } /** * Gets the vm list. * * @param <T> the generic type * @return the vm list */ @SuppressWarnings("unchecked") public <T extends Vm> List<T> getVmsCreatedList() { return (List<T>) vmsCreatedList; } /** * Sets the vm list. * * @param <T> the generic type * @param vmsCreatedList the vms created list */ protected <T extends Vm> void setVmsCreatedList(List<T> vmsCreatedList) { this.vmsCreatedList = vmsCreatedList; } /** * Gets the vms requested. * * @return the vms requested */ protected int getVmsRequested() { return vmsRequested; } /** * 新请求的vms * Sets the vms requested. * * @param vmsRequested the new vms requested */ protected void setVmsRequested(int vmsRequested) { this.vmsRequested = vmsRequested; } /** * Gets the vms acks. * * @return the vms acks */ protected int getVmsAcks() { return vmsAcks; } /** * Sets the vms acks. * * @param vmsAcks the new vms acks */ protected void setVmsAcks(int vmsAcks) { this.vmsAcks = vmsAcks; } /** * Increment vms acks. */ protected void incrementVmsAcks() { this.vmsAcks++; } /** * Gets the vms destroyed. * * @return the vms destroyed */ protected int getVmsDestroyed() { return vmsDestroyed; } /** * Sets the vms destroyed. * * @param vmsDestroyed the new vms destroyed */ protected void setVmsDestroyed(int vmsDestroyed) { this.vmsDestroyed = vmsDestroyed; } /** * Gets the datacenter ids list. * * @return the datacenter ids list */ protected List<Integer> getDatacenterIdsList() { return datacenterIdsList; } /** * Sets the datacenter ids list. * * @param datacenterIdsList the new datacenter ids list */ protected void setDatacenterIdsList(List<Integer> datacenterIdsList) { this.datacenterIdsList = datacenterIdsList; } /** * Gets the vms to datacenters map. * * @return the vms to datacenters map */ protected Map<Integer, Integer> getVmsToDatacentersMap() { return vmsToDatacentersMap; } /** * Sets the vms to datacenters map. * * @param vmsToDatacentersMap the vms to datacenters map */ protected void setVmsToDatacentersMap(Map<Integer, Integer> vmsToDatacentersMap) { this.vmsToDatacentersMap = vmsToDatacentersMap; } /** * Gets the datacenter characteristics list. * * @return the datacenter characteristics list */ protected Map<Integer, DatacenterCharacteristics> getDatacenterCharacteristicsList() { return datacenterCharacteristicsList; } /** * Sets the datacenter characteristics list. * * @param datacenterCharacteristicsList the datacenter characteristics list */ protected void setDatacenterCharacteristicsList(Map<Integer, DatacenterCharacteristics> datacenterCharacteristicsList) { this.datacenterCharacteristicsList = datacenterCharacteristicsList; } /** * Gets the datacenter requested ids list. * * @return the datacenter requested ids list */ protected List<Integer> getDatacenterRequestedIdsList() { return datacenterRequestedIdsList; } /** * Sets the datacenter requested ids list. * * @param datacenterRequestedIdsList the new datacenter requested ids list */ protected void setDatacenterRequestedIdsList(List<Integer> datacenterRequestedIdsList) { this.datacenterRequestedIdsList = datacenterRequestedIdsList; } }