/*
* 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.network.datacenter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.cloudbus.cloudsim.Cloudlet;
import org.cloudbus.cloudsim.CloudletScheduler;
import org.cloudbus.cloudsim.Datacenter;
import org.cloudbus.cloudsim.DatacenterCharacteristics;
import org.cloudbus.cloudsim.Host;
import org.cloudbus.cloudsim.Log;
import org.cloudbus.cloudsim.Storage;
import org.cloudbus.cloudsim.Vm;
import org.cloudbus.cloudsim.VmAllocationPolicy;
import org.cloudbus.cloudsim.core.CloudSim;
import org.cloudbus.cloudsim.core.CloudSimTags;
import org.cloudbus.cloudsim.core.SimEvent;
/**
* NetworkDatacenter class is a {@link Datacenter} whose hostList are virtualized and networked. It contains
* all the information about internal network. For example, which VM is connected to what switch etc. It
* deals with processing of VM queries (i.e., handling of VMs) instead of processing
* Cloudlet-related queries. So, even though an AllocPolicy will be instantiated (in the init()
* method of the superclass, it will not be used, as processing of cloudlets are handled by the
* CloudletScheduler and processing of VirtualMachines are handled by the VmAllocationPolicy.
*
* @todo If an AllocPolicy is not being used, why it is being created. Perhaps
* a better class hierarchy should be created, introducing some abstract class
* or interface.
*
* <br/>Please refer to following publication for more details:<br/>
* <ul>
* <li><a href="http://dx.doi.org/10.1109/UCC.2011.24">Saurabh Kumar Garg and Rajkumar Buyya, NetworkCloudSim: Modelling Parallel Applications in Cloud
* Simulations, Proceedings of the 4th IEEE/ACM International Conference on Utility and Cloud
* Computing (UCC 2011, IEEE CS Press, USA), Melbourne, Australia, December 5-7, 2011.</a>
* </ul>
*
* @author Saurabh Kumar Garg
* @since CloudSim Toolkit 3.0
*/
public class NetworkDatacenter extends Datacenter {
/**
* A map between VMs and Switches, where each key
* is a VM id and the corresponding value is the id of the switch where the VM is connected to.
*/
public Map<Integer, Integer> VmToSwitchid = new HashMap<Integer, Integer>();
/**
* A map between hosts and Switches, where each key
* is a host id and the corresponding value is the id of the switch where the host is connected to.
*/
public Map<Integer, Integer> HostToSwitchid;
/**
* A map of datacenter switches where each key is a switch id
* and the corresponding value is the switch itself.
*/
public Map<Integer, Switch> Switchlist;
/**
* A map between VMs and Hosts, where each key
* is a VM id and the corresponding value is the id of the host where the VM is placed.
*/
public Map<Integer, Integer> VmtoHostlist;
/**
* Instantiates a new NetworkDatacenter object.
*
* @param name the name to be associated with this entity (as required by {@link org.cloudbus.cloudsim.core.SimEntity})
* @param characteristics the datacenter characteristics
* @param vmAllocationPolicy the vmAllocationPolicy
* @param storageList a List of storage elements, for data simulation
* @param schedulingInterval the scheduling delay to process each datacenter received event
*
* @throws Exception when one of the following scenarios occur:
* <ul>
* <li>creating this entity before initializing CloudSim package
* <li>this entity name is <tt>null</tt> or empty
* <li>this entity has <tt>zero</tt> number of PEs (Processing Elements). <br>
* No PEs mean the Cloudlets can't be processed. A CloudResource must contain one or
* more Machines. A Machine must contain one or more PEs.
* </ul>
*
* @pre name != null
* @pre resource != null
* @post $none
*/
public NetworkDatacenter(
String name,
DatacenterCharacteristics characteristics,
VmAllocationPolicy vmAllocationPolicy,
List<Storage> storageList,
double schedulingInterval) throws Exception {
super(name, characteristics, vmAllocationPolicy, storageList, schedulingInterval);
VmToSwitchid = new HashMap<Integer, Integer>();
HostToSwitchid = new HashMap<Integer, Integer>();
VmtoHostlist = new HashMap<Integer, Integer>();
Switchlist = new HashMap<Integer, Switch>();
}
/**
* Gets a map of all EdgeSwitches in the Datacenter network.
* One can design similar functions for other type of switches.
*
* @return a EdgeSwitches map, where each key is the switch id
* and each value it the switch itself.
*/
public Map<Integer, Switch> getEdgeSwitch() {
Map<Integer, Switch> edgeswitch = new HashMap<Integer, Switch>();
for (Entry<Integer, Switch> es : Switchlist.entrySet()) {
if (es.getValue().level == NetworkConstants.EDGE_LEVEL) {
edgeswitch.put(es.getKey(), es.getValue());
}
}
return edgeswitch;
}
/**
* Creates the given VM within the NetworkDatacenter.
* It can be directly accessed by Datacenter Broker which manages allocation of Cloudlets.
*
* @param vm
* @return true if the VW was created successfully, false otherwise
*/
public boolean processVmCreateNetwork(Vm vm) {
boolean result = getVmAllocationPolicy().allocateHostForVm(vm);
if (result) {
VmToSwitchid.put(vm.getId(), ((NetworkHost) vm.getHost()).sw.getId());
VmtoHostlist.put(vm.getId(), vm.getHost().getId());
System.out.println(vm.getId() + " VM is created on " + vm.getHost().getId());
getVmList().add(vm);
vm.updateVmProcessing(CloudSim.clock(), getVmAllocationPolicy().getHost(vm).getVmScheduler()
.getAllocatedMipsForVm(vm));
}
return result;
}
@Override
protected void processCloudletSubmit(SimEvent ev, boolean ack) {
updateCloudletProcessing();
try {
// gets the Cloudlet object
Cloudlet cl = (Cloudlet) ev.getData();
// checks whether this Cloudlet has finished or not
if (cl.isFinished()) {
String name = CloudSim.getEntityName(cl.getUserId());
Log.printConcatLine(getName(), ": Warning - Cloudlet #", cl.getCloudletId(), " owned by ", name,
" is already completed/finished.");
Log.printLine("Therefore, it is not being executed again");
Log.printLine();
// NOTE: If a Cloudlet has finished, then it won't be processed.
// So, if ack is required, this method sends back a result.
// If ack is not required, this method don't send back a result.
// Hence, this might cause CloudSim to be hanged since waiting
// for this Cloudlet back.
if (ack) {
int[] data = new int[3];
data[0] = getId();
data[1] = cl.getCloudletId();
data[2] = CloudSimTags.FALSE;
// unique tag = operation tag
int tag = CloudSimTags.CLOUDLET_SUBMIT_ACK;
sendNow(cl.getUserId(), tag, data);
}
sendNow(cl.getUserId(), CloudSimTags.CLOUDLET_RETURN, cl);
return;
}
// process this Cloudlet to this CloudResource
cl.setResourceParameter(getId(), getCharacteristics().getCostPerSecond(), getCharacteristics()
.getCostPerBw());
int userId = cl.getUserId();
int vmId = cl.getVmId();
// time to transfer the files
double fileTransferTime = predictFileTransferTime(cl.getRequiredFiles());
Host host = getVmAllocationPolicy().getHost(vmId, userId);
Vm vm = host.getVm(vmId, userId);
CloudletScheduler scheduler = vm.getCloudletScheduler();
double estimatedFinishTime = scheduler.cloudletSubmit(cl, fileTransferTime);
if (estimatedFinishTime > 0.0) { // if this cloudlet is in the exec
// time to process the cloudlet
estimatedFinishTime += fileTransferTime;
send(getId(), estimatedFinishTime, CloudSimTags.VM_DATACENTER_EVENT);
// event to update the stages
send(getId(), 0.0001, CloudSimTags.VM_DATACENTER_EVENT);
}
if (ack) {
int[] data = new int[3];
data[0] = getId();
data[1] = cl.getCloudletId();
data[2] = CloudSimTags.TRUE;
// unique tag = operation tag
int tag = CloudSimTags.CLOUDLET_SUBMIT_ACK;
sendNow(cl.getUserId(), tag, data);
}
} catch (ClassCastException c) {
Log.printLine(getName() + ".processCloudletSubmit(): " + "ClassCastException error.");
c.printStackTrace();
} catch (Exception e) {
Log.printLine(getName() + ".processCloudletSubmit(): " + "Exception error.");
e.printStackTrace();
}
checkCloudletCompletion();
}
}