/* * 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. * * @authorRodrigo N. Calheiros * @authorAnton Beloglazov * @sinceCloudSim 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 */@Overridepublic void processEvent(SimEvent ev) {//Log.printLine(CloudSim.clock()+"[Broker]: event received:"+ev.getTag());switch (ev.getTag()){// Resource characteristics requestcase 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的characteristicDatacenterCharacteristics characteristics = (DatacenterCharacteristics) ev.getData();//添加到datacenter和characteristic映射表中getDatacenterCharacteristicsList().put(characteristics.getId(), characteristics);//每一個datacenter都得到了characteristicif (getDatacenterCharacteristicsList().size() == getDatacenterIdsList().size()) {setDatacenterRequestedIdsList(new ArrayList<Integer>());//向第一個資料中心請求建立vmscreateVmsInDatacenter(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 createdsubmitCloudlets();} 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 triedfor (int nextDatacenterId : getDatacenterIdsList()) {if (!getDatacenterRequestedIdsList().contains(nextDatacenterId)) {//請求資料中心盡最大能力建立vmscreateVmsInDatacenter(nextDatacenterId);return;}}//all datacenters already queriedif (getVmsCreatedList().size() > 0) { //if some vm were createdsubmitCloudlets(); //提交雲任務} else { //no vms created. abortLog.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 executedLog.printLine(CloudSim.clock()+": "+getName()+ ": All Cloudlets executed. Finishing...");clearDatacenters();finishExecution();} else { //some cloudlets haven't finished yetif (getCloudletList().size()>0 && cloudletsSubmitted==0) { //建立新的虛擬機器//all the cloudlets sent finished. It means that some bount//cloudlet is waiting its VM be createdclearDatacenters();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 oneint 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記錄到requestedidslistgetDatacenterRequestedIdsList().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 yetvm = getVmsCreatedList().get(vmIndex);} else { //submit to the specific vmvm = VmList.getById(getVmsCreatedList(), cloudlet.getVmId());if (vm == null) { // vm was not createdLog.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 listfor (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() */@Overridepublic void shutdownEntity() { Log.printLine(getName() + " is shutting down...");}/* (non-Javadoc) * @see cloudsim.core.SimEntity#startEntity() */@Overridepublic 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;}}